From f7e22c8c56d7dc35258aa45db1c91d8a9e70ec4a Mon Sep 17 00:00:00 2001 From: kolaente Date: Thu, 24 Aug 2023 12:15:45 +0200 Subject: [PATCH] fix(auth): correctly redirect the user to the last visited page after login Resolves https://kolaente.dev/vikunja/frontend/issues/3682 --- cypress/e2e/user/login.spec.ts | 38 +++++++++++++++++++++++----------- src/helpers/saveLastVisited.ts | 8 +++++-- src/router/index.ts | 26 +++++++++++++---------- 3 files changed, 47 insertions(+), 25 deletions(-) diff --git a/cypress/e2e/user/login.spec.ts b/cypress/e2e/user/login.spec.ts index 7ba127063..c19b9398b 100644 --- a/cypress/e2e/user/login.spec.ts +++ b/cypress/e2e/user/login.spec.ts @@ -1,4 +1,5 @@ import {UserFactory} from '../../factories/user' +import {ProjectFactory} from '../../factories/project' const testAndAssertFailed = fixture => { cy.intercept(Cypress.env('API_URL') + '/login*').as('login') @@ -13,26 +14,28 @@ const testAndAssertFailed = fixture => { cy.get('div.message.danger').contains('Wrong username or password.') } -const username = 'test' +const credentials = { + username: 'test', + password: '1234', +} + +function login() { + cy.get('input[id=username]').type(credentials.username) + cy.get('input[id=password]').type(credentials.password) + cy.get('.button').contains('Login').click() + cy.url().should('include', '/') +} context('Login', () => { beforeEach(() => { - UserFactory.create(1, {username}) + UserFactory.create(1, {username: credentials.username}) }) it('Should log in with the right credentials', () => { - const fixture = { - username: 'test', - password: '1234', - } - cy.visit('/login') - cy.get('input[id=username]').type(fixture.username) - cy.get('input[id=password]').type(fixture.password) - cy.get('.button').contains('Login').click() - cy.url().should('include', '/') + login() cy.clock(1625656161057) // 13:00 - cy.get('h2').should('contain', `Hi ${fixture.username}!`) + cy.get('h2').should('contain', `Hi ${credentials.username}!`) }) it('Should fail with a bad password', () => { @@ -57,4 +60,15 @@ context('Login', () => { cy.visit('/') cy.url().should('include', '/login') }) + + it('Should redirect to the previous route after logging in', () => { + const projects = ProjectFactory.create(1) + cy.visit(`/projects/${projects[0].id}/list`) + + cy.url().should('include', '/login') + + login() + + cy.url().should('include', `/projects/${projects[0].id}/list`) + }) }) diff --git a/src/helpers/saveLastVisited.ts b/src/helpers/saveLastVisited.ts index a7043ce93..98a32174f 100644 --- a/src/helpers/saveLastVisited.ts +++ b/src/helpers/saveLastVisited.ts @@ -1,6 +1,10 @@ const LAST_VISITED_KEY = 'lastVisited' -export const saveLastVisited = (name: string, params: object, query: object) => { +export const saveLastVisited = (name: string | undefined, params: object, query: object) => { + if (typeof name === 'undefined') { + return + } + localStorage.setItem(LAST_VISITED_KEY, JSON.stringify({name, params, query})) } @@ -9,7 +13,7 @@ export const getLastVisited = () => { if (lastVisited === null) { return null } - + return JSON.parse(lastVisited) } diff --git a/src/router/index.ts b/src/router/index.ts index 6caa65743..3aaa786e9 100644 --- a/src/router/index.ts +++ b/src/router/index.ts @@ -448,16 +448,9 @@ export async function getAuthForRoute(to: RouteLocation, authStore) { return } - const baseStore = useBaseStore() - // When trying this before the current user was fully loaded we might get a flash of the login screen - // in the user shell. To make shure this does not happen we check if everything is ready before trying. - if (!baseStore.ready) { - return - } - - // Check if the user is already logged in and redirect them to the home page if not - if ( - ![ + // Check if the route the user wants to go to is a route which needs authentication. We use this to + // redirect the user after successful login. + const isValidUserAppRoute = ![ 'user.login', 'user.password-reset.request', 'user.password-reset.reset', @@ -468,8 +461,19 @@ export async function getAuthForRoute(to: RouteLocation, authStore) { localStorage.getItem('passwordResetToken') === null && localStorage.getItem('emailConfirmToken') === null && !(to.name === 'home' && (typeof to.query.userPasswordReset !== 'undefined' || typeof to.query.userEmailConfirm !== 'undefined')) - ) { + + if (isValidUserAppRoute) { saveLastVisited(to.name as string, to.params, to.query) + } + + const baseStore = useBaseStore() + // When trying this before the current user was fully loaded we might get a flash of the login screen + // in the user shell. To make sure this does not happen we check if everything is ready before trying. + if (!baseStore.ready) { + return + } + + if (isValidUserAppRoute) { return {name: 'user.login'} }