Set up Store, Service & Routing to handle the sign in process

This commit is contained in:
Bubka
2023-09-27 10:44:54 +02:00
parent 1d51cb3e31
commit 48bea5721f
10 changed files with 685 additions and 46 deletions

View File

@ -1,11 +1,11 @@
import '/resources/js_vue3/assets/app.scss';
import { createApp } from 'vue'
import { i18nVue } from 'laravel-vue-i18n'
import { createPinia } from 'pinia'
// import { createApp } from 'vue'
// import { i18nVue } from 'laravel-vue-i18n'
// import { createPinia } from 'pinia'
import Notifications from '@kyvg/vue3-notification'
import App from './App.vue'
import router from './router'
import Notifications from '@kyvg/vue3-notification'
import FontAwesomeIcon from './icons'
const app = createApp(App)

View File

@ -1,28 +0,0 @@
import { createRouter, createWebHistory } from 'vue-router'
import Accounts from './views/Accounts.vue'
import SettingsOptions from './views/settings/Options.vue'
// import SettingsAccount from './views/settings/Account'
// import SettingsOAuth from './views/settings/OAuth'
// import SettingsWebAuthn from './views/settings/WebAuthn'
// import EditCredential from './views/settings/Credentials/Edit'
// import GeneratePAT from './views/settings/PATokens/Create'
const router = createRouter({
history: createWebHistory('/'),
routes: [
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { requiresAuth: true }, alias: '/', props: true },
{ path: '/settings/options', name: 'settings.options', component: SettingsOptions, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/account', name: 'settings.account', component: SettingsAccount, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/oauth', name: 'settings.oauth.tokens', component: SettingsOAuth, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/oauth/pat/create', name: 'settings.oauth.generatePAT', component: GeneratePAT, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/webauthn/:credentialId/edit', name: 'settings.webauthn.editCredential', component: EditCredential, meta: { requiresAuth: true, showAbout: true }, props: true },
// { path: '/settings/webauthn', name: 'settings.webauthn.devices', component: SettingsWebAuthn, meta: { requiresAuth: true, showAbout: true } },
// Lazy loaded view
{ path: '/about', name: 'about', component: () => import('./views/About.vue') }
]
})
export default router

90
resources/js_vue3/router/index.js vendored Normal file
View File

