From 1ad8ee12b1d9666e6cf5db6bcb6e7e3ba5d5e40d Mon Sep 17 00:00:00 2001 From: swve Date: Mon, 10 Apr 2023 19:59:50 +0200 Subject: [PATCH] feat: init routes protection --- .../activity/[activityid]/edit/page.tsx | 2 +- .../(withmenu)/collections/new/page.tsx | 2 +- .../[orgslug]/(withmenu)/collections/page.tsx | 2 +- .../[courseid]/activity/[activityid]/page.tsx | 2 +- .../course/[courseid]/edit/page.tsx | 5 +-- .../(withmenu)/course/[courseid]/page.tsx | 21 ++++++---- .../[orgslug]/(withmenu)/courses/page.tsx | 2 +- .../_orgs/[orgslug]/(withmenu)/trail/page.tsx | 2 +- .../settings/organization/general/page.tsx | 2 +- front/app/organizations/page.tsx | 2 +- front/services/blocks/Image/images.ts | 2 +- front/services/blocks/Pdf/pdf.ts | 2 +- front/services/blocks/Quiz/quiz.ts | 2 +- front/services/blocks/Video/video.ts | 2 +- front/services/courses/activities.ts | 2 +- front/services/courses/activity.ts | 2 +- front/services/courses/chapters.ts | 39 +++++++------------ front/services/courses/collections.ts | 2 +- front/services/courses/courses.ts | 2 +- front/services/organizations/orgs.ts | 2 +- front/services/settings/org.ts | 2 +- front/services/settings/password.ts | 2 +- front/services/settings/profile.ts | 2 +- .../services/utils/react/middlewares/views.ts | 14 +++++++ front/services/utils/{ => ts}/requests.ts | 27 +++++++++---- 25 files changed, 82 insertions(+), 64 deletions(-) create mode 100644 front/services/utils/react/middlewares/views.ts rename front/services/utils/{ => ts}/requests.ts (61%) diff --git a/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx b/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx index 778ec4f0..6539e6c6 100644 --- a/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx +++ b/front/app/_editor/course/[courseid]/activity/[activityid]/edit/page.tsx @@ -9,7 +9,7 @@ import AuthProvider from "@components/Security/AuthProvider"; import EditorWrapper from "@components/Editor/EditorWrapper"; import useSWR, { mutate } from "swr"; import { getAPIUrl } from "@services/config/config"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; function EditActivity(params: any) { diff --git a/front/app/_orgs/[orgslug]/(withmenu)/collections/new/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/collections/new/page.tsx index da1f8355..5a190dec 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/collections/new/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/collections/new/page.tsx @@ -5,7 +5,7 @@ import { Title } from "@components/UI/Elements/Styles/Title"; import { createCollection } from "@services/courses/collections"; import useSWR from "swr"; import { getAPIUrl } from "@services/config/config"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import { getOrganizationContextInfo } from "@services/organizations/orgs"; function NewCollection(params : any) { diff --git a/front/app/_orgs/[orgslug]/(withmenu)/collections/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/collections/page.tsx index c74dd467..a6169647 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/collections/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/collections/page.tsx @@ -5,7 +5,7 @@ import styled from "styled-components"; import { Title } from "@components/UI/Elements/Styles/Title"; import { deleteCollection } from "@services/courses/collections"; import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import useSWR, { mutate } from "swr"; function Collections(params: any) { diff --git a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/activity/[activityid]/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/activity/[activityid]/page.tsx index 480040f2..b8d2d2b2 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/activity/[activityid]/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/activity/[activityid]/page.tsx @@ -10,7 +10,7 @@ import { getCourse } from "@services/courses/courses"; import VideoActivity from "@components/Pages/Activities/Video/Video"; import useSWR, { mutate } from "swr"; import { Check } from "lucide-react"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import { markActivityAsComplete } from "@services/courses/activity"; function ActivityPage(params: any) { diff --git a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx index 45f0d10f..f2bd7c06 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/edit/page.tsx @@ -15,6 +15,7 @@ import { createActivity, createFileActivity } from "@services/courses/activities import { getOrganizationContextInfo } from "@services/organizations/orgs"; import Modal from "@components/UI/Modal/Modal"; import AuthProvider from "@components/Security/AuthProvider"; +import { denyAccessToUser } from "@services/utils/react/middlewares/views"; function CourseEdit(params: any) { @@ -38,9 +39,7 @@ function CourseEdit(params: any) { const courseChapters = await getCourseChaptersMetadata(courseid); setData(courseChapters); } catch (error: any) { - if (error.status === 401) { - router.push("/login"); - } + denyAccessToUser(error, router) } } diff --git a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx index 0f2f3b4c..f098e2b6 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx @@ -1,21 +1,26 @@ "use client"; import { EyeOpenIcon, Pencil2Icon } from "@radix-ui/react-icons"; -import { removeCourse, startCourse } from "@services/courses/activity"; +import { removeCourse, startCourse } from "@services/courses/activity"; import Link from "next/link"; import React from "react"; import styled from "styled-components"; import { getAPIUrl, getBackendUrl, getUriWithOrg } from "@services/config/config"; import useSWR, { mutate } from "swr"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; +import { useRouter } from "next/navigation"; const CourseIdPage = (params: any) => { const courseid = params.params.courseid; const orgslug = params.params.orgslug; - const { data: course, error: error } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`, swrFetcher); + const router = useRouter(); + + const { data: course, error: error } = useSWR(`${getAPIUrl()}courses/meta/course_${courseid}`, + (url: string, body: any) => swrFetcher(url, body, router) + ); async function startCourseUI() { // Create activity - await startCourse("course_" + courseid, orgslug); + await startCourse("course_" + courseid, orgslug); // Mutate course mutate(`${getAPIUrl()}courses/meta/course_${courseid}`); @@ -24,7 +29,7 @@ const CourseIdPage = (params: any) => { async function quitCourse() { // Close activity - let activity = await removeCourse("course_" + courseid, orgslug); + let activity = await removeCourse("course_" + courseid, orgslug); console.log(activity); // Mutate course @@ -42,7 +47,7 @@ const CourseIdPage = (params: any) => {

Course

{course.course.name}{" "} - + {" "}

@@ -53,7 +58,7 @@ const CourseIdPage = (params: any) => { {chapter.activities.map((activity: any) => { return ( <> - + {" "} @@ -94,7 +99,7 @@ const CourseIdPage = (params: any) => { <>

Activity {activity.name} - + {" "}

diff --git a/front/app/_orgs/[orgslug]/(withmenu)/courses/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/courses/page.tsx index 86706ad1..d7bfa2cd 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/courses/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/courses/page.tsx @@ -7,7 +7,7 @@ import { Title } from "@components/UI/Elements/Styles/Title"; import { getAPIUrl, getBackendUrl, getSelfHostedOption, getUriWithOrg } from "@services/config/config"; import { deleteCourseFromBackend } from "@services/courses/courses"; import useSWR, { mutate } from "swr"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import { Edit2, Trash } from "lucide-react"; const CoursesIndexPage = (params: any) => { diff --git a/front/app/_orgs/[orgslug]/(withmenu)/trail/page.tsx b/front/app/_orgs/[orgslug]/(withmenu)/trail/page.tsx index 2d86dacb..f965dce1 100644 --- a/front/app/_orgs/[orgslug]/(withmenu)/trail/page.tsx +++ b/front/app/_orgs/[orgslug]/(withmenu)/trail/page.tsx @@ -1,6 +1,6 @@ "use client"; import { getAPIUrl, getBackendUrl } from "@services/config/config"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import React from "react"; import { styled } from "styled-components"; import useSWR from "swr"; diff --git a/front/app/_orgs/[orgslug]/settings/organization/general/page.tsx b/front/app/_orgs/[orgslug]/settings/organization/general/page.tsx index 4ecd1249..048f4fc2 100644 --- a/front/app/_orgs/[orgslug]/settings/organization/general/page.tsx +++ b/front/app/_orgs/[orgslug]/settings/organization/general/page.tsx @@ -1,7 +1,7 @@ "use client"; import React from 'react' import useSWR, { mutate } from "swr"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import { getAPIUrl } from '@services/config/config'; import { Field, Form, Formik } from 'formik'; import { updateOrganization } from '@services/settings/org'; diff --git a/front/app/organizations/page.tsx b/front/app/organizations/page.tsx index ba286b4c..312ec33b 100644 --- a/front/app/organizations/page.tsx +++ b/front/app/organizations/page.tsx @@ -4,7 +4,7 @@ import React from "react"; import { Title } from "../../components/UI/Elements/Styles/Title"; import { deleteOrganizationFromBackend } from "@services/organizations/orgs"; import useSWR, { mutate } from "swr"; -import { swrFetcher } from "@services/utils/requests"; +import { swrFetcher } from "@services/utils/ts/requests"; import { getAPIUrl, getUriWithOrg } from "@services/config/config"; import AuthProvider from "@components/Security/AuthProvider"; diff --git a/front/services/blocks/Image/images.ts b/front/services/blocks/Image/images.ts index bb93582b..0429b6dd 100644 --- a/front/services/blocks/Image/images.ts +++ b/front/services/blocks/Image/images.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; export async function uploadNewImageFile(file: any, activity_id: string) { // Send file thumbnail as form data diff --git a/front/services/blocks/Pdf/pdf.ts b/front/services/blocks/Pdf/pdf.ts index 2bff8fbe..fc9b4e5e 100644 --- a/front/services/blocks/Pdf/pdf.ts +++ b/front/services/blocks/Pdf/pdf.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; export async function uploadNewPDFFile(file: any, activity_id: string) { // Send file thumbnail as form data diff --git a/front/services/blocks/Quiz/quiz.ts b/front/services/blocks/Quiz/quiz.ts index 706bbf00..0adb85dd 100644 --- a/front/services/blocks/Quiz/quiz.ts +++ b/front/services/blocks/Quiz/quiz.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; export async function submitQuizBlock(activity_id: string, data: any) { diff --git a/front/services/blocks/Video/video.ts b/front/services/blocks/Video/video.ts index a2c45388..bf7142b4 100644 --- a/front/services/blocks/Video/video.ts +++ b/front/services/blocks/Video/video.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; export async function uploadNewVideoFile(file: any, activity_id: string) { // Send file thumbnail as form data diff --git a/front/services/courses/activities.ts b/front/services/courses/activities.ts index 9ee811d6..02d8726c 100644 --- a/front/services/courses/activities.ts +++ b/front/services/courses/activities.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; export async function createActivity(data: any, chapter_id: any, org_id: any) { data.content = {}; diff --git a/front/services/courses/activity.ts b/front/services/courses/activity.ts index d2fcda94..cce7f84f 100644 --- a/front/services/courses/activity.ts +++ b/front/services/courses/activity.ts @@ -1,4 +1,4 @@ -import { RequestBody } from "@services/utils/requests"; +import { RequestBody } from "@services/utils/ts/requests"; import { getAPIUrl } from "@services/config/config"; /* diff --git a/front/services/courses/chapters.ts b/front/services/courses/chapters.ts index 8bdc85e2..ddf2c521 100644 --- a/front/services/courses/chapters.ts +++ b/front/services/courses/chapters.ts @@ -1,6 +1,5 @@ -import { initialData } from "../../components/Pages/CourseEdit/Draggables/data"; import { getAPIUrl } from "@services/config/config"; -import { RequestBody } from "@services/utils/requests"; +import { RequestBody, errorHandling } from "@services/utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests @@ -9,38 +8,26 @@ import { RequestBody } from "@services/utils/requests"; //TODO : depreciate this function export async function getCourseChaptersMetadata(course_id: any) { - const response = await fetch(`${getAPIUrl()}chapters/meta/course_${course_id}`, RequestBody("GET", null)); - - if (!response.ok) { - const error: any = new Error(`Error ${response.status}: ${response.statusText}`, {}); - error.status = response.status; - throw error; - } - - const data = await response.json(); - return data; + const result = await fetch(`${getAPIUrl()}chapters/meta/course_${course_id}`, RequestBody("GET", null)); + const res = await errorHandling(result); + return res; } export async function updateChaptersMetadata(course_id: any, data: any) { - const result: any = await fetch(`${getAPIUrl()}chapters/meta/course_${course_id}`, RequestBody("PUT", data)) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); - - return result; + const result: any = await fetch(`${getAPIUrl()}chapters/meta/course_${course_id}`, RequestBody("PUT", data)); + const res = await errorHandling(result); + return res; } export async function createChapter(data: any, course_id: any) { - const result: any = await fetch(`${getAPIUrl()}chapters/?course_id=course_${course_id}`, RequestBody("POST", data)) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); + const result: any = await fetch(`${getAPIUrl()}chapters/?course_id=course_${course_id}`, RequestBody("POST", data)); + const res = await errorHandling(result); - return result; + return res; } export async function deleteChapter(coursechapter_id: any) { - const result: any = await fetch(`${getAPIUrl()}chapters/${coursechapter_id}`, RequestBody("DELETE", null)) - .then((result) => result.json()) - .catch((error) => console.log("error", error)); - - return result; + const result: any = await fetch(`${getAPIUrl()}chapters/${coursechapter_id}`, RequestBody("DELETE", null)); + const res = await errorHandling(result); + return res; } diff --git a/front/services/courses/collections.ts b/front/services/courses/collections.ts index 2f213f0b..7429f5a6 100644 --- a/front/services/courses/collections.ts +++ b/front/services/courses/collections.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "../config/config"; -import { RequestBody } from "../utils/requests"; +import { RequestBody } from "../utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/courses/courses.ts b/front/services/courses/courses.ts index d7307e70..a0236419 100644 --- a/front/services/courses/courses.ts +++ b/front/services/courses/courses.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody, RequestBodyForm } from "@services/utils/requests"; +import { RequestBody, RequestBodyForm } from "@services/utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/organizations/orgs.ts b/front/services/organizations/orgs.ts index ddd6fde4..eb648285 100644 --- a/front/services/organizations/orgs.ts +++ b/front/services/organizations/orgs.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody } from "../utils/requests"; +import { RequestBody } from "../utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/settings/org.ts b/front/services/settings/org.ts index 10842ca2..4f225fce 100644 --- a/front/services/settings/org.ts +++ b/front/services/settings/org.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody } from "@services/utils/requests"; +import { RequestBody } from "@services/utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/settings/password.ts b/front/services/settings/password.ts index b4c13bb3..9cd57b28 100644 --- a/front/services/settings/password.ts +++ b/front/services/settings/password.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody } from "@services/utils/requests"; +import { RequestBody } from "@services/utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/settings/profile.ts b/front/services/settings/profile.ts index bb1a048a..b6322d65 100644 --- a/front/services/settings/profile.ts +++ b/front/services/settings/profile.ts @@ -1,5 +1,5 @@ import { getAPIUrl } from "@services/config/config"; -import { RequestBody } from "@services/utils/requests"; +import { RequestBody } from "@services/utils/ts/requests"; /* This file includes only POST, PUT, DELETE requests diff --git a/front/services/utils/react/middlewares/views.ts b/front/services/utils/react/middlewares/views.ts new file mode 100644 index 00000000..6ab82348 --- /dev/null +++ b/front/services/utils/react/middlewares/views.ts @@ -0,0 +1,14 @@ +import { AppRouterInstance } from "next/dist/shared/lib/app-router-context"; +import { NextRouter } from "next/router"; + +export const denyAccessToUser = (error : any, router: AppRouterInstance) => { + if (error.status === 401) { + router.push("/login"); + } + + if (error.status === 403) { + router.push("/login"); + // TODO : add a message to the user to tell him he is not allowed to access this page, route to /error + } + +} \ No newline at end of file diff --git a/front/services/utils/requests.ts b/front/services/utils/ts/requests.ts similarity index 61% rename from front/services/utils/requests.ts rename to front/services/utils/ts/requests.ts index 3f4e6466..ee372a47 100644 --- a/front/services/utils/requests.ts +++ b/front/services/utils/ts/requests.ts @@ -1,3 +1,6 @@ +import { AppRouterInstance } from "next/dist/shared/lib/app-router-context"; +import { denyAccessToUser } from "../react/middlewares/views"; + export const RequestBody = (method: string, data: any) => { let HeadersConfig = new Headers({ "Content-Type": "application/json" }); let options: any = { @@ -24,7 +27,7 @@ export const RequestBodyForm = (method: string, data: any) => { return options; }; -export const swrFetcher = async (url: string, body: any) => { +export const swrFetcher = async (url: string, body: any, router?: AppRouterInstance) => { // Create the request options let HeadersConfig = new Headers({ "Content-Type": "application/json" }); let options: any = { @@ -39,15 +42,25 @@ export const swrFetcher = async (url: string, body: any) => { options.body = JSON.stringify(body); } - // Fetch the data - const res = await fetch(url, options); + try { + // Fetch the data + const request = await fetch(url, options); + let res = errorHandling(request); - // If the response is not in the 200 range, throw an error + // Return the data + return res; + } catch (error: any) { + if (router) { + denyAccessToUser(error, router); + } + } +}; + +export const errorHandling = (res: any) => { if (!res.ok) { - const error = new Error("An error occurred while fetching the data."); + const error: any = new Error(`Error ${res.status}: ${res.statusText}`, {}); + error.status = res.status; throw error; } - - // Return the data return res.json(); };