diff --git a/client/src/pages/onboarding/vv/CheckoutAddress.vue b/client/src/pages/onboarding/vv/CheckoutAddress.vue index eb8b7b9d..357d3847 100644 --- a/client/src/pages/onboarding/vv/CheckoutAddress.vue +++ b/client/src/pages/onboarding/vv/CheckoutAddress.vue @@ -31,6 +31,10 @@ const route = useRoute(); const { organisations } = useEntities(); const userOrganisationName = computed(() => { + if (!user.organisation) { + return null; + } + // Those IDs do not represent a company // 1: Other broker // 2: Other insurance diff --git a/client/src/router/__tests__/onboarding.spec.ts b/client/src/router/__tests__/onboarding.spec.ts index ede9c6a4..db52734c 100644 --- a/client/src/router/__tests__/onboarding.spec.ts +++ b/client/src/router/__tests__/onboarding.spec.ts @@ -39,7 +39,7 @@ describe("Onboarding", () => { it("UK: redirect to profile next route for logged-in user with organisation", () => { const user = useUserStore(); user.loggedIn = true; - user.organisation = "1"; + user.organisation = 1; const mockNext = vi.fn(); onboardingRedirect(routeLocation("accountConfirm", "uk"), START_LOCATION, mockNext); expect(mockNext).toHaveBeenCalledWith({ @@ -51,7 +51,7 @@ describe("Onboarding", () => { it("VV: redirect to profile next route for logged-in user with organisation", () => { const user = useUserStore(); user.loggedIn = true; - user.organisation = "1"; + user.organisation = 1; const mockNext = vi.fn(); onboardingRedirect(routeLocation("accountConfirm", "vv"), START_LOCATION, mockNext); expect(mockNext).toHaveBeenCalledWith({ @@ -63,7 +63,7 @@ describe("Onboarding", () => { it("no redirect for logged-in user without organisation to accountConfirm", () => { const user = useUserStore(); user.loggedIn = true; - user.organisation = ""; + user.organisation = null; const mockNext = vi.fn(); onboardingRedirect(routeLocation("accountConfirm", "uk"), START_LOCATION, mockNext); expect(mockNext).toHaveBeenCalledWith(); // No arguments passed means no redirection diff --git a/client/src/router/guards.ts b/client/src/router/guards.ts index 72da59c8..854cf51a 100644 --- a/client/src/router/guards.ts +++ b/client/src/router/guards.ts @@ -12,10 +12,27 @@ export const updateLoggedIn: NavigationGuard = async () => { } }; -export const redirectToStartIfRequired: NavigationGuard = (to) => { - const userStore = useUserStore(); - if (loginRequired(to) && !userStore.loggedIn) { - return "/start"; +export const redirectToLoginIfRequired: NavigationGuard = (to, from, next) => { + const user = useUserStore(); + + // redirect guests to /start if they access / + if (!user.loggedIn && to.path === "/") { + return next("/start"); + } + + if (loginRequired(to) && !user.loggedIn) { + const appEnv = import.meta.env.VITE_APP_ENVIRONMENT || "local"; + const ssoLogin = appEnv.startsWith("prod") || appEnv.startsWith("stage"); + if (ssoLogin) { + // Redirect to SSO login page, handled by the server + window.location.href = `/sso/login/?next=${encodeURIComponent(to.fullPath)}`; + } else { + // Handle local login with Vue router + next(`/login-local?next=${encodeURIComponent(to.fullPath)}`); + } + } else { + // If login is not required or user is already logged in, continue with the navigation + next(); } }; diff --git a/client/src/router/index.ts b/client/src/router/index.ts index ea4a490e..58712b3a 100644 --- a/client/src/router/index.ts +++ b/client/src/router/index.ts @@ -6,7 +6,7 @@ import DashboardPage from "@/pages/dashboard/DashboardPage.vue"; import { handleCourseSessionAsQueryParam, handleCurrentCourseSession, - redirectToStartIfRequired, + redirectToLoginIfRequired, updateLoggedIn, } from "@/router/guards"; import { addToHistory } from "@/router/history"; @@ -314,7 +314,7 @@ const router = createRouter({ }); router.beforeEach(updateLoggedIn); -router.beforeEach(redirectToStartIfRequired); +router.beforeEach(redirectToLoginIfRequired); // register after login hooks router.beforeEach(handleCurrentCourseSession); diff --git a/client/src/stores/user.ts b/client/src/stores/user.ts index 0806ef19..7951978b 100644 --- a/client/src/stores/user.ts +++ b/client/src/stores/user.ts @@ -25,7 +25,7 @@ export type UserState = { email: string; username: string; avatar_url: string; - organisation: number; + organisation: number | null; is_superuser: boolean; course_session_experts: string[]; loggedIn: boolean; diff --git a/cypress/e2e/login.cy.js b/cypress/e2e/login.cy.js index 1fdc3e2c..0f20f31a 100644 --- a/cypress/e2e/login.cy.js +++ b/cypress/e2e/login.cy.js @@ -11,36 +11,36 @@ describe("login.cy.js", () => { }); it("can login to app with username/password", () => { - cy.visit("/"); + cy.visit("/login-local"); cy.get("#username").type("test-student1@example.com"); cy.get("#password").type("test"); - cy.get('[data-cy="login-button"]').click(); + cy.get("[data-cy=\"login-button\"]").click(); cy.request("/api/core/me").its("status").should("eq", 200); - cy.get('[data-cy="dashboard-title"]').should("contain", "Dashboard"); + cy.get("[data-cy=\"dashboard-title\"]").should("contain", "Dashboard"); }); it("can login with helper function", () => { login("test-student1@example.com", "test"); cy.visit("/"); cy.request("/api/core/me").its("status").should("eq", 200); - cy.get('[data-cy="dashboard-title"]').should("contain", "Dashboard"); + cy.get("[data-cy=\"dashboard-title\"]").should("contain", "Dashboard"); }); - it("login will redirect to requestet page", () => { + it("login will redirect to requested page", () => { cy.visit("/course/test-lehrgang/learn"); cy.get("h1").should("contain", "Login"); cy.get("#username").type("test-student1@example.com"); cy.get("#password").type("test"); - cy.get('[data-cy="login-button"]').click(); + cy.get("[data-cy=\"login-button\"]").click(); - cy.get('[data-cy="learning-path-title"]').should( + cy.get("[data-cy=\"learning-path-title\"]").should( "contain", - "Test Lehrgang", + "Test Lehrgang" ); }); });