diff --git a/package-lock.json b/package-lock.json
index 5a6faba..38d2308 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -15,6 +15,7 @@
"bootstrap-icons": "^1.6.0",
"date-fns": "^2.25.0",
"pinia": "^2.0.0-rc.13",
+ "pinia-plugin-persist": "^0.0.92",
"vue": "^3.2.20",
"vue-router": "^4.0.12",
"vue-tsc": "^0.3.0"
@@ -1125,6 +1126,48 @@
}
}
},
+ "node_modules/pinia-plugin-persist": {
+ "version": "0.0.92",
+ "resolved": "https://registry.npmjs.org/pinia-plugin-persist/-/pinia-plugin-persist-0.0.92.tgz",
+ "integrity": "sha512-eBNv1mqWwtiRPg4lraHuhXTqsPt51tRT2yaukW8+Gj9NIbLuPKS/VhnwmTF46WpIMJ0OP5xC4cwz9JOKJGX3GQ==",
+ "dependencies": {
+ "vue-demi": "^0.11.4"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0",
+ "vue": "^2.0.0 || >=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pinia-plugin-persist/node_modules/vue-demi": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.11.4.tgz",
+ "integrity": "sha512-/3xFwzSykLW2HiiLie43a+FFgNOcokbBJ+fzvFXd0r2T8MYohqvphUyDQ8lbAwzQ3Dlcrb1c9ykifGkhSIAk6A==",
+ "hasInstallScript": true,
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
"node_modules/pinia/node_modules/vue-demi": {
"version": "0.11.4",
"resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.11.4.tgz",
@@ -2478,6 +2521,22 @@
}
}
},
+ "pinia-plugin-persist": {
+ "version": "0.0.92",
+ "resolved": "https://registry.npmjs.org/pinia-plugin-persist/-/pinia-plugin-persist-0.0.92.tgz",
+ "integrity": "sha512-eBNv1mqWwtiRPg4lraHuhXTqsPt51tRT2yaukW8+Gj9NIbLuPKS/VhnwmTF46WpIMJ0OP5xC4cwz9JOKJGX3GQ==",
+ "requires": {
+ "vue-demi": "^0.11.4"
+ },
+ "dependencies": {
+ "vue-demi": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.11.4.tgz",
+ "integrity": "sha512-/3xFwzSykLW2HiiLie43a+FFgNOcokbBJ+fzvFXd0r2T8MYohqvphUyDQ8lbAwzQ3Dlcrb1c9ykifGkhSIAk6A==",
+ "requires": {}
+ }
+ }
+ },
"postcss": {
"version": "8.3.9",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.3.9.tgz",
diff --git a/package.json b/package.json
index 5594e6e..acd3e2e 100644
--- a/package.json
+++ b/package.json
@@ -14,6 +14,7 @@
"bootstrap-icons": "^1.6.0",
"date-fns": "^2.25.0",
"pinia": "^2.0.0-rc.13",
+ "pinia-plugin-persist": "^0.0.92",
"vue": "^3.2.20",
"vue-router": "^4.0.12",
"vue-tsc": "^0.3.0"
diff --git a/src/App.vue b/src/App.vue
index 4bed711..9004aca 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -4,9 +4,10 @@
@@ -18,6 +19,18 @@
diff --git a/src/components/HelloWorld.vue b/src/components/HelloWorld.vue
deleted file mode 100644
index 2d61249..0000000
--- a/src/components/HelloWorld.vue
+++ /dev/null
@@ -1,52 +0,0 @@
-
-
-
- {{ msg }}
-
-
- Recommended IDE setup:
- VSCode
- +
- Volar
-
-
- See README.md for more information.
-
-
-
- Vite Docs
-
- |
- Vue 3 Docs
-
-
-
-
- Edit
- components/HelloWorld.vue to test hot module replacement.
-
-
-
-
diff --git a/src/main.ts b/src/main.ts
index 7c492c0..47e8432 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -1,5 +1,6 @@
import { createApp } from 'vue'
import { createPinia } from 'pinia'
+import piniaPersist from 'pinia-plugin-persist'
import App from './App.vue'
import router from './router'
import Oruga from '@oruga-ui/oruga-next'
@@ -8,8 +9,11 @@ import 'bootstrap'
import "bootstrap/scss/bootstrap.scss"
import "bootstrap-icons/font/bootstrap-icons.css"
+const pinia = createPinia()
+pinia.use(piniaPersist)
+
createApp(App)
.use(router)
.use(Oruga)
-.use(createPinia())
+.use(pinia)
.mount('#app')
diff --git a/src/router/index.ts b/src/router/index.ts
index 5add4c3..a10df9e 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -1,17 +1,29 @@
import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'
-import Home from '../views/Home.vue'
-import Login from '../views/Login.vue'
+import { useUser } from '@/stores/user'
const routes: Array = [
{
path: '/',
name: 'Home',
- component: Home
+ component: () => import('@/views/Home.vue'),
+ meta: {
+ requiresAuth: true,
+ requiresAdmin: false
+ }
},
{
path: '/login',
name: 'Login',
- component: Login
+ component: () => import('@/views/Login.vue'),
+ meta: {
+ requiresAuth: false,
+ requiresAdmin: false
+ }
+ },
+ {
+ path: '/:pathMatch(.*)*/',
+ name: 'not-found',
+ redirect: '/login'
}
]
@@ -20,4 +32,9 @@ const router = createRouter({
routes
})
+router.beforeEach((to, from) => {
+ if (to.meta.requiresAuth && !useUser().isLoggedIn) return '/login'
+ if (to.meta.requiresAdmin && !useUser().isAdmin) return false
+})
+
export default router
diff --git a/src/stores/user.ts b/src/stores/user.ts
index 736e419..d47d866 100644
--- a/src/stores/user.ts
+++ b/src/stores/user.ts
@@ -10,7 +10,8 @@ type AuthSuccResult = {
text: string
}
user: string,
- role: string
+ role: string,
+ token: string
}
type AuthErrResult = {
@@ -20,17 +21,34 @@ type AuthErrResult = {
}
}
-export const useUser = defineStore('userStore', {
+
+
+export const useUser = defineStore({
+ id: 'storeUser',
+
state: () => {
return {
user: '',
role: '',
- isLoggedIn: false
+ isLoggedIn: false,
+ rememberMe: false,
+ token: ''
+ }
+ },
+
+ getters: {
+ isAdmin: (state) => state.role === 'admin',
+
+ preferredStorage: (state) => {
+ return localStorage
+ /* if (state.rememberMe) return localStorage
+ else return sessionStorage */
}
},
actions: {
- async login(username: string, password: string) : Promise {
+ async login(username: string, password: string, rememberMe: boolean): Promise {
+
const { notifications } = storeToRefs(useNotifications())
try {
@@ -38,10 +56,13 @@ export const useUser = defineStore('userStore', {
username: username,
password: password
})
+
+ console.log(response)
this.isLoggedIn = true
this.user = response.data.user
this.role = response.data.role
+ this.token = response.data.token
notifications.value.push({
type: response.data.notification.type,
@@ -67,6 +88,54 @@ export const useUser = defineStore('userStore', {
return false
}
+ },
+
+ async logout(): Promise {
+
+ const { notifications } = storeToRefs(useNotifications())
+
+ try {
+ const ai = axios.create({
+ baseURL: 'http://localhost:3333/api/v1/',
+ headers: {
+ 'Authorization': 'Bearer '+this.token
+ }
+
+ })
+ await ai.post('/logout')
+
+ notifications.value.push({
+ type: 'success',
+ text: 'Logged out successfully',
+ randomKey: getUnixTime(new Date()).toString()
+ })
+
+ this.$reset()
+
+ return true
+ }
+ catch(error) {
+ if(error instanceof Error) {
+ const notification = {
+ type: 'danger',
+ text: error.message,
+ randomKey: getUnixTime(new Date()).toString()
+ /**TODO #19 Generate randomKey in notification-store! */
+ }
+
+ notifications.value.push(notification)
+ }
+ return false
+ }
}
+ },
+
+ persist: {
+ enabled: true,
+ strategies: [
+ {
+ storage: localStorage
+ }
+ ]
}
})
\ No newline at end of file
diff --git a/src/views/Login.vue b/src/views/Login.vue
index c838aea..91f3c02 100644
--- a/src/views/Login.vue
+++ b/src/views/Login.vue
@@ -1,7 +1,4 @@
-
-
-