diff --git a/package.json b/package.json index 8515f41..29bdbc9 100644 --- a/package.json +++ b/package.json @@ -14,6 +14,7 @@ "axios": "^0.21.1", "cordova": "^10.0.0", "core-js": "^3.7.0", + "pinia": "^2.0.0-alpha.7", "quasar": "^2.0.0-beta.9" }, "prettier": { diff --git a/quasar.conf.js b/quasar.conf.js index ef6bb05..4fe8d42 100644 --- a/quasar.conf.js +++ b/quasar.conf.js @@ -30,7 +30,7 @@ module.exports = configure(function (/* ctx */) { // app boot file (/src/boot) // --> boot files are part of "main.js" // https://quasar.dev/quasar-cli/boot-files - boot: ['axios', 'plugins', 'loading', 'login'], + boot: ['axios', 'store', 'plugins', 'loading', 'login'], // https://quasar.dev/quasar-cli/quasar-conf-js#Property%3A-css css: ['app.scss'], diff --git a/src/boot/axios.ts b/src/boot/axios.ts index 916a863..c7f23f1 100644 --- a/src/boot/axios.ts +++ b/src/boot/axios.ts @@ -1,27 +1,21 @@ import config from 'src/config'; import { boot } from 'quasar/wrappers'; import { LocalStorage, Notify } from 'quasar'; -import axios, { AxiosError, AxiosInstance } from 'axios'; -import { UserSessionState } from 'src/plugins/user/store'; +import axios, { AxiosError } from 'axios'; +import { useMainStore } from 'src/store'; -declare module '@vue/runtime-core' { - interface ComponentCustomProperties { - $axios: AxiosInstance; - } -} +const api = axios.create(); -const api = axios.create({ - baseURL: LocalStorage.getItem('baseURL') || config.baseURL, -}); +export default boot(({ store, router }) => { + api.defaults.baseURL = LocalStorage.getItem('baseURL') || config.baseURL; -export default boot(({ app, store, router }) => { /*** * Intercept requests and insert Token if available */ api.interceptors.request.use((config) => { - const session = store.state.sessions.currentSession; - if (session?.token) { - config.headers = { Authorization: 'Bearer ' + session.token }; + const store = useMainStore(); + if (store.session?.token) { + config.headers = { Authorization: 'Bearer ' + store.session.token }; } return config; }); @@ -31,7 +25,7 @@ export default boot(({ app, store, router }) => { * - filter 401 --> logout * - filter timeout or 502-504 --> backendOffline */ - axios.interceptors.response.use( + api.interceptors.response.use( (response) => response, (error) => { if (error) { @@ -56,22 +50,13 @@ export default boot(({ app, store, router }) => { return Promise.reject(error); } ); - // for use inside Vue files (Options API) through this.$axios and this.$api - - app.config.globalProperties.$axios = axios; - // ^ ^ ^ this will allow you to use this.$axios (for Vue Options API form) - // so you won't necessarily have to import axios in each vue file - - app.config.globalProperties.$api = api; - // ^ ^ ^ this will allow you to use this.$api (for Vue Options API form) - // so you can easily perform requests against your app's API }); -export { axios, api }; +export { api }; -export const setBaseUrl = (url: string) => { +export const setBaseURL = (url: string) => { LocalStorage.set('baseURL', url); - axios.defaults.baseURL = url; + api.defaults.baseURL = url; Notify.create({ message: 'Serveraddresse gespeichert', position: 'bottom', diff --git a/src/boot/login.ts b/src/boot/login.ts index d4b0bc3..da36ef3 100644 --- a/src/boot/login.ts +++ b/src/boot/login.ts @@ -1,10 +1,12 @@ import { boot } from 'quasar/wrappers'; -import { UserSessionState } from 'src/plugins/user/store'; +import { useMainStore } from 'src/store'; +import { hasPermissions } from 'src/utils/permission'; import { RouteRecord } from 'vue-router'; -export default boot(({ router, store }) => { +export default boot(({ router }) => { router.beforeEach((to, from, next) => { - const session = store.state.sessions.currentSession; + console.log(`from ${from.fullPath} to ${to.fullPath}`); + const store = useMainStore(); if (to.path == from.path) { return; @@ -13,10 +15,9 @@ export default boot(({ router, store }) => { if (to.path.startsWith('/main')) { // Secured area (LOGIN REQUIRED) // Check login is ok - if (!session || session.expires <= new Date()) { - store.dispatch('sessions/logout').catch((error) => { - console.warn(error); - }); + if (!store.session || store.session.expires <= new Date()) { + console.log('Nope, logout'); + void store.logout(); return; } @@ -24,27 +25,28 @@ export default boot(({ router, store }) => { if ( to.matched.every((record: RouteRecord) => { if (!('meta' in record) || !('permissions' in record.meta)) return true; - if (record.meta) { - if ((<{ permissions: FG.Permission[] }>record.meta).permissions) { - return (<{ permissions: FG.Permission[] }>record.meta).permissions.every( - (permission: string) => { - return store.state.users.currentPermissions.includes(permission); - } - ); - } + if ((<{ permissions: FG.Permission[] }>record.meta).permissions) { + console.log(record.meta); + const h = hasPermissions((<{ permissions: FG.Permission[] }>record.meta).permissions); + console.log(h); + return h; } }) ) { + console.log('ok next'); next(); } else { + console.log('Back loggin'); next({ name: 'login', query: { redirect: to.fullPath } }); } } else { - if (to.name == 'login' && store.state.users.currentUser && !to.params['logout']) { + if (to.name == 'login' && store.user && !to.params['logout']) { // Called login while already logged in + console.log('Ok next'); void next({ name: 'dashboard' }); } else { // We are on the non secured area + console.log('Ok non sec'); next(); } } diff --git a/src/boot/notify.ts b/src/boot/notify.ts deleted file mode 100644 index 28f7609..0000000 --- a/src/boot/notify.ts +++ /dev/null @@ -1,14 +0,0 @@ -import { boot } from 'quasar/wrappers'; -import { Notify } from 'quasar'; - -// "async" is optional; -// more info on params: https://quasar.dev/quasar-cli/boot-files -export default boot(() => { - Notify.registerType('error', { - color: 'negative', - icon: 'mdi-alert-circle', - progress: true, - position: 'bottom', - actions: [{ icon: 'mdi-close', color: 'white' }], - }); -}); diff --git a/src/boot/plugins.ts b/src/boot/plugins.ts index 4ecc362..6a91fde 100644 --- a/src/boot/plugins.ts +++ b/src/boot/plugins.ts @@ -5,7 +5,6 @@ import routes from 'src/router/routes'; import { api } from 'boot/axios'; import { AxiosResponse } from 'axios'; import { Router, RouteRecordRaw } from 'vue-router'; -import { UserSessionState } from 'src/plugins/user/store'; const config: { [key: string]: Array } = { // Do not change required Modules !! @@ -160,7 +159,7 @@ function loadPlugin( modules: string[], backendpromise: Promise, plugins: FG_Plugin.Plugin[], - store: Store, + store: Store, router: Router ): FG_Plugin.Flaschengeist { modules.forEach((requiredModule) => { @@ -218,7 +217,7 @@ async function getBackend(): Promise { // "async" is optional; // more info on params: https://quasar.dev/quasar-cli/cli-documentation/boot-files#Anatomy-of-a-boot-file -export default boot(({ router, store, app }) => { +export default boot(({ router, app, store }) => { const plugins: FG_Plugin.Plugin[] = []; const backendPromise = getBackend(); diff --git a/src/boot/store.ts b/src/boot/store.ts new file mode 100644 index 0000000..9ffce59 --- /dev/null +++ b/src/boot/store.ts @@ -0,0 +1,10 @@ +import { createPinia } from 'pinia'; +import { boot } from 'quasar/wrappers'; +import { useMainStore } from 'src/store'; + +export default boot(({ app }) => { + app.use(createPinia()); + + const store = useMainStore(); + void store.init(); +}); diff --git a/src/components/navigation/EssentialLink.vue b/src/components/navigation/EssentialLink.vue index afc36ce..0a2e95d 100644 --- a/src/components/navigation/EssentialLink.vue +++ b/src/components/navigation/EssentialLink.vue @@ -5,7 +5,7 @@ - {{ realTitle }} + {{ title }} @@ -14,7 +14,6 @@ diff --git a/src/flaschengeist.d.ts b/src/flaschengeist.d.ts index 694df70..789c85a 100644 --- a/src/flaschengeist.d.ts +++ b/src/flaschengeist.d.ts @@ -13,10 +13,10 @@ declare namespace FG { firstname: string; lastname: string; mail: string; - birthday?: any; + birthday?: Date; roles: Array; - permissions?: any; - avatar_url?: any; + permissions?: Array; + avatar_url?: string; } type Permission = string; interface Role { @@ -29,51 +29,16 @@ declare namespace FG { time: Date; amount: number; reversal_id: number; - sender_id?: any; - receiver_id?: any; - author_id?: any; - original_id?: any; - } - interface Drink { - id: number; - name: string; - volume: number; - cost_price: number; - discount: number; - extra_charge?: any; - prices: Array; - ingredients: Array; - tags: Array; - } - interface DrinkPrice { - id: number; - volume: number; - price: number; - no_auto: boolean; - public: boolean; - description?: any; - round_step: number; - } - interface DrinkType { - id: number; - name: string; - } - interface Ingredient { - id: number; - volume: number; - drink_parent_id: number; - drink_ingredient_id: number; - drink_ingredient?: any; - } - interface Tag { - id: number; - name: string; + sender_id?: string; + receiver_id?: string; + author_id?: string; + original_id?: number; } interface Event { id: number; start: Date; end: Date; - description?: any; + description?: string; type: EventType; jobs: Array; } @@ -84,7 +49,7 @@ declare namespace FG { interface Job { id: number; start: Date; - end?: any; + end?: Date; comment: string; type: JobType; services: Array; diff --git a/src/layouts/MainLayout.vue b/src/layouts/MainLayout.vue index 0eda61e..e40126c 100644 --- a/src/layouts/MainLayout.vue +++ b/src/layouts/MainLayout.vue @@ -48,7 +48,7 @@ import EssentialLink from 'components/navigation/EssentialLink.vue'; import ShortCutLink from 'components/navigation/ShortCutLink.vue'; -import { Screen, Loading } from 'quasar'; +import { Screen } from 'quasar'; import { defineComponent, ref, inject, computed } from 'vue'; +import { useMainStore } from 'src/store'; import { FG_Plugin } from 'src/plugins'; import { useRoute } from 'vue-router'; -import { useStore } from 'vuex'; const links = [ { @@ -136,7 +136,7 @@ export default defineComponent({ components: { EssentialLink, ShortCutLink }, setup() { const route = useRoute(); - const store = useStore(); + const mainStore = useMainStore(); const flaschengeist = inject('flaschengeist'); const leftDrawer = ref(false); @@ -171,10 +171,7 @@ export default defineComponent({ }); function logout() { - Loading.show({ message: 'Session wird abgemeldet' }); - store.dispatch('sessions/logout').finally(() => { - Loading.hide(); - }); + void mainStore.logout(); } return { diff --git a/src/pages/Login.vue b/src/pages/Login.vue index 22a59f1..1b1dfc0 100644 --- a/src/pages/Login.vue +++ b/src/pages/Login.vue @@ -54,19 +54,19 @@