@ -0,0 +1,90 @@
import { createRouter, createWebHistory } from 'vue-router'
import middlewarePipeline from "@/router/middlewarePipeline";
import { useUserStore } from '@/stores/user'
// import Start from './views/Start.vue'
// import Capture from './views/Capture.vue'
import Accounts from '../views/Accounts.vue'
// import CreateAccount from './views/twofaccounts/Create.vue'
// import EditAccount from './views/twofaccounts/Edit.vue'
// import ImportAccount from './views/twofaccounts/Import.vue'
// import QRcodeAccount from './views/twofaccounts/QRcode.vue'
// import Groups from './views/Groups.vue'
// import CreateGroup from './views/groups/Create.vue'
// import EditGroup from './views/groups/Edit.vue'
import Login from '../views/auth/Login.vue'
import Register from '../views/auth/Register.vue'
// import Autolock from './views/auth/Autolock.vue'
import PasswordRequest from '../views/auth/password/Request.vue'
// import PasswordReset from './views/auth/password/Reset.vue'
import WebauthnLost from '../views/auth/webauthn/Lost.vue'
// import WebauthnRecover from './views/auth/webauthn/Recover.vue'
import SettingsOptions from '../views/settings/Options.vue'
// import SettingsAccount from './views/settings/Account.vue'
// import SettingsOAuth from './views/settings/OAuth.vue'
// import SettingsWebAuthn from './views/settings/WebAuthn.vue'
// import EditCredential from './views/settings/Credentials/Edit.vue'
// import GeneratePAT from './views/settings/PATokens/Create.vue'
// import Errors from './views/Error.vue'
import About from '../views/About.vue'
import authGuard from './middlewares/authGuard'
const router = createRouter({
history: createWebHistory('/'),
routes: [
// { path: '/start', name: 'start', component: Start, meta: { requiresAuth: true }, props: true },
// { path: '/capture', name: 'capture', component: Capture, meta: { requiresAuth: true }, props: true },
{ path: '/accounts', name: 'accounts', component: Accounts, meta: { middlewares: [authGuard], requiresAuth: true }, alias: '/', props: true },
// { path: '/account/create', name: 'createAccount', component: CreateAccount, meta: { requiresAuth: true } },
// { path: '/account/import', name: 'importAccounts', component: ImportAccount, meta: { requiresAuth: true } },
// { path: '/account/:twofaccountId/edit', name: 'editAccount', component: EditAccount, meta: { requiresAuth: true } },
// { path: '/account/:twofaccountId/qrcode', name: 'showQRcode', component: QRcodeAccount, meta: { requiresAuth: true } },
// { path: '/groups', name: 'groups', component: Groups, meta: { requiresAuth: true }, props: true },
// { path: '/group/create', name: 'createGroup', component: CreateGroup, meta: { requiresAuth: true } },
// { path: '/group/:groupId/edit', name: 'editGroup', component: EditGroup, meta: { requiresAuth: true }, props: true },
{ path: '/settings/options', name: 'settings.options', component: SettingsOptions, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/account', name: 'settings.account', component: SettingsAccount, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/oauth', name: 'settings.oauth.tokens', component: SettingsOAuth, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/oauth/pat/create', name: 'settings.oauth.generatePAT', component: GeneratePAT, meta: { requiresAuth: true, showAbout: true } },
// { path: '/settings/webauthn/:credentialId/edit', name: 'settings.webauthn.editCredential', component: EditCredential, meta: { requiresAuth: true, showAbout: true }, props: true },
// { path: '/settings/webauthn', name: 'settings.webauthn.devices', component: SettingsWebAuthn, meta: { requiresAuth: true, showAbout: true } },
{ path: '/login', name: 'login', component: Login, meta: { disabledWithAuthProxy: true, showAbout: true } },
{ path: '/register', name: 'register', component: Register, meta: { disabledWithAuthProxy: true, showAbout: true } },
// { path: '/autolock', name: 'autolock',component: Autolock, meta: { disabledWithAuthProxy: true, showAbout: true } },
{ path: '/password/request', name: 'password.request', component: PasswordRequest, meta: { disabledWithAuthProxy: true, showAbout: true } },
// { path: '/user/password/reset', name: 'password.reset', component: PasswordReset, meta: { disabledWithAuthProxy: true, showAbout: true } },
{ path: '/webauthn/lost', name: 'webauthn.lost', component: WebauthnLost, meta: { disabledWithAuthProxy: true, showAbout: true } },
// { path: '/webauthn/recover', name: 'webauthn.recover', component: WebauthnRecover, meta: { disabledWithAuthProxy: true, showAbout: true } },
{ path: '/about', name: 'about',component: About, meta: { showAbout: true } },
// { path: '/error', name: 'genericError',component: Errors, props: true },
// { path: '/404', name: '404',component: Errors, props: true },
// { path: '*', redirect: { name: '404' } },
// Lazy loaded view
{ path: '/about', name: 'about', component: () => import('../views/About.vue') }
]
})
router.beforeEach((to, from, next) => {
const middlewares = to.meta.middlewares
const user = useUserStore()
const stores = { user: user }
const context = { to, from, next, stores }
if (!middlewares) {
return next();
}
middlewares[0]({
...context,
next: middlewarePipeline(context, middlewares, 1),
});
});
export default router

View File

@ -0,0 +1,12 @@
export default function middlewarePipeline(context, middleware, index) {
const nextMiddleware = middleware[index];
if (!nextMiddleware) {
return context.next;
}
return () => {
nextMiddleware({
...context,
next: middlewarePipeline(context, middleware, index + 1),
});
};
}

View File

@ -0,0 +1,24 @@
import authService from '@/services/authService'
export default async function auth({ to, next, stores }) {
const { user } = stores
// No authenticated user on the front-end side, we try to
// get an active user from the back-end side
if (! user.isAuthenticated) {
const currentUser = await authService.getCurrentUser()
if (currentUser) {
user.$patch({
name: currentUser.name,
preferences: currentUser.preferences,
isAdmin: currentUser.is_admin,
})
}
}
if (! user.isAuthenticated) {
next({ name: 'login' })
} else {
next()
}
}

View File

@ -0,0 +1,26 @@
import { httpClientFactory } from '@/services/httpClientFactory'
const webClient = httpClientFactory('web')
const apiClient = httpClientFactory('api')
export default {
/**
*
*/
logout() {
return webClient.get('/user/logout')
},
/**
*
*/
async getCurrentUser() {
try {
const { data } = await apiClient.get('/user')
return data
} catch (error) {
return null
}
},
}

View File

@ -1,22 +1,48 @@
import { defineStore } from 'pinia'
// import { useApi } from '@/api/useAPI.js'
// const api = useApi()
import authService from '@/services/authService'
import router from '@/router'
export const useUserStore = defineStore({
id: 'user',
id: 'user',
state: () => {
state: () => {
return {
name: 'guest',
preferences: window.userPreferences,
name: undefined,
preferences: window.defaultPreferences,
isAdmin: false,
}
},
actions: {
updatePreference(preference) {
this.preferences = { ...this.state.preferences, ...preference }
},
},
getters: {
isAuthenticated() {
return this.name != undefined
}
},
actions: {
updatePreference(preference) {
this.preferences = { ...this.state.preferences, ...preference }
},
logout() {
// async appLogout(evt) {
if (this.$2fauth.config.proxyAuth) {
if (this.$2fauth.config.proxyLogoutUrl) {
location.assign(this.$2fauth.config.proxyLogoutUrl)
}
else return false
}
else {
return authService.logout().then(() => {
localStorage.clear()
this.$reset()
router.push({ name: 'login' })
})
// this.$router.push({ name: 'login', params: { forceRefresh: true } })
}
// },
}
},
})