diff --git a/frontend/src/App.vue b/frontend/src/App.vue index 1cd28402..26391e07 100644 --- a/frontend/src/App.vue +++ b/frontend/src/App.vue @@ -353,9 +353,7 @@ export default { this.handleLogout(); } } catch (error) { - this.isAuthenticated = false; - this.username = ''; - this.currentClub = ''; + this.logout(); } }, diff --git a/frontend/src/router.js b/frontend/src/router.js index dcb9a80c..02fc5e3e 100644 --- a/frontend/src/router.js +++ b/frontend/src/router.js @@ -27,14 +27,15 @@ import PersonalSettings from './views/PersonalSettings.vue'; import Impressum from './views/Impressum.vue'; import Datenschutz from './views/Datenschutz.vue'; import { applySeoForPath } from './utils/seo.js'; +import { safeSessionStorage } from './utils/storage.js'; const routes = [ - { path: '/register', name: 'register', component: Register }, - { path: '/login', name: 'login', component: Login }, - { path: '/activate/:activationCode', name: 'activate', component: Activate }, - { path: '/forgot-password', name: 'forgot-password', component: ForgotPassword }, - { path: '/reset-password/:token', name: 'reset-password', component: ResetPassword }, - { path: '/', name: 'home', component: Home }, + { path: '/register', name: 'register', component: Register, meta: { public: true } }, + { path: '/login', name: 'login', component: Login, meta: { public: true } }, + { path: '/activate/:activationCode', name: 'activate', component: Activate, meta: { public: true } }, + { path: '/forgot-password', name: 'forgot-password', component: ForgotPassword, meta: { public: true } }, + { path: '/reset-password/:token', name: 'reset-password', component: ResetPassword, meta: { public: true } }, + { path: '/', name: 'home', component: Home, meta: { public: true } }, { path: '/createclub', name: 'create-club', component: CreateClub }, { path: '/showclub/:clubId', name: 'show-club', component: ClubView }, { path: '/members', name: 'members', component: MembersView }, @@ -54,8 +55,8 @@ const routes = [ { path: '/clicktt', name: 'clicktt', component: ClickTtView }, { path: '/member-transfer-settings', name: 'member-transfer-settings', component: MemberTransferSettingsView }, { path: '/personal-settings', name: 'personal-settings', component: PersonalSettings }, - { path: '/impressum', name: 'impressum', component: Impressum }, - { path: '/datenschutz', name: 'datenschutz', component: Datenschutz }, + { path: '/impressum', name: 'impressum', component: Impressum, meta: { public: true } }, + { path: '/datenschutz', name: 'datenschutz', component: Datenschutz, meta: { public: true } }, ]; const router = createRouter({ @@ -63,6 +64,26 @@ const router = createRouter({ routes, }); +router.beforeEach((to, from, next) => { + const isAuthenticated = Boolean(safeSessionStorage.getItem('token')); + const isPublicRoute = to.matched.some((record) => record.meta?.public); + + if (!isAuthenticated && !isPublicRoute) { + next({ + path: '/login', + query: to.fullPath && to.fullPath !== '/' ? { redirect: to.fullPath } : {} + }); + return; + } + + if (isAuthenticated && (to.path === '/login' || to.path === '/register')) { + next('/'); + return; + } + + next(); +}); + router.afterEach((to) => { applySeoForPath(to.path); }); diff --git a/frontend/src/views/Login.vue b/frontend/src/views/Login.vue index 69a432f1..98c6089b 100644 --- a/frontend/src/views/Login.vue +++ b/frontend/src/views/Login.vue @@ -105,7 +105,8 @@ export default { timeout: 5000, }); await this.login({ token: response.data.token, username: this.email }); - this.$router.push('/'); + const redirectTarget = typeof this.$route.query.redirect === 'string' ? this.$route.query.redirect : '/'; + this.$router.push(redirectTarget); } catch (error) { const message = safeErrorMessage(error, this.$t('auth.loginFailed')); await this.showInfo(this.$t('messages.error'), message, '', 'error');