Add middleware and guards
This commit is contained in:
parent
7b976a0097
commit
14965aa60b
|
|
@ -0,0 +1,49 @@
|
||||||
|
import type {NavigationGuardWithThis, RouteLocationNormalized} from 'vue-router';
|
||||||
|
import { useUserStore } from '@/stores/user'
|
||||||
|
import type {Store} from 'pinia';
|
||||||
|
|
||||||
|
const cookieName = 'loginStatus'
|
||||||
|
let userStore: Store | null = null
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export const updateLoggedIn: NavigationGuardWithThis<undefined> = (_to) => {
|
||||||
|
const loggedIn = getCookieValue(cookieName) === 'true'
|
||||||
|
const store = getUserStore()
|
||||||
|
|
||||||
|
store.$patch({ loggedIn })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const redirectToLoginIfRequired: NavigationGuardWithThis<undefined> = (to, _from) => {
|
||||||
|
const store = getUserStore()
|
||||||
|
if(loginRequired(to) && !store.loggedIn) {
|
||||||
|
return { name: 'home' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCookieValue = (cookieName: string): string => {
|
||||||
|
// https://stackoverflow.com/questions/5639346/what-is-the-shortest-function-for-reading-a-cookie-by-name-in-javascript
|
||||||
|
const cookieValue = document.cookie.match('(^|[^;]+)\\s*' + cookieName + '\\s*=\\s*([^;]+)')
|
||||||
|
if (!cookieValue) {
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
return cookieValue.pop() || '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pina is not ready when router is called the first time by app.use(), so we need to load it here
|
||||||
|
const getUserStore = (): Store => {
|
||||||
|
if (!userStore) {
|
||||||
|
userStore = useUserStore()
|
||||||
|
}
|
||||||
|
return userStore
|
||||||
|
}
|
||||||
|
|
||||||
|
const loginRequired = (to: RouteLocationNormalized) => {
|
||||||
|
return !to.meta?.public
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// export const unauthorizedAccess: NavigationGuardWithThis<undefined> = (to) => {
|
||||||
|
// r loginRequired(to) && getCookieValue('loginStatus') !== 'true';
|
||||||
|
// }
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
import HomeView from '../views/HomeView.vue';
|
import HomeView from '../views/HomeView.vue';
|
||||||
import learningPathRoutes from './learningpath.routes'
|
import learningPathRoutes from './learningpath.routes'
|
||||||
|
import {redirectToLoginIfRequired, updateLoggedIn} from "@/router/guards";
|
||||||
|
|
||||||
|
const loginUrl = '/sso/login/'
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(import.meta.env.BASE_URL),
|
history: createWebHistory(import.meta.env.BASE_URL),
|
||||||
|
|
@ -10,15 +13,19 @@ const router = createRouter({
|
||||||
name: 'home',
|
name: 'home',
|
||||||
component: HomeView,
|
component: HomeView,
|
||||||
meta: {
|
meta: {
|
||||||
layout: 'NoNavbarDemoLayout'
|
layout: 'NoNavbarDemoLayout',
|
||||||
|
public: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
component: HomeView,
|
component: HomeView,
|
||||||
beforeEnter(to, from, next) {
|
beforeEnter(_to, _from) {
|
||||||
window.location.href = "/sso/login/";
|
window.location.href = loginUrl
|
||||||
},
|
},
|
||||||
|
meta: {
|
||||||
|
public: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/profile',
|
path: '/profile',
|
||||||
|
|
@ -32,4 +39,7 @@ const router = createRouter({
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
router.beforeEach(updateLoggedIn)
|
||||||
|
router.beforeEach(redirectToLoginIfRequired)
|
||||||
|
|
||||||
export default router
|
export default router
|
||||||
|
|
|
||||||
|
|
@ -1,16 +0,0 @@
|
||||||
import { defineStore } from 'pinia'
|
|
||||||
|
|
||||||
export const useCounterStore = defineStore({
|
|
||||||
id: 'counter',
|
|
||||||
state: () => ({
|
|
||||||
counter: 0
|
|
||||||
}),
|
|
||||||
getters: {
|
|
||||||
doubleCount: (state) => state.counter * 2
|
|
||||||
},
|
|
||||||
actions: {
|
|
||||||
increment() {
|
|
||||||
this.counter++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { defineStore } from 'pinia'
|
||||||
|
// typed state https://stackoverflow.com/questions/71012513/when-using-pinia-and-typescript-how-do-you-use-an-action-to-set-the-state
|
||||||
|
export const useUserStore = defineStore({
|
||||||
|
id: 'user',
|
||||||
|
state: () => ({
|
||||||
|
email: '',
|
||||||
|
loggedIn: false
|
||||||
|
}),
|
||||||
|
getters: {
|
||||||
|
},
|
||||||
|
actions: {
|
||||||
|
setEmail (email: string) {
|
||||||
|
this.email = email
|
||||||
|
},
|
||||||
|
setLoggedIn (isLoggedIn: boolean) {
|
||||||
|
this.loggedIn = isLoggedIn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
@ -12,9 +12,9 @@ export default {
|
||||||
setup () {
|
setup () {
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
const res = await getUserData();
|
// const res = await getUserData();
|
||||||
users.value = res.data;
|
// users.value = res.data;
|
||||||
console.log(res);
|
// console.log(res);
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
|
|
|
||||||
|
|
@ -153,6 +153,7 @@ MIDDLEWARE = [
|
||||||
"django_htmx.middleware.HtmxMiddleware",
|
"django_htmx.middleware.HtmxMiddleware",
|
||||||
"vbv_lernwelt.core.middleware.auth.AuthenticationRequiredMiddleware",
|
"vbv_lernwelt.core.middleware.auth.AuthenticationRequiredMiddleware",
|
||||||
"vbv_lernwelt.core.middleware.security.SecurityRequestResponseLoggingMiddleware",
|
"vbv_lernwelt.core.middleware.security.SecurityRequestResponseLoggingMiddleware",
|
||||||
|
"vbv_lernwelt.core.middleware.auth.UserLoggedInCookieMiddleWare",
|
||||||
]
|
]
|
||||||
|
|
||||||
# STATIC
|
# STATIC
|
||||||
|
|
|
||||||
|
|
@ -45,3 +45,23 @@ class DjangoViewAuthenticationExemptDRFViewSetMixin:
|
||||||
)
|
)
|
||||||
view.authentication_exempt = True
|
view.authentication_exempt = True
|
||||||
return view
|
return view
|
||||||
|
|
||||||
|
|
||||||
|
# https://stackoverflow.com/questions/4898408/how-to-set-a-login-cookie-in-django
|
||||||
|
class UserLoggedInCookieMiddleWare(MiddlewareMixin):
|
||||||
|
"""
|
||||||
|
Middleware to set user cookie
|
||||||
|
If user is authenticated and there is no cookie, set the cookie,
|
||||||
|
If the user is not authenticated and the cookie remains, delete it
|
||||||
|
"""
|
||||||
|
|
||||||
|
cookie_name = 'loginStatus'
|
||||||
|
|
||||||
|
def process_response(self, request, response):
|
||||||
|
# if user and no cookie, set cookie
|
||||||
|
if request.user.is_authenticated and not request.COOKIES.get(self.cookie_name):
|
||||||
|
response.set_cookie(self.cookie_name, 'true')
|
||||||
|
elif not request.user.is_authenticated and request.COOKIES.get(self.cookie_name):
|
||||||
|
# else if if no user and cookie remove user cookie, logout
|
||||||
|
response.delete_cookie(self.cookie_name)
|
||||||
|
return response
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue