Add logout
This commit is contained in:
parent
6ec987110a
commit
38d5fc3369
|
|
@ -58,13 +58,17 @@ function handleDropdownSelect(data) {
|
||||||
router.push('/profile')
|
router.push('/profile')
|
||||||
break
|
break
|
||||||
case 'logout':
|
case 'logout':
|
||||||
router.push('/logout')
|
userStore.handleLogout();
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
console.log('no action')
|
console.log('no action')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function logout () {
|
||||||
|
userStore.handleLogout();
|
||||||
|
}
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
log.debug('MainNavigationBar mounted');
|
log.debug('MainNavigationBar mounted');
|
||||||
})
|
})
|
||||||
|
|
@ -96,7 +100,7 @@ const profileDropdownData = [
|
||||||
<div>
|
<div>
|
||||||
<Teleport to="body">
|
<Teleport to="body">
|
||||||
<MobileMenu
|
<MobileMenu
|
||||||
:user="userStore"
|
:user-store="userStore"
|
||||||
:show="state.showMenu"
|
:show="state.showMenu"
|
||||||
:learning-path-slug="learninPathSlug()"
|
:learning-path-slug="learninPathSlug()"
|
||||||
:learning-path-name="learningPathName()"
|
:learning-path-name="learningPathName()"
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ const router = useRouter()
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
show: boolean,
|
show: boolean,
|
||||||
user: object,
|
userStore: object,
|
||||||
learningPathName: string,
|
learningPathName: string,
|
||||||
learningPathSlug: string
|
learningPathSlug: string
|
||||||
}>()
|
}>()
|
||||||
|
|
@ -29,17 +29,19 @@ const clickLink = (to: string) => {
|
||||||
>
|
>
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<div class="border-b border-gray-500 -mx-4 px-8 pb-4">
|
<div
|
||||||
|
v-if="userStore.loggedIn"
|
||||||
|
class="border-b border-gray-500 -mx-4 px-8 pb-4">
|
||||||
<div class="-ml-4 flex">
|
<div class="-ml-4 flex">
|
||||||
<div
|
<div
|
||||||
v-if="user.avatar_url"
|
v-if="userStore.avatar_url"
|
||||||
>
|
>
|
||||||
<img class="inline-block h-16 w-16 rounded-full"
|
<img class="inline-block h-16 w-16 rounded-full"
|
||||||
:src="user.avatar_url"
|
:src="userStore.avatar_url"
|
||||||
alt=""/>
|
alt=""/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-6">
|
<div class="ml-6">
|
||||||
<h3>{{user.first_name}} {{user.last_name}}</h3>
|
<h3>{{userStore.first_name}} {{userStore.last_name}}</h3>
|
||||||
<button
|
<button
|
||||||
@click="clickLink('/profile')"
|
@click="clickLink('/profile')"
|
||||||
class="mt-2 inline-block flex items-center">
|
class="mt-2 inline-block flex items-center">
|
||||||
|
|
@ -64,9 +66,13 @@ const clickLink = (to: string) => {
|
||||||
<li class="mt-6">Mediathek</li>
|
<li class="mt-6">Mediathek</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-6 items-center flex">
|
<button
|
||||||
|
v-if="userStore.loggedIn"
|
||||||
|
type="button"
|
||||||
|
@click="userStore.handleLogout()"
|
||||||
|
class="mt-6 items-center flex">
|
||||||
<IconLogout class="inline-block" /><span class="ml-1">Abmelden</span>
|
<IconLogout class="inline-block" /><span class="ml-1">Abmelden</span>
|
||||||
</div>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,18 @@ export type UserState = {
|
||||||
loggedIn: boolean;
|
loggedIn: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUserStore = defineStore({
|
const initialUserState: UserState = {
|
||||||
id: 'user',
|
|
||||||
state: () => ({
|
|
||||||
email: '',
|
email: '',
|
||||||
first_name: '',
|
first_name: '',
|
||||||
last_name: '',
|
last_name: '',
|
||||||
username: '',
|
username: '',
|
||||||
avatar_url: '',
|
avatar_url: '',
|
||||||
loggedIn: false
|
loggedIn: false
|
||||||
} as UserState),
|
}
|
||||||
|
|
||||||
|
export const useUserStore = defineStore({
|
||||||
|
id: 'user',
|
||||||
|
state: () => (initialUserState as UserState),
|
||||||
getters: {
|
getters: {
|
||||||
getFullName(): string {
|
getFullName(): string {
|
||||||
return `${this.first_name} ${this.last_name}`.trim();
|
return `${this.first_name} ${this.last_name}`.trim();
|
||||||
|
|
@ -46,6 +48,13 @@ export const useUserStore = defineStore({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleLogout() {
|
||||||
|
itPost('/core/logout/', {})
|
||||||
|
.then(data => {
|
||||||
|
Object.assign(this, initialUserState);
|
||||||
|
window.location.href = '/';
|
||||||
|
})
|
||||||
|
},
|
||||||
fetchUser() {
|
fetchUser() {
|
||||||
const appStore = useAppStore();
|
const appStore = useAppStore();
|
||||||
itGet('/api/core/me/').then((data) => {
|
itGet('/api/core/me/').then((data) => {
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,7 @@ from vbv_lernwelt.core.middleware.auth import django_view_authentication_exempt
|
||||||
from vbv_lernwelt.core.views import (
|
from vbv_lernwelt.core.views import (
|
||||||
rate_limit_exceeded_view,
|
rate_limit_exceeded_view,
|
||||||
permission_denied_view,
|
permission_denied_view,
|
||||||
check_rate_limit, cypress_reset_view, vue_home, vue_login, me_user_view, )
|
check_rate_limit, cypress_reset_view, vue_home, vue_login, me_user_view, vue_logout, )
|
||||||
from .wagtail_api import wagtail_api_router
|
from .wagtail_api import wagtail_api_router
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -42,6 +42,7 @@ urlpatterns = [
|
||||||
path('learnpath/', include("vbv_lernwelt.learnpath.urls")),
|
path('learnpath/', include("vbv_lernwelt.learnpath.urls")),
|
||||||
path('api/completion/', include("vbv_lernwelt.completion.urls")),
|
path('api/completion/', include("vbv_lernwelt.completion.urls")),
|
||||||
re_path(r'api/core/me/$', me_user_view, name='me_user_view'),
|
re_path(r'api/core/me/$', me_user_view, name='me_user_view'),
|
||||||
|
re_path(r'core/logout/$', vue_logout, name='vue_logout'),
|
||||||
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
# Static file serving when using Gunicorn + Uvicorn for local web socket development
|
# Static file serving when using Gunicorn + Uvicorn for local web socket development
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import requests
|
import requests
|
||||||
import structlog
|
import structlog
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.contrib.auth import authenticate, login
|
from django.contrib.auth import authenticate, login, logout
|
||||||
from django.core.management import call_command
|
from django.core.management import call_command
|
||||||
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
|
from django.http import JsonResponse, HttpResponse, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
|
@ -69,6 +69,12 @@ def me_user_view(request):
|
||||||
return Response(status=403)
|
return Response(status=403)
|
||||||
|
|
||||||
|
|
||||||
|
@api_view(['POST'])
|
||||||
|
def vue_logout(request):
|
||||||
|
logout(request)
|
||||||
|
return Response({'success': True}, 200)
|
||||||
|
|
||||||
|
|
||||||
def permission_denied_view(request, exception):
|
def permission_denied_view(request, exception):
|
||||||
return render(request, "403.html", status=403)
|
return render(request, "403.html", status=403)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue