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 37c19000..1d20368d 100644 --- a/front/app/editor/course/[courseid]/activity/[activityid]/edit/page.tsx +++ b/front/app/editor/course/[courseid]/activity/[activityid]/edit/page.tsx @@ -9,6 +9,7 @@ import { getCourseMetadataWithAuthHeader } from "@services/courses/courses"; import { cookies } from "next/headers"; import { Metadata } from "next"; import { getActivityWithAuthHeader } from "@services/courses/activities"; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; type MetadataProps = { params: { orgslug: string, courseid: string, activityid: string }; @@ -19,10 +20,9 @@ export async function generateMetadata( { params }: MetadataProps, ): Promise { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); - + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) // Get Org context information - const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) + const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) return { title: `Edit - ${course_meta.course.name} Activity`, @@ -32,13 +32,13 @@ export async function generateMetadata( const EditActivity = async (params: any) => { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) const activityid = params.params.activityid; const courseid = params.params.courseid; const orgslug = params.params.orgslug; - const courseInfo = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) - const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token_cookie ? access_token_cookie.value : null) + const courseInfo = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) return ( diff --git a/front/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx index f0d77317..51efcfd5 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/collection/[collectionid]/page.tsx @@ -1,4 +1,5 @@ import GeneralWrapperStyled from "@components/StyledElements/Wrappers/GeneralWrapper"; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; import { getBackendUrl, getUriWithOrg } from "@services/config/config"; import { getCollectionByIdWithAuthHeader } from "@services/courses/collections"; import { getCourseThumbnailMediaDirectory } from "@services/media/media"; @@ -16,12 +17,13 @@ export async function generateMetadata( { params }: MetadataProps, ): Promise { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); - const col = await getCollectionByIdWithAuthHeader(params.collectionid, access_token_cookie ? access_token_cookie.value : null, { revalidate: 0, tags: ['collections'] }); + const col = await getCollectionByIdWithAuthHeader(params.collectionid, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] }); + - return { title: `Collection : ${col.name} — ${org.name}`, @@ -31,9 +33,9 @@ export async function generateMetadata( const CollectionPage = async (params: any) => { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) const orgslug = params.params.orgslug; - const col = await getCollectionByIdWithAuthHeader(params.params.collectionid, access_token_cookie ? access_token_cookie.value : null, { revalidate: 0, tags: ['collections'] }); + const col = await getCollectionByIdWithAuthHeader(params.params.collectionid, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] }); const removeCoursePrefix = (courseid: string) => { return courseid.replace("course_", "") diff --git a/front/app/orgs/[orgslug]/(withmenu)/collections/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/collections/page.tsx index 37d505dd..0e6310e2 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/collections/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/collections/page.tsx @@ -9,6 +9,7 @@ import { cookies } from "next/headers"; import Link from "next/link"; import CollectionAdminEditsArea from "./admin"; import { getCourseThumbnailMediaDirectory } from "@services/media/media"; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; type MetadataProps = { params: { orgslug: string, courseid: string }; @@ -19,7 +20,6 @@ export async function generateMetadata( { params }: MetadataProps, ): Promise { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); return { @@ -35,11 +35,11 @@ const removeCollectionPrefix = (collectionid: string) => { const CollectionsPage = async (params: any) => { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) const orgslug = params.params.orgslug; const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); const org_id = org.org_id; - const collections = await getOrgCollectionsWithAuthHeader(org_id, access_token_cookie ? access_token_cookie.value : null, { revalidate: 0, tags: ['collections'] }); + const collections = await getOrgCollectionsWithAuthHeader(org_id, access_token ? access_token : null, { revalidate: 0, tags: ['collections'] }); return ( 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 140a0f1a..0f642018 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 @@ -4,6 +4,7 @@ import { cookies } from "next/headers"; import ActivityClient from "./activity"; import { getOrganizationContextInfo } from "@services/organizations/orgs"; import { Metadata } from "next"; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; type MetadataProps = { @@ -15,12 +16,12 @@ export async function generateMetadata( { params }: MetadataProps, ): Promise { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); - const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null ) - const activity = await getActivityWithAuthHeader(params.activityid, { revalidate: 0, tags: ['activities'] }, access_token_cookie ? access_token_cookie.value : null) + const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + const activity = await getActivityWithAuthHeader(params.activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) return { title: activity.name + ` — ${course_meta.course.name} Course`, @@ -30,13 +31,13 @@ export async function generateMetadata( const ActivityPage = async (params: any) => { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) const activityid = params.params.activityid; const courseid = params.params.courseid; const orgslug = params.params.orgslug; - const course_meta = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) - const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token_cookie ? access_token_cookie.value : null) + const course_meta = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + const activity = await getActivityWithAuthHeader(activityid, { revalidate: 0, tags: ['activities'] }, access_token ? access_token : null) return ( <> { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); - const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) + const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) return { title: `Edit Course - ` + course_meta.course.name, @@ -31,7 +32,7 @@ function CourseEdit(params: any) { let subpage = params.params.subpage ? params.params.subpage : 'general'; return ( <> - + ); } diff --git a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx index 2e07285e..f224e72e 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/course/[courseid]/page.tsx @@ -4,6 +4,7 @@ import { cookies } from 'next/headers'; import { getCourseMetadataWithAuthHeader } from '@services/courses/courses'; import { getOrganizationContextInfo } from '@services/organizations/orgs'; import { Metadata } from 'next'; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from '@services/auth/auth'; type MetadataProps = { params: { orgslug: string, courseid: string }; @@ -14,12 +15,12 @@ export async function generateMetadata( { params }: MetadataProps, ): Promise { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); - + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + // Get Org context information const org = await getOrganizationContextInfo(params.orgslug, { revalidate: 1800, tags: ['organizations'] }); - const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) + const course_meta = await getCourseMetadataWithAuthHeader(params.courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) return { title: course_meta.course.name + ` — ${org.name}`, @@ -31,11 +32,11 @@ export async function generateMetadata( const CoursePage = async (params: any) => { const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); const courseid = params.params.courseid const orgslug = params.params.orgslug; - const course_meta = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null) - + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const course_meta = await getCourseMetadataWithAuthHeader(courseid, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null) + return (
diff --git a/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx index 8b4e5371..e0ff84f9 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/courses/page.tsx @@ -5,6 +5,7 @@ import { getOrgCoursesWithAuthHeader } from "@services/courses/courses"; import { Metadata } from "next"; import { getOrganizationContextInfo } from "@services/organizations/orgs"; import { cookies } from "next/headers"; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from "@services/auth/auth"; type MetadataProps = { params: { orgslug: string }; @@ -27,8 +28,8 @@ const CoursesPage = async (params: any) => { const orgslug = params.params.orgslug; const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); - const courses = await getOrgCoursesWithAuthHeader(orgslug, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const courses = await getOrgCoursesWithAuthHeader(orgslug, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null); return (
diff --git a/front/app/orgs/[orgslug]/(withmenu)/page.tsx b/front/app/orgs/[orgslug]/(withmenu)/page.tsx index 45af8588..63a5fe65 100644 --- a/front/app/orgs/[orgslug]/(withmenu)/page.tsx +++ b/front/app/orgs/[orgslug]/(withmenu)/page.tsx @@ -12,6 +12,7 @@ import { cookies } from 'next/headers'; import GeneralWrapperStyled from '@components/StyledElements/Wrappers/GeneralWrapper'; import TypeOfContentTitle from '@components/StyledElements/Titles/TypeOfContentTitle'; import { getCourseThumbnailMediaDirectory } from '@services/media/media'; +import { getAccessTokenFromRefreshTokenCookie, getNewAccessTokenUsingRefreshTokenServer } from '@services/auth/auth'; type MetadataProps = { params: { orgslug: string }; @@ -34,11 +35,11 @@ export async function generateMetadata( const OrgHomePage = async (params: any) => { const orgslug = params.params.orgslug; const cookieStore = cookies(); - const access_token_cookie: any = cookieStore.get('access_token_cookie'); - const courses = await getOrgCoursesWithAuthHeader(orgslug, { revalidate: 0, tags: ['courses'] }, access_token_cookie ? access_token_cookie.value : null); + const access_token = await getAccessTokenFromRefreshTokenCookie(cookieStore) + const courses = await getOrgCoursesWithAuthHeader(orgslug, { revalidate: 0, tags: ['courses'] }, access_token ? access_token : null); const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); - const collections = await getOrgCollectionsWithAuthHeader(org.org_id, access_token_cookie ? access_token_cookie.value : null, { revalidate: 0, tags: ['courses'] }); + const collections = await getOrgCollectionsWithAuthHeader(org.org_id, access_token ? access_token : null, { revalidate: 0, tags: ['courses'] }); // function to remove "course_" from the course_id diff --git a/front/components/Objects/Editor/Editor.tsx b/front/components/Objects/Editor/Editor.tsx index d101e3d0..fd7ad21e 100644 --- a/front/components/Objects/Editor/Editor.tsx +++ b/front/components/Objects/Editor/Editor.tsx @@ -24,7 +24,6 @@ import ToolTip from "@components/StyledElements/Tooltip/Tooltip"; import Link from "next/link"; import { getCourseThumbnailMediaDirectory } from "@services/media/media"; import { OrderedList } from "@tiptap/extension-ordered-list"; -import {ListItem} from '@tiptap/extension-list-item' interface Editor { @@ -116,14 +115,14 @@ function Editor(props: Editor) { }} exit={{ opacity: 0 }} > - + - + {" "} @@ -140,10 +139,16 @@ function Editor(props: Editor) { {!auth.isAuthenticated && Loading} {auth.isAuthenticated && } - - - props.setContent(editor.getJSON())}> Save - + + +
props.setContent(editor.getJSON())}> Save
+ + +
+ +
+ +
@@ -170,8 +175,6 @@ function Editor(props: Editor) { const Page = styled.div` height: 100vh; width: 100%; - min-height: 100vh; - min-width: 100vw; padding-top: 30px; // dots background @@ -183,9 +186,7 @@ const Page = styled.div` `; const EditorTop = styled.div` - background-color: #ffffffeb; border-radius: 15px; - backdrop-filter: saturate(180%) blur(14px); margin: 40px; margin-top: 0px; margin-bottom: 20px; @@ -194,7 +195,7 @@ const EditorTop = styled.div` justify-content: space-between; box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03); position: fixed; - z-index: 3; + z-index: 303; width: -webkit-fill-available; `; @@ -217,50 +218,6 @@ const EditorLeftOptionsSection = styled.div` align-items: center; `; -const EditorLeftOptionsSaveButton = styled.button` - background-color: #8783f7; - border-radius: 8px; - border: none; - color: white; - padding: 8px; - margin-left: 10px; - margin-right: 10px; - font-size: 14px; - font-weight: 600; - cursor: pointer; - outline: none; - - - &:hover { - background-color: #4a44f9; - opacity: 0.8; - } -`; - -const EditorLeftOptionsPreviewButton = styled.button` - background-color: #a4a4a449; - border-radius: 8px; - border: none; - color: #000000; - padding: 8px; - margin-right: 10px; - font-size: 14px; - font-weight: 600; - cursor: pointer; - outline: none; - - // center icon - display: flex; - justify-content: center; - align-items: center; - - &:hover { - background-color: #c0bfbf; - opacity: 0.8; - } - -`; - // Inside EditorDocSection const EditorInfoWrapper = styled.div` @@ -300,33 +257,6 @@ const EditorInfoDocName = styled.div` } `; -const EditorSaveButton = styled.div` - display: flex; - border-radius: 8px; - padding: 5px; - font-size: 12px; - margin-right: 5px; - margin-left: 7px; - background: #ffffff8d; - color: #5252528d; - border: solid 1px #52525257; - align-items: center; - justify-content: space-between; - width: 53px; - - &.is-active { - background: rgba(176, 176, 176, 0.5); - - &:hover { - background: rgba(31, 31, 31, 0.5); - cursor: pointer; - } - } - - &:hover { - cursor: pointer; - } -`; const EditorInfoThumbnail = styled.img` height: 25px; @@ -346,6 +276,7 @@ export const EditorContentWrapper = styled.div` margin-top: 90px; background-color: white; border-radius: 10px; + z-index: 300; box-shadow: 0px 4px 16px rgba(0, 0, 0, 0.03); // disable chrome outline @@ -412,9 +343,11 @@ export const EditorContentWrapper = styled.div` ul, ol { padding: 0 1rem; - padding-left: 10px; + padding-left: 20px; list-style-type: decimal; } + + `; diff --git a/front/components/Objects/Editor/Toolbar/ToolbarButtons.tsx b/front/components/Objects/Editor/Toolbar/ToolbarButtons.tsx index 4df34e3c..d5ebc0b9 100644 --- a/front/components/Objects/Editor/Toolbar/ToolbarButtons.tsx +++ b/front/components/Objects/Editor/Toolbar/ToolbarButtons.tsx @@ -193,7 +193,7 @@ const ToolBtn = styled.div` const ToolSelect = styled.select` display: flex; - background: rgba(217, 217, 217, 0.24); + background: rgba(217, 217, 217, 0.185); border-radius: 6px; width: 100px; border: none; diff --git a/front/components/Objects/Menu/Menu.tsx b/front/components/Objects/Menu/Menu.tsx index 441703cb..bdf5dcb4 100644 --- a/front/components/Objects/Menu/Menu.tsx +++ b/front/components/Objects/Menu/Menu.tsx @@ -1,7 +1,7 @@ 'use client'; import React from "react"; import Link from "next/link"; -import { getUriWithOrg } from "@services/config/config"; +import { getUriWithOrg } from "@services/config/config"; import { getOrganizationContextInfo } from "@services/organizations/orgs"; import ClientComponentSkeleton from "@components/Utils/ClientComp"; import { HeaderProfileBox } from "@components/Security/HeaderProfileBox"; @@ -10,23 +10,22 @@ import { getOrgLogoMediaDirectory } from "@services/media/media"; export const Menu = async (props: any) => { const orgslug = props.orgslug; - const org = await getOrganizationContextInfo(orgslug, { revalidate: 1800, tags: ['organizations'] }); - + const org = await getOrganizationContextInfo(orgslug, { revalidate: 0, tags: ['organizations'] }); return ( <> -
-
+
- {org?.logo ? ( + {org.logo ? ( Learnhouse({ access_token: "", isAuthenticated: false, userInfo: {}, isLoading: true }); async function checkRefreshToken() { - let data = await getRefreshToken(); + let data = await getNewAccessTokenUsingRefreshToken(); if (data) { return data.access_token; } } + React.useEffect(() => { + checkAuth(); + }, [pathname]); async function checkAuth() { try { diff --git a/front/components/Objects/Modals/Course/Create/CreateCourse.tsx b/front/components/Objects/Modals/Course/Create/CreateCourse.tsx index d1bc7b63..e95cfd09 100644 --- a/front/components/Objects/Modals/Course/Create/CreateCourse.tsx +++ b/front/components/Objects/Modals/Course/Create/CreateCourse.tsx @@ -55,7 +55,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) { // window.location.reload(); } else { alert("Error creating course, please see console logs"); - console.log(status); } }; diff --git a/front/components/Pages/Activities/DynamicCanva/DynamicCanva.tsx b/front/components/Pages/Activities/DynamicCanva/DynamicCanva.tsx index 5ab24ea7..69ebf363 100644 --- a/front/components/Pages/Activities/DynamicCanva/DynamicCanva.tsx +++ b/front/components/Pages/Activities/DynamicCanva/DynamicCanva.tsx @@ -107,7 +107,7 @@ h5 { ul, ol { padding: 0 1rem; - padding-left: 10px; + padding-left: 20px; list-style-type: decimal; } diff --git a/front/components/Security/AuthProvider.tsx b/front/components/Security/AuthProvider.tsx index c8bcee55..364c8971 100644 --- a/front/components/Security/AuthProvider.tsx +++ b/front/components/Security/AuthProvider.tsx @@ -1,6 +1,6 @@ "use client"; import React, { useEffect } from "react"; -import { getRefreshToken, getUserInfo } from "../../services/auth/auth"; +import { getNewAccessTokenUsingRefreshToken, getUserInfo } from "../../services/auth/auth"; import { useRouter, usePathname } from "next/navigation"; export const AuthContext: any = React.createContext({}); @@ -21,8 +21,14 @@ const AuthProvider = ({ children }: any) => { const [auth, setAuth] = React.useState({ access_token: "", isAuthenticated: false, userInfo: {}, isLoading: true }); + function deleteCookie(cookieName: string) { + document.cookie = cookieName + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/;"; + } + + async function checkRefreshToken() { - let data = await getRefreshToken(); + deleteCookie("access_token_cookie"); + let data = await getNewAccessTokenUsingRefreshToken(); if (data) { return data.access_token; } @@ -61,13 +67,12 @@ const AuthProvider = ({ children }: any) => { } useEffect(() => { - if (auth.isLoading) { - checkAuth(); - } + checkRefreshToken(); + checkAuth(); return () => { auth.isLoading = false; }; - }, []); + }, [pathname]); return {children}; }; diff --git a/front/package-lock.json b/front/package-lock.json index cf9185d5..53741010 100644 --- a/front/package-lock.json +++ b/front/package-lock.json @@ -24,7 +24,7 @@ "@tiptap/starter-kit": "^2.0.0-beta.199", "avvvatars-react": "^0.4.2", "formik": "^2.2.9", - "framer-motion": "^7.3.6", + "framer-motion": "^10.16.1", "lucide-react": "^0.268.0", "next": "^13.4.19", "re-resizable": "^6.9.9", @@ -2259,64 +2259,6 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@motionone/animation": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/animation/-/animation-10.15.1.tgz", - "integrity": "sha512-mZcJxLjHor+bhcPuIFErMDNyrdb2vJur8lSfMCsuCB4UyV8ILZLvK+t+pg56erv8ud9xQGK/1OGPt10agPrCyQ==", - "dependencies": { - "@motionone/easing": "^10.15.1", - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/dom": { - "version": "10.16.2", - "resolved": "https://registry.npmjs.org/@motionone/dom/-/dom-10.16.2.tgz", - "integrity": "sha512-bnuHdNbge1FutZXv+k7xub9oPWcF0hsu8y1HTH/qg6av58YI0VufZ3ngfC7p2xhMJMnoh0LXFma2EGTgPeCkeg==", - "dependencies": { - "@motionone/animation": "^10.15.1", - "@motionone/generators": "^10.15.1", - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/easing": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/easing/-/easing-10.15.1.tgz", - "integrity": "sha512-6hIHBSV+ZVehf9dcKZLT7p5PEKHGhDwky2k8RKkmOvUoYP3S+dXsKupyZpqx5apjd9f+php4vXk4LuS+ADsrWw==", - "dependencies": { - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/generators": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/generators/-/generators-10.15.1.tgz", - "integrity": "sha512-67HLsvHJbw6cIbLA/o+gsm7h+6D4Sn7AUrB/GPxvujse1cGZ38F5H7DzoH7PhX+sjvtDnt2IhFYF2Zp1QTMKWQ==", - "dependencies": { - "@motionone/types": "^10.15.1", - "@motionone/utils": "^10.15.1", - "tslib": "^2.3.1" - } - }, - "node_modules/@motionone/types": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/types/-/types-10.15.1.tgz", - "integrity": "sha512-iIUd/EgUsRZGrvW0jqdst8st7zKTzS9EsKkP+6c6n4MPZoQHwiHuVtTQLD6Kp0bsBLhNzKIBlHXponn/SDT4hA==" - }, - "node_modules/@motionone/utils": { - "version": "10.15.1", - "resolved": "https://registry.npmjs.org/@motionone/utils/-/utils-10.15.1.tgz", - "integrity": "sha512-p0YncgU+iklvYr/Dq4NobTRdAPv9PveRDUXabPEeOjBLSO/1FNB2phNTZxOxpi1/GZwYpAoECEa0Wam+nsmhSw==", - "dependencies": { - "@motionone/types": "^10.15.1", - "hey-listen": "^1.0.8", - "tslib": "^2.3.1" - } - }, "node_modules/@next/env": { "version": "13.4.19", "resolved": "https://registry.npmjs.org/@next/env/-/env-13.4.19.tgz", @@ -5781,13 +5723,11 @@ } }, "node_modules/framer-motion": { - "version": "7.10.3", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-7.10.3.tgz", - "integrity": "sha512-k2ccYeZNSpPg//HTaqrU+4pRq9f9ZpaaN7rr0+Rx5zA4wZLbk547wtDzge2db1sB+1mnJ6r59P4xb+aEIi/W+w==", + "version": "10.16.1", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-10.16.1.tgz", + "integrity": "sha512-K6TXr5mZtitC/dxQCBdg7xzdN0d5IAIrlaqCPKtIQVdzVPGC0qBuJKXggHX1vjnP5gPOFwB1KbCCTWcnFc3kWg==", "dependencies": { - "@motionone/dom": "^10.15.3", - "hey-listen": "^1.0.8", - "tslib": "2.4.0" + "tslib": "^2.4.0" }, "optionalDependencies": { "@emotion/is-prop-valid": "^0.8.2" @@ -5795,13 +5735,16 @@ "peerDependencies": { "react": "^18.0.0", "react-dom": "^18.0.0" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-dom": { + "optional": true + } } }, - "node_modules/framer-motion/node_modules/tslib": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" - }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", @@ -6135,11 +6078,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hey-listen": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/hey-listen/-/hey-listen-1.0.8.tgz", - "integrity": "sha512-COpmrF2NOg4TBWUJ5UVyaCU2A88wEMkUPK4hNqyCkqHbxT92BbvfjoSozkAIIm6XhicGlJHhFdullInrdhwU8Q==" - }, "node_modules/hoist-non-react-statics": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz", diff --git a/front/package.json b/front/package.json index 66c06ba5..592c2f7c 100644 --- a/front/package.json +++ b/front/package.json @@ -25,7 +25,7 @@ "@tiptap/starter-kit": "^2.0.0-beta.199", "avvvatars-react": "^0.4.2", "formik": "^2.2.9", - "framer-motion": "^7.3.6", + "framer-motion": "^10.16.1", "lucide-react": "^0.268.0", "next": "^13.4.19", "re-resizable": "^6.9.9", diff --git a/front/services/auth/auth.ts b/front/services/auth/auth.ts index d09a6746..b07027be 100644 --- a/front/services/auth/auth.ts +++ b/front/services/auth/auth.ts @@ -1,4 +1,5 @@ import { getAPIUrl } from "@services/config/config"; +import { NextApiRequestCookies } from "next/dist/server/api-utils"; interface LoginAndGetTokenResponse { access_token: "string"; @@ -44,7 +45,7 @@ export async function getUserInfo(token: string): Promise { .catch((error) => console.log("error", error)); } -export async function getRefreshToken(): Promise { +export async function getNewAccessTokenUsingRefreshToken(): Promise { const requestOptions: any = { method: "POST", redirect: "follow", @@ -56,6 +57,28 @@ export async function getRefreshToken(): Promise { .catch((error) => console.log("error", error)); } +export async function getNewAccessTokenUsingRefreshTokenServer(refresh_token_cookie: any): Promise { + const requestOptions: any = { + method: "POST", + redirect: "follow", + headers: { + Cookie: `refresh_token_cookie=${refresh_token_cookie}`, + }, + credentials: "include", + }; + return fetch(`${getAPIUrl()}auth/refresh`, requestOptions) + .then((result) => result.json()) + .catch((error) => console.log("error", error)); +} + +// cookies + +export async function getAccessTokenFromRefreshTokenCookie(cookieStore: any) { + const refresh_token_cookie: any = cookieStore.get("refresh_token_cookie"); + const access_token_cookie: any = await getNewAccessTokenUsingRefreshTokenServer(refresh_token_cookie?.value); + return access_token_cookie && refresh_token_cookie ? access_token_cookie.access_token : null; +} + // signup interface NewAccountBody { diff --git a/front/services/config/config.ts b/front/services/config/config.ts index 4fca83ce..caab8422 100644 --- a/front/services/config/config.ts +++ b/front/services/config/config.ts @@ -1,6 +1,6 @@ export const LEARNHOUSE_HTTP_PROTOCOL = process.env.NEXT_PUBLIC_LEARNHOUSE_HTTPS === "true" ? "https://" : "http://"; const LEARNHOUSE_API_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_API_URL}`; -const LEARNHOUSE_BACKEND_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_BACKEND_URL}`; +export const LEARNHOUSE_BACKEND_URL = `${process.env.NEXT_PUBLIC_LEARNHOUSE_BACKEND_URL}`; export const LEARNHOUSE_DOMAIN = process.env.NEXT_PUBLIC_LEARNHOUSE_DOMAIN; export const getAPIUrl = () => LEARNHOUSE_API_URL; diff --git a/src/routers/auth.py b/src/routers/auth.py index 2cc82973..54e4dc7a 100644 --- a/src/routers/auth.py +++ b/src/routers/auth.py @@ -9,7 +9,7 @@ router = APIRouter() @router.post("/refresh") -def refresh(Authorize: AuthJWT = Depends()): +def refresh(response: Response,Authorize: AuthJWT = Depends()): """ The jwt_refresh_token_required() function insures a valid refresh token is present in the request before running any code below that function. @@ -20,6 +20,8 @@ def refresh(Authorize: AuthJWT = Depends()): current_user = Authorize.get_jwt_subject() new_access_token = Authorize.create_access_token(subject=current_user) # type: ignore + + response.set_cookie(key="access_token_cookie", value=new_access_token, httponly=False, domain=get_learnhouse_config().hosting_config.cookie_config.domain) return {"access_token": new_access_token}