Prevent normal users from navigating to the cockpit
This commit is contained in:
parent
d1615954df
commit
58df3201d4
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { createPinia, setActivePinia } from "pinia";
|
||||||
|
import { beforeEach, describe, expect, vi } from "vitest";
|
||||||
|
import * as courseSessions from "../../stores/courseSessions";
|
||||||
|
import { expertRequired } from "../guards";
|
||||||
|
|
||||||
|
describe("Guards", () => {
|
||||||
|
afterEach(() => {
|
||||||
|
vi.restoreAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// creates a fresh pinia and make it active so it's automatically picked
|
||||||
|
// up by any useStore() call without having to pass it to it:
|
||||||
|
// `useStore(pinia)`
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
});
|
||||||
|
|
||||||
|
it("cannot route to cockpit", () => {
|
||||||
|
vi.spyOn(courseSessions, "useCourseSessionsStore").mockReturnValue({
|
||||||
|
hasCockpit: false,
|
||||||
|
});
|
||||||
|
const slug = "test";
|
||||||
|
expect(expertRequired({ params: { courseSlug: "test" } })).toEqual(
|
||||||
|
`/course/${slug}/learn`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("can route to cockpit", () => {
|
||||||
|
vi.spyOn(courseSessions, "useCourseSessionsStore").mockReturnValue({
|
||||||
|
hasCockpit: true,
|
||||||
|
});
|
||||||
|
const to = {
|
||||||
|
params: {
|
||||||
|
courseSlug: "test",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
expect(expertRequired(to)).toEqual(to);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { useCourseSessionsStore } from "@/stores/courseSessions";
|
||||||
import { useUserStore } from "@/stores/user";
|
import { useUserStore } from "@/stores/user";
|
||||||
import type { NavigationGuardWithThis, RouteLocationNormalized } from "vue-router";
|
import type { NavigationGuardWithThis, RouteLocationNormalized } from "vue-router";
|
||||||
|
|
||||||
|
|
@ -32,3 +33,13 @@ export const getCookieValue = (cookieName: string): string => {
|
||||||
const loginRequired = (to: RouteLocationNormalized) => {
|
const loginRequired = (to: RouteLocationNormalized) => {
|
||||||
return !to.meta?.public;
|
return !to.meta?.public;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const expertRequired = (to: RouteLocationNormalized) => {
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
if (courseSessionsStore.hasCockpit) {
|
||||||
|
return to;
|
||||||
|
} else {
|
||||||
|
const courseSlug = to.params.courseSlug as string;
|
||||||
|
return `/course/${courseSlug}/learn`;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,10 @@
|
||||||
import DashboardPage from "@/pages/DashboardPage.vue";
|
import DashboardPage from "@/pages/DashboardPage.vue";
|
||||||
import LoginPage from "@/pages/LoginPage.vue";
|
import LoginPage from "@/pages/LoginPage.vue";
|
||||||
import { redirectToLoginIfRequired, updateLoggedIn } from "@/router/guards";
|
import {
|
||||||
|
expertRequired,
|
||||||
|
redirectToLoginIfRequired,
|
||||||
|
updateLoggedIn,
|
||||||
|
} from "@/router/guards";
|
||||||
import { useAppStore } from "@/stores/app";
|
import { useAppStore } from "@/stores/app";
|
||||||
import { createRouter, createWebHistory } from "vue-router";
|
import { createRouter, createWebHistory } from "vue-router";
|
||||||
|
|
||||||
|
|
@ -103,6 +107,7 @@ const router = createRouter({
|
||||||
path: "/course/:courseSlug/cockpit",
|
path: "/course/:courseSlug/cockpit",
|
||||||
props: true,
|
props: true,
|
||||||
component: () => import("@/pages/cockpit/CockpitParentPage.vue"),
|
component: () => import("@/pages/cockpit/CockpitParentPage.vue"),
|
||||||
|
beforeEnter: [expertRequired],
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
path: "",
|
path: "",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
import { itGetCached, itPost } from "@/fetchHelpers";
|
||||||
|
import type { CourseSession } from "@/types";
|
||||||
|
import { createPinia, setActivePinia } from "pinia";
|
||||||
|
import { beforeEach, describe, expect, vi } from "vitest";
|
||||||
|
import { useRoute } from "vue-router";
|
||||||
|
import { useCourseSessionsStore } from "../courseSessions";
|
||||||
|
import { useUserStore } from "../user";
|
||||||
|
|
||||||
|
let user = {};
|
||||||
|
let courseSessions: CourseSession[] = [];
|
||||||
|
|
||||||
|
describe("CourseSession Store", () => {
|
||||||
|
vi.mock("vue-router", () => ({
|
||||||
|
useRoute: () => ({
|
||||||
|
path: "/course/test-course/learn/",
|
||||||
|
}),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock("@/fetchHelpers", () => {
|
||||||
|
const itGetCached = () => Promise.resolve([]);
|
||||||
|
const itPost = () => Promise.resolve([]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
itGetCached,
|
||||||
|
itPost,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
// creates a fresh pinia and make it active so it's automatically picked
|
||||||
|
// up by any useStore() call without having to pass it to it:
|
||||||
|
// `useStore(pinia)`
|
||||||
|
setActivePinia(createPinia());
|
||||||
|
user = {
|
||||||
|
is_superuser: false,
|
||||||
|
course_session_expert: [],
|
||||||
|
};
|
||||||
|
courseSessions = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
created_at: "2021-05-11T10:00:00.000000Z",
|
||||||
|
updated_at: "2023-05-11T10:00:00.000000Z",
|
||||||
|
course: {
|
||||||
|
id: 1,
|
||||||
|
title: "Test Course",
|
||||||
|
category_name: "Test Category",
|
||||||
|
slug: "test-course",
|
||||||
|
},
|
||||||
|
title: "Test Course Session",
|
||||||
|
start_date: "2022-05-11T10:00:00.000000Z",
|
||||||
|
end_date: "2023-05-11T10:00:00.000000Z",
|
||||||
|
learning_path_url: "/course/test-course/learn/",
|
||||||
|
competence_url: "/course/test-course/competence/",
|
||||||
|
course_url: "/course/test-course/",
|
||||||
|
media_library_url: "/course/test-course/media/",
|
||||||
|
additional_json_data: {},
|
||||||
|
documents: [],
|
||||||
|
users: [],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
it("normal user has no cockpit", () => {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
userStore.$patch(user);
|
||||||
|
courseSessionsStore.$patch({ courseSessions });
|
||||||
|
|
||||||
|
expect(courseSessionsStore.hasCockpit).toBeFalsy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("superuser has cockpit", () => {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
userStore.$patch(Object.assign(user, { is_superuser: true }));
|
||||||
|
courseSessionsStore.$patch({ courseSessions });
|
||||||
|
|
||||||
|
expect(courseSessionsStore.hasCockpit).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("expert has cockpit", () => {
|
||||||
|
const userStore = useUserStore();
|
||||||
|
const courseSessionsStore = useCourseSessionsStore();
|
||||||
|
userStore.$patch(
|
||||||
|
Object.assign(user, { course_session_experts: [courseSessions[0].id] })
|
||||||
|
);
|
||||||
|
courseSessionsStore.$patch({ courseSessions });
|
||||||
|
|
||||||
|
expect(courseSessionsStore.hasCockpit).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue