Add middleware and guards

This commit is contained in:
Christian Cueni 2022-04-21 14:23:52 +02:00
parent 7b976a0097
commit 14965aa60b
7 changed files with 105 additions and 22 deletions

View File

@ -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';
// }

View File

@ -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

View File

@ -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++
}
}
})

19
client/src/stores/user.ts Normal file
View File

@ -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
}
}
})

View File

@ -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 {

View File

@ -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

View File

@ -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