mirror of
https://github.com/rzmk/learnhouse.git
synced 2025-12-19 04:19:25 +00:00
fix: session auth issues
This commit is contained in:
parent
1708b36818
commit
08cc97f557
70 changed files with 607 additions and 427 deletions
|
|
@ -4,6 +4,7 @@ import { getAPIUrl } from '@services/config/config'
|
|||
import { swrFetcher } from '@services/utils/ts/requests'
|
||||
import React, { createContext, useContext, useEffect, useReducer } from 'react'
|
||||
import useSWR from 'swr'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
export const CourseContext = createContext(null) as any
|
||||
export const CourseDispatchContext = createContext(null) as any
|
||||
|
|
@ -15,9 +16,11 @@ export function CourseProvider({
|
|||
children: React.ReactNode
|
||||
courseuuid: string
|
||||
}) {
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const { data: courseStructureData } = useSWR(
|
||||
`${getAPIUrl()}courses/${courseuuid}/meta`,
|
||||
swrFetcher
|
||||
(url) => swrFetcher(url, access_token)
|
||||
)
|
||||
const [courseStructure, dispatchCourseStructure] = useReducer(courseReducer, {
|
||||
courseStructure: courseStructureData ? courseStructureData : {},
|
||||
|
|
@ -33,7 +36,7 @@ export function CourseProvider({
|
|||
payload: courseStructureData,
|
||||
})
|
||||
}
|
||||
}, [courseStructureData])
|
||||
}, [courseStructureData,session])
|
||||
|
||||
if (!courseStructureData) return <PageLoading></PageLoading>
|
||||
|
||||
|
|
|
|||
33
apps/web/components/Contexts/LHSessionContext.tsx
Normal file
33
apps/web/components/Contexts/LHSessionContext.tsx
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
'use client'
|
||||
import PageLoading from '@components/Objects/Loaders/PageLoading';
|
||||
import { useSession } from 'next-auth/react';
|
||||
import React, { useContext, createContext, useEffect } from 'react'
|
||||
|
||||
export const SessionContext = createContext({}) as any
|
||||
|
||||
function LHSessionProvider({ children }: { children: React.ReactNode }) {
|
||||
const session = useSession();
|
||||
|
||||
useEffect(() => {
|
||||
console.log('useLHSession', session);
|
||||
}, [session])
|
||||
|
||||
|
||||
if (session.status == 'loading') {
|
||||
return <PageLoading />
|
||||
}
|
||||
|
||||
else {
|
||||
return (
|
||||
<SessionContext.Provider value={session}>
|
||||
{children}
|
||||
</SessionContext.Provider>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export function useLHSession() {
|
||||
return useContext(SessionContext)
|
||||
}
|
||||
|
||||
export default LHSessionProvider
|
||||
|
|
@ -5,6 +5,8 @@ import React, { useContext, useEffect } from 'react'
|
|||
import useSWR from 'swr'
|
||||
import { createContext } from 'react'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import ErrorUI from '@components/StyledElements/Error/Error'
|
||||
|
||||
export const OrgContext = createContext({}) as any
|
||||
|
||||
|
|
@ -15,7 +17,10 @@ export function OrgProvider({
|
|||
children: React.ReactNode
|
||||
orgslug: string
|
||||
}) {
|
||||
const { data: org } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher)
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const { data: org } = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, (url) => swrFetcher(url, access_token))
|
||||
|
||||
const router = useRouter()
|
||||
// Check if Org is Active
|
||||
const verifyIfOrgIsActive = () => {
|
||||
|
|
@ -28,7 +33,12 @@ export function OrgProvider({
|
|||
verifyIfOrgIsActive()
|
||||
}, [org])
|
||||
|
||||
return <OrgContext.Provider value={org}>{children}</OrgContext.Provider>
|
||||
if (org) {
|
||||
return <OrgContext.Provider value={org}>{children}</OrgContext.Provider>
|
||||
}
|
||||
else {
|
||||
return <ErrorUI />
|
||||
}
|
||||
}
|
||||
|
||||
export function useOrg() {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { getAPIUrl } from '@services/config/config'
|
|||
import { unLinkResourcesToUserGroup } from '@services/usergroups/usergroups'
|
||||
import { swrFetcher } from '@services/utils/ts/requests'
|
||||
import { Globe, SquareUserRound, Users, UsersRound, X } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import React from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import useSWR, { mutate } from 'swr'
|
||||
|
|
@ -17,13 +18,15 @@ type EditCourseAccessProps = {
|
|||
|
||||
function EditCourseAccess(props: EditCourseAccessProps) {
|
||||
const [error, setError] = React.useState('')
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const course = useCourse() as any
|
||||
const dispatchCourse = useCourseDispatch() as any
|
||||
const courseStructure = course.courseStructure
|
||||
const { data: usergroups } = useSWR(
|
||||
courseStructure ? `${getAPIUrl()}usergroups/resource/${courseStructure.course_uuid}` : null,
|
||||
swrFetcher
|
||||
(url) => swrFetcher(url, access_token)
|
||||
)
|
||||
const [isPublic, setIsPublic] = React.useState(courseStructure.public)
|
||||
|
||||
|
|
@ -109,7 +112,7 @@ function EditCourseAccess(props: EditCourseAccessProps) {
|
|||
status="info"
|
||||
></ConfirmationModal>
|
||||
</div>
|
||||
{!isPublic ? ( <UserGroupsSection usergroups={usergroups} />) : null}
|
||||
{!isPublic ? (<UserGroupsSection usergroups={usergroups} />) : null}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
|
|
|||
|
|
@ -4,11 +4,13 @@ import { getAPIUrl } from '@services/config/config'
|
|||
import { updateCourseThumbnail } from '@services/courses/courses'
|
||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||
import { ArrowBigUpDash, UploadCloud } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import React from 'react'
|
||||
import { mutate } from 'swr'
|
||||
|
||||
function ThumbnailUpdate() {
|
||||
const course = useCourse() as any
|
||||
const session = useLHSession()
|
||||
const org = useOrg() as any
|
||||
const [localThumbnail, setLocalThumbnail] = React.useState(null) as any
|
||||
const [isLoading, setIsLoading] = React.useState(false) as any
|
||||
|
|
@ -20,7 +22,8 @@ function ThumbnailUpdate() {
|
|||
setIsLoading(true)
|
||||
const res = await updateCourseThumbnail(
|
||||
course.courseStructure.course_uuid,
|
||||
file
|
||||
file,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
// wait for 1 second to show loading animation
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import {
|
|||
import { getOrganizationContextInfoWithoutCredentials } from '@services/organizations/orgs'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { Layers } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React, { useEffect } from 'react'
|
||||
import { mutate } from 'swr'
|
||||
|
|
@ -23,6 +24,8 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
|||
const [newActivityModal, setNewActivityModal] = React.useState(false)
|
||||
const router = useRouter()
|
||||
const course = useCourse() as any
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
|
||||
const openNewActivityModal = async (chapterId: any) => {
|
||||
setNewActivityModal(true)
|
||||
|
|
@ -38,7 +41,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
|||
props.orgslug,
|
||||
{ revalidate: 1800 }
|
||||
)
|
||||
await createActivity(activity, props.chapterId, org.org_id)
|
||||
await createActivity(activity, props.chapterId, org.org_id, access_token)
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
setNewActivityModal(false)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
|
|
@ -52,7 +55,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
|||
activity: any,
|
||||
chapterId: string
|
||||
) => {
|
||||
await createFileActivity(file, type, activity, chapterId)
|
||||
await createFileActivity(file, type, activity, chapterId, access_token)
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
setNewActivityModal(false)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
|
|
@ -68,7 +71,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
|||
await createExternalVideoActivity(
|
||||
external_video_data,
|
||||
activity,
|
||||
props.chapterId
|
||||
props.chapterId, access_token
|
||||
)
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
setNewActivityModal(false)
|
||||
|
|
@ -76,7 +79,7 @@ function NewActivityButton(props: NewActivityButtonProps) {
|
|||
router.refresh()
|
||||
}
|
||||
|
||||
useEffect(() => {}, [course])
|
||||
useEffect(() => { }, [course])
|
||||
|
||||
return (
|
||||
<div className="flex justify-center">
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import {
|
|||
Video,
|
||||
X,
|
||||
} from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React from 'react'
|
||||
|
|
@ -32,6 +33,8 @@ interface ModifiedActivityInterface {
|
|||
|
||||
function ActivityElement(props: ActivitiyElementProps) {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const [modifiedActivity, setModifiedActivity] = React.useState<
|
||||
ModifiedActivityInterface | undefined
|
||||
>(undefined)
|
||||
|
|
@ -41,7 +44,7 @@ function ActivityElement(props: ActivitiyElementProps) {
|
|||
const activityUUID = props.activity.activity_uuid
|
||||
|
||||
async function deleteActivityUI() {
|
||||
await deleteActivity(props.activity.activity_uuid)
|
||||
await deleteActivity(props.activity.activity_uuid,access_token)
|
||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
@ -60,7 +63,7 @@ function ActivityElement(props: ActivitiyElementProps) {
|
|||
content: props.activity.content,
|
||||
}
|
||||
|
||||
await updateActivity(modifiedActivityCopy, activityUUID)
|
||||
await updateActivity(modifiedActivityCopy, activityUUID,access_token)
|
||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ import { revalidateTags } from '@services/utils/ts/requests'
|
|||
import { useRouter } from 'next/navigation'
|
||||
import { getAPIUrl } from '@services/config/config'
|
||||
import { mutate } from 'swr'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
type ChapterElementProps = {
|
||||
chapter: any
|
||||
|
|
@ -31,6 +32,8 @@ interface ModifiedChapterInterface {
|
|||
|
||||
function ChapterElement(props: ChapterElementProps) {
|
||||
const activities = props.chapter.activities || []
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const [modifiedChapter, setModifiedChapter] = React.useState<
|
||||
ModifiedChapterInterface | undefined
|
||||
>(undefined)
|
||||
|
|
@ -41,7 +44,7 @@ function ChapterElement(props: ChapterElementProps) {
|
|||
const router = useRouter()
|
||||
|
||||
const deleteChapterUI = async () => {
|
||||
await deleteChapter(props.chapter.id)
|
||||
await deleteChapter(props.chapter.id, access_token)
|
||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
@ -53,7 +56,7 @@ function ChapterElement(props: ChapterElementProps) {
|
|||
let modifiedChapterCopy = {
|
||||
name: modifiedChapter.chapterName,
|
||||
}
|
||||
await updateChapter(chapterId, modifiedChapterCopy)
|
||||
await updateChapter(chapterId, modifiedChapterCopy, access_token)
|
||||
mutate(`${getAPIUrl()}courses/${props.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import {
|
|||
import { Hexagon } from 'lucide-react'
|
||||
import Modal from '@components/StyledElements/Modal/Modal'
|
||||
import NewChapterModal from '@components/Objects/Modals/Chapters/NewChapter'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
type EditCourseStructureProps = {
|
||||
orgslug: string
|
||||
|
|
@ -38,6 +39,8 @@ export type OrderPayload =
|
|||
|
||||
const EditCourseStructure = (props: EditCourseStructureProps) => {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
// Check window availability
|
||||
const [winReady, setwinReady] = useState(false)
|
||||
|
||||
|
|
@ -57,7 +60,7 @@ const EditCourseStructure = (props: EditCourseStructureProps) => {
|
|||
|
||||
// Submit new chapter
|
||||
const submitChapter = async (chapter: any) => {
|
||||
await createChapter(chapter)
|
||||
await createChapter(chapter,access_token)
|
||||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
'use client'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { signOut } from 'next-auth/react'
|
||||
import ToolTip from '@components/StyledElements/Tooltip/Tooltip'
|
||||
import LearnHouseDashboardLogo from '@public/dashLogo.png'
|
||||
import { logout } from '@services/auth/auth'
|
||||
import { BookCopy, Home, LogOut, School, Settings, Users } from 'lucide-react'
|
||||
import Image from 'next/image'
|
||||
import Link from 'next/link'
|
||||
|
|
@ -11,10 +10,11 @@ import { useRouter } from 'next/navigation'
|
|||
import React, { useEffect } from 'react'
|
||||
import UserAvatar from '../../Objects/UserAvatar'
|
||||
import AdminAuthorization from '@components/Security/AdminAuthorization'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
function LeftMenu() {
|
||||
const org = useOrg() as any
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const [loading, setLoading] = React.useState(true)
|
||||
const route = useRouter()
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ function LeftMenu() {
|
|||
}
|
||||
|
||||
async function logOutUI() {
|
||||
const res = await logout()
|
||||
const res = await signOut()
|
||||
if (res) {
|
||||
route.push('/login')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,9 +11,11 @@ import { useRouter } from 'next/navigation'
|
|||
import React, { useEffect } from 'react'
|
||||
import { mutate } from 'swr'
|
||||
import { updateCourse } from '@services/courses/courses'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
function SaveState(props: { orgslug: string }) {
|
||||
const course = useCourse() as any
|
||||
const session = useLHSession() as any;
|
||||
const router = useRouter()
|
||||
const saved = course ? course.isSaved : true
|
||||
const dispatchCourse = useCourseDispatch() as any
|
||||
|
|
@ -37,7 +39,8 @@ function SaveState(props: { orgslug: string }) {
|
|||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await updateCourseOrderStructure(
|
||||
course.courseStructure.course_uuid,
|
||||
course.courseOrder
|
||||
course.courseOrder,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
@ -49,7 +52,8 @@ function SaveState(props: { orgslug: string }) {
|
|||
mutate(`${getAPIUrl()}courses/${course.courseStructure.course_uuid}/meta`)
|
||||
await updateCourse(
|
||||
course.courseStructure.course_uuid,
|
||||
course.courseStructure
|
||||
course.courseStructure,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
import { updateProfile } from '@services/settings/profile'
|
||||
import React, { useEffect } from 'react'
|
||||
import { Formik, Form, Field } from 'formik'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import {
|
||||
ArrowBigUpDash,
|
||||
Check,
|
||||
|
|
@ -14,7 +14,7 @@ import UserAvatar from '@components/Objects/UserAvatar'
|
|||
import { updateUserAvatar } from '@services/users/users'
|
||||
|
||||
function UserEditGeneral() {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const [localAvatar, setLocalAvatar] = React.useState(null) as any
|
||||
const [isLoading, setIsLoading] = React.useState(false) as any
|
||||
const [error, setError] = React.useState() as any
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { updatePassword } from '@services/settings/password'
|
||||
import { Formik, Form, Field } from 'formik'
|
||||
import React, { useEffect } from 'react'
|
||||
|
||||
function UserEditPassword() {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
|
||||
const updatePasswordUI = async (values: any) => {
|
||||
let user_id = session.data.user.id
|
||||
|
|
|
|||
|
|
@ -1,43 +1,40 @@
|
|||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useEffect } from 'react'
|
||||
import { useOrg } from '@components/Contexts/OrgContext';
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext';
|
||||
import { useEffect, useState, useMemo } from 'react';
|
||||
|
||||
interface Role {
|
||||
org: { id: number };
|
||||
role: { id: number; role_uuid: string };
|
||||
}
|
||||
|
||||
function useAdminStatus() {
|
||||
const session = useSession() as any
|
||||
const org = useOrg() as any
|
||||
console.log('useAdminStatus', {
|
||||
session,
|
||||
})
|
||||
const session = useLHSession() as any;
|
||||
const org = useOrg() as any;
|
||||
const [isAdmin, setIsAdmin] = useState<boolean | null>(null);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
|
||||
// If session is not loaded, redirect to login
|
||||
const userRoles = useMemo(() => session?.data?.roles || [], [session?.data?.roles]);
|
||||
|
||||
useEffect(() => {
|
||||
if (session.status == 'loading') {
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
, [session])
|
||||
|
||||
const isUserAdmin = () => {
|
||||
if (session.status == 'authenticated') {
|
||||
const isAdmin = session?.data?.roles.some((role: any) => {
|
||||
if (session.status === 'authenticated' && org?.id) {
|
||||
const isAdminVar = userRoles.some((role: Role) => {
|
||||
return (
|
||||
role.org.id === org.id &&
|
||||
(role.role.id === 1 ||
|
||||
role.role.id === 2 ||
|
||||
role.role.role_uuid === 'role_global_admin' ||
|
||||
role.role.role_uuid === 'role_global_maintainer')
|
||||
)
|
||||
})
|
||||
return isAdmin
|
||||
);
|
||||
});
|
||||
setIsAdmin(isAdminVar);
|
||||
setLoading(false); // Set loading to false once the status is determined
|
||||
} else {
|
||||
setIsAdmin(false);
|
||||
setLoading(false); // Set loading to false if not authenticated or org not found
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Return the user admin status
|
||||
return isUserAdmin()
|
||||
}, [session.status, userRoles, org.id]);
|
||||
|
||||
return { isAdmin, loading };
|
||||
}
|
||||
|
||||
export default useAdminStatus
|
||||
export default useAdminStatus;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import {
|
||||
sendActivityAIChatMessage,
|
||||
startActivityAIChatSession,
|
||||
|
|
@ -74,7 +74,7 @@ type ActivityChatMessageBoxProps = {
|
|||
}
|
||||
|
||||
function ActivityChatMessageBox(props: ActivityChatMessageBoxProps) {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
||||
const dispatchAIChatBot = useAIChatBotDispatch() as any
|
||||
|
||||
|
|
@ -328,7 +328,7 @@ type AIMessageProps = {
|
|||
}
|
||||
|
||||
function AIMessage(props: AIMessageProps) {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
|
||||
const words = props.message.message.split(' ')
|
||||
|
||||
|
|
@ -378,7 +378,7 @@ const AIMessagePlaceHolder = (props: {
|
|||
activity_uuid: string
|
||||
sendMessage: any
|
||||
}) => {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
||||
const aiChatBotState = useAIChatBot() as AIChatBotStateTypes
|
||||
|
||||
|
|
|
|||
|
|
@ -20,12 +20,15 @@ import toast from 'react-hot-toast'
|
|||
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTime from 'dayjs/plugin/relativeTime';
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
dayjs.extend(relativeTime);
|
||||
|
||||
function CourseUpdates() {
|
||||
const course = useCourse() as any;
|
||||
const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, swrFetcher)
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, (url) => swrFetcher(url, access_token))
|
||||
const [isModelOpen, setIsModelOpen] = React.useState(false)
|
||||
|
||||
function handleModelOpen() {
|
||||
|
|
@ -71,7 +74,7 @@ function CourseUpdates() {
|
|||
|
||||
const UpdatesSection = () => {
|
||||
const [selectedView, setSelectedView] = React.useState('list')
|
||||
const isAdmin = useAdminStatus() as boolean;
|
||||
const adminStatus = useAdminStatus() ;
|
||||
return (
|
||||
<div className='bg-white/95 backdrop-blur-md nice-shadow rounded-lg w-[700px] overflow-hidden'>
|
||||
<div className='bg-gray-50/70 flex justify-between outline outline-1 rounded-lg outline-neutral-200/40'>
|
||||
|
|
@ -80,7 +83,7 @@ const UpdatesSection = () => {
|
|||
<span>Updates</span>
|
||||
|
||||
</div>
|
||||
{isAdmin && <div
|
||||
{adminStatus.isAdmin && <div
|
||||
onClick={() => setSelectedView('new')}
|
||||
className='py-2 px-4 space-x-2 items-center flex cursor-pointer text-xs font-medium hover:bg-gray-200 bg-gray-100 outline outline-1 outline-neutral-200/40'>
|
||||
<PencilLine size={14} />
|
||||
|
|
@ -98,6 +101,7 @@ const UpdatesSection = () => {
|
|||
const NewUpdateForm = ({ setSelectedView }: any) => {
|
||||
const org = useOrg() as any;
|
||||
const course = useCourse() as any;
|
||||
const session = useLHSession() as any;
|
||||
|
||||
const validate = (values: any) => {
|
||||
const errors: any = {}
|
||||
|
|
@ -124,7 +128,7 @@ const NewUpdateForm = ({ setSelectedView }: any) => {
|
|||
course_uuid: course.courseStructure.course_uuid,
|
||||
org_id: org.id
|
||||
}
|
||||
const res = await createCourseUpdate(body)
|
||||
const res = await createCourseUpdate(body, session.data?.tokens?.access_token)
|
||||
if (res.status === 200) {
|
||||
toast.success('Update added successfully')
|
||||
setSelectedView('list')
|
||||
|
|
@ -192,23 +196,25 @@ const NewUpdateForm = ({ setSelectedView }: any) => {
|
|||
|
||||
const UpdatesListView = () => {
|
||||
const course = useCourse() as any;
|
||||
const isAdmin = useAdminStatus() as boolean;
|
||||
const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`, swrFetcher)
|
||||
const adminStatus = useAdminStatus() ;
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const { data: updates } = useSWR(`${getAPIUrl()}courses/${course?.courseStructure?.course_uuid}/updates`, (url) => swrFetcher(url, access_token))
|
||||
|
||||
return (
|
||||
<div className='px-5 bg-white overflow-y-auto' style={{ maxHeight: '400px' }}>
|
||||
{updates && updates.map((update: any) => (
|
||||
{updates && !adminStatus.loading && updates.map((update: any) => (
|
||||
<div key={update.id} className='py-2 border-b border-neutral-200 antialiased'>
|
||||
<div className='font-bold text-gray-500 flex space-x-2 items-center justify-between '>
|
||||
<div className='flex space-x-2 items-center'>
|
||||
<span> {update.title}</span>
|
||||
<span
|
||||
title={"Created at " + dayjs(update.creation_date).format('MMMM D, YYYY')}
|
||||
className='text-xs font-semibold text-gray-300'>
|
||||
{dayjs(update.creation_date).fromNow()}
|
||||
<span
|
||||
title={"Created at " + dayjs(update.creation_date).format('MMMM D, YYYY')}
|
||||
className='text-xs font-semibold text-gray-300'>
|
||||
{dayjs(update.creation_date).fromNow()}
|
||||
</span>
|
||||
</div>
|
||||
{isAdmin && <DeleteUpdateButton update={update} />}</div>
|
||||
{adminStatus.isAdmin && !adminStatus.loading && <DeleteUpdateButton update={update} />}</div>
|
||||
<div className='text-gray-600'>{update.content}</div>
|
||||
</div>
|
||||
))}
|
||||
|
|
@ -223,11 +229,12 @@ const UpdatesListView = () => {
|
|||
}
|
||||
|
||||
const DeleteUpdateButton = ({ update }: any) => {
|
||||
const session = useLHSession() as any;
|
||||
const course = useCourse() as any;
|
||||
const org = useOrg() as any;
|
||||
|
||||
const handleDelete = async () => {
|
||||
const res = await deleteCourseUpdate(course.courseStructure.course_uuid, update.courseupdate_uuid)
|
||||
const res = await deleteCourseUpdate(course.courseStructure.course_uuid, update.courseupdate_uuid, session.data?.tokens?.access_token)
|
||||
if (res.status === 200) {
|
||||
toast.success('Update deleted successfully')
|
||||
mutate(`${getAPIUrl()}courses/${course?.courseStructure.course_uuid}/updates`)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import React, { useEffect, useState } from 'react'
|
||||
import UserAvatar from '../UserAvatar'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { getUserAvatarMediaDirectory } from '@services/media/media';
|
||||
import { getCollaborationServerUrl } from '@services/config/config';
|
||||
import { useOrg } from '@components/Contexts/OrgContext';
|
||||
|
|
@ -11,7 +11,7 @@ type ActiveAvatarsProps = {
|
|||
}
|
||||
|
||||
function ActiveAvatars(props: ActiveAvatarsProps) {
|
||||
const session = useSession() as any;
|
||||
const session = useLHSession() as any;
|
||||
const org = useOrg() as any;
|
||||
const [activeUsers, setActiveUsers] = useState({} as any);
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ import html from 'highlight.js/lib/languages/xml'
|
|||
import python from 'highlight.js/lib/languages/python'
|
||||
import java from 'highlight.js/lib/languages/java'
|
||||
import { CourseProvider } from '@components/Contexts/CourseContext'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import AIEditorToolkit from './AI/AIEditorToolkit'
|
||||
import useGetAIFeatures from '@components/AI/Hooks/useGetAIFeatures'
|
||||
import UserAvatar from '../UserAvatar'
|
||||
|
|
@ -65,7 +65,7 @@ interface Editor {
|
|||
}
|
||||
|
||||
function Editor(props: Editor) {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const dispatchAIEditor = useAIEditorDispatch() as any
|
||||
const aiEditorState = useAIEditor() as AIEditorStateTypes
|
||||
const is_ai_feature_enabled = useGetAIFeatures({ feature: 'editor' })
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { updateActivity } from '@services/courses/activities'
|
|||
import { toast } from 'react-hot-toast'
|
||||
import Toast from '@components/StyledElements/Toast/Toast'
|
||||
import { OrgProvider } from '@components/Contexts/OrgContext'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
// Collaboration
|
||||
import { HocuspocusProvider } from '@hocuspocus/provider'
|
||||
|
|
@ -24,7 +24,7 @@ interface EditorWrapperProps {
|
|||
}
|
||||
|
||||
function EditorWrapper(props: EditorWrapperProps): JSX.Element {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
// Define provider in the state
|
||||
const [provider, setProvider] = React.useState<HocuspocusProvider | null>(null);
|
||||
const [thisPageColor, setThisPageColor] = useState(randomColor({ luminosity: 'light' }) as string)
|
||||
|
|
|
|||
|
|
@ -7,15 +7,15 @@ import MenuLinks from './MenuLinks'
|
|||
import { getOrgLogoMediaDirectory } from '@services/media/media'
|
||||
import useSWR from 'swr'
|
||||
import { swrFetcher } from '@services/utils/ts/requests'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
|
||||
export const Menu = (props: any) => {
|
||||
const orgslug = props.orgslug
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const [feedbackModal, setFeedbackModal] = React.useState(false)
|
||||
const {
|
||||
data: org,
|
||||
error: error,
|
||||
isLoading,
|
||||
} = useSWR(`${getAPIUrl()}orgs/slug/${orgslug}`, swrFetcher)
|
||||
const org = useOrg() as any;
|
||||
|
||||
function closeFeedbackModal() {
|
||||
setFeedbackModal(false)
|
||||
|
|
|
|||
|
|
@ -15,9 +15,11 @@ import React, { useState } from 'react'
|
|||
import { BarLoader } from 'react-spinners'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
function CreateCourseModal({ closeModal, orgslug }: any) {
|
||||
const [isSubmitting, setIsSubmitting] = useState(false)
|
||||
const session = useLHSession()
|
||||
const [name, setName] = React.useState('')
|
||||
const [description, setDescription] = React.useState('')
|
||||
const [learnings, setLearnings] = React.useState('')
|
||||
|
|
@ -71,7 +73,8 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
|
|||
let status = await createNewCourse(
|
||||
orgId,
|
||||
{ name, description, tags, visibility },
|
||||
thumbnail
|
||||
thumbnail,
|
||||
session.data?.tokens?.access_token
|
||||
)
|
||||
await revalidateTags(['courses'], orgslug)
|
||||
setIsSubmitting(false)
|
||||
|
|
@ -80,9 +83,6 @@ function CreateCourseModal({ closeModal, orgslug }: any) {
|
|||
closeModal()
|
||||
router.refresh()
|
||||
await revalidateTags(['courses'], orgslug)
|
||||
|
||||
// refresh page (FIX for Next.js BUG)
|
||||
// window.location.reload();
|
||||
} else {
|
||||
alert('Error creating course, please see console logs')
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { getAPIUrl } from '@services/config/config'
|
|||
import { createInviteCode, createInviteCodeWithUserGroup } from '@services/organizations/invites'
|
||||
import { swrFetcher } from '@services/utils/ts/requests'
|
||||
import { Shield, Ticket } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import React, { useEffect } from 'react'
|
||||
import toast from 'react-hot-toast'
|
||||
import useSWR, { mutate } from 'swr'
|
||||
|
|
@ -13,6 +14,7 @@ type OrgInviteCodeGenerateProps = {
|
|||
|
||||
function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
||||
const org = useOrg() as any
|
||||
const session = useLHSession()
|
||||
const [usergroup_id, setUsergroup_id] = React.useState(0);
|
||||
const { data: usergroups } = useSWR(
|
||||
org ? `${getAPIUrl()}usergroups/org/${org.id}` : null,
|
||||
|
|
@ -20,7 +22,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
|||
)
|
||||
|
||||
async function createInviteWithUserGroup() {
|
||||
let res = await createInviteCodeWithUserGroup(org.id, usergroup_id)
|
||||
let res = await createInviteCodeWithUserGroup(org.id, usergroup_id, session.data?.tokens?.access_token)
|
||||
if (res.status == 200) {
|
||||
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
||||
props.setInvitesModal(false)
|
||||
|
|
@ -30,7 +32,7 @@ function OrgInviteCodeGenerate(props: OrgInviteCodeGenerateProps) {
|
|||
}
|
||||
|
||||
async function createInvite() {
|
||||
let res = await createInviteCode(org.id)
|
||||
let res = await createInviteCode(org.id, session.data?.tokens?.access_token)
|
||||
if (res.status == 200) {
|
||||
mutate(`${getAPIUrl()}orgs/${org.id}/invites`)
|
||||
props.setInvitesModal(false)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { deleteCollection } from '@services/courses/collections'
|
|||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { X } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React from 'react'
|
||||
|
|
@ -74,9 +75,10 @@ function CollectionThumbnail(props: PropsType) {
|
|||
|
||||
const CollectionAdminEditsArea = (props: any) => {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() ;
|
||||
|
||||
const deleteCollectionUI = async (collectionId: number) => {
|
||||
await deleteCollection(collectionId)
|
||||
await deleteCollection(collectionId, session.data?.tokens?.access_token)
|
||||
await revalidateTags(['collections'], props.orgslug)
|
||||
// reload the page
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import { deleteCourseFromBackend } from '@services/courses/courses'
|
|||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { Settings, X } from 'lucide-react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React, { useEffect } from 'react'
|
||||
|
|
@ -24,15 +25,16 @@ function removeCoursePrefix(course_uuid: string) {
|
|||
function CourseThumbnail(props: PropsType) {
|
||||
const router = useRouter()
|
||||
const org = useOrg() as any
|
||||
const session = useLHSession();
|
||||
|
||||
async function deleteCourses(course_uuid: any) {
|
||||
await deleteCourseFromBackend(course_uuid)
|
||||
await deleteCourseFromBackend(course_uuid, session.data?.tokens?.access_token)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
|
||||
router.refresh()
|
||||
}
|
||||
|
||||
useEffect(() => {}, [org])
|
||||
useEffect(() => { }, [org])
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
|
|
@ -92,8 +94,8 @@ const AdminEditsArea = (props: {
|
|||
href={getUriWithOrg(
|
||||
props.orgSlug,
|
||||
'/dash/courses/course/' +
|
||||
removeCoursePrefix(props.courseId) +
|
||||
'/general'
|
||||
removeCoursePrefix(props.courseId) +
|
||||
'/general'
|
||||
)}
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import React, { useEffect } from 'react'
|
|||
import { getUriWithOrg } from '@services/config/config'
|
||||
import { useParams } from 'next/navigation'
|
||||
import { getUserAvatarMediaDirectory } from '@services/media/media'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
type UserAvatarProps = {
|
||||
width?: number
|
||||
|
|
@ -20,7 +20,7 @@ type UserAvatarProps = {
|
|||
}
|
||||
|
||||
function UserAvatar(props: UserAvatarProps) {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const params = useParams() as any
|
||||
|
||||
function checkUrlProtocol(url: string): boolean {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import { revalidateTags } from '@services/utils/ts/requests'
|
|||
import { useRouter } from 'next/navigation'
|
||||
import ConfirmationModal from '@components/StyledElements/ConfirmationModal/ConfirmationModal'
|
||||
import { deleteActivity, updateActivity } from '@services/courses/activities'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
interface ModifiedActivityInterface {
|
||||
activityId: string
|
||||
|
|
@ -25,6 +26,7 @@ interface ModifiedActivityInterface {
|
|||
|
||||
function Activity(props: any) {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() as any;
|
||||
const [modifiedActivity, setModifiedActivity] = React.useState<
|
||||
ModifiedActivityInterface | undefined
|
||||
>(undefined)
|
||||
|
|
@ -33,7 +35,7 @@ function Activity(props: any) {
|
|||
>(undefined)
|
||||
|
||||
async function removeActivity() {
|
||||
await deleteActivity(props.activity.id)
|
||||
await deleteActivity(props.activity.id, session.data?.tokens?.access_token)
|
||||
mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
@ -52,7 +54,7 @@ function Activity(props: any) {
|
|||
content: props.activity.content,
|
||||
}
|
||||
|
||||
await updateActivity(modifiedActivityCopy, activityId)
|
||||
await updateActivity(modifiedActivityCopy, activityId, session.data?.tokens?.access_token)
|
||||
await mutate(`${getAPIUrl()}chapters/meta/course_${props.courseid}`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import { updateChapter } from '@services/courses/chapters'
|
|||
import { mutate } from 'swr'
|
||||
import { getAPIUrl } from '@services/config/config'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
interface ModifiedChapterInterface {
|
||||
chapterId: string
|
||||
|
|
@ -17,6 +18,7 @@ interface ModifiedChapterInterface {
|
|||
|
||||
function Chapter(props: any) {
|
||||
const router = useRouter()
|
||||
const session = useLHSession() as any;
|
||||
const [modifiedChapter, setModifiedChapter] = React.useState<
|
||||
ModifiedChapterInterface | undefined
|
||||
>(undefined)
|
||||
|
|
@ -30,7 +32,7 @@ function Chapter(props: any) {
|
|||
let modifiedChapterCopy = {
|
||||
name: modifiedChapter.chapterName,
|
||||
}
|
||||
await updateChapter(chapterId, modifiedChapterCopy)
|
||||
await updateChapter(chapterId, modifiedChapterCopy, session.data?.tokens?.access_token)
|
||||
await mutate(`${getAPIUrl()}chapters/course/${props.course_uuid}/meta`)
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { getAPIUrl, getUriWithOrg } from '@services/config/config'
|
|||
import { removeCourse } from '@services/courses/activity'
|
||||
import { getCourseThumbnailMediaDirectory } from '@services/media/media'
|
||||
import { revalidateTags } from '@services/utils/ts/requests'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import { useEffect } from 'react'
|
||||
|
|
@ -17,6 +18,8 @@ interface TrailCourseElementProps {
|
|||
|
||||
function TrailCourseElement(props: TrailCourseElementProps) {
|
||||
const org = useOrg() as any
|
||||
const session = useLHSession() as any;
|
||||
const access_token = session?.data?.tokens?.access_token;
|
||||
const courseid = props.course.course_uuid.replace('course_', '')
|
||||
const course = props.course
|
||||
const router = useRouter()
|
||||
|
|
@ -29,7 +32,7 @@ function TrailCourseElement(props: TrailCourseElementProps) {
|
|||
|
||||
async function quitCourse(course_uuid: string) {
|
||||
// Close activity
|
||||
let activity = await removeCourse(course_uuid, props.orgslug)
|
||||
let activity = await removeCourse(course_uuid, props.orgslug,access_token)
|
||||
// Mutate course
|
||||
await revalidateTags(['courses'], props.orgslug)
|
||||
router.refresh()
|
||||
|
|
|
|||
|
|
@ -1,15 +1,14 @@
|
|||
'use client'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
||||
import { usePathname, useRouter } from 'next/navigation'
|
||||
import React from 'react'
|
||||
'use client';
|
||||
import React, { useEffect, useState, useCallback, useMemo } from 'react';
|
||||
import { useOrg } from '@components/Contexts/OrgContext';
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext';
|
||||
import useAdminStatus from '@components/Hooks/useAdminStatus';
|
||||
import { usePathname, useRouter } from 'next/navigation';
|
||||
|
||||
type AuthorizationProps = {
|
||||
children: React.ReactNode
|
||||
// Authorize components rendering or page rendering
|
||||
authorizationMode: 'component' | 'page'
|
||||
}
|
||||
children: React.ReactNode;
|
||||
authorizationMode: 'component' | 'page';
|
||||
};
|
||||
|
||||
const ADMIN_PATHS = [
|
||||
'/dash/org/*',
|
||||
|
|
@ -19,106 +18,71 @@ const ADMIN_PATHS = [
|
|||
'/dash/courses/*',
|
||||
'/dash/courses',
|
||||
'/dash/org/settings/general',
|
||||
]
|
||||
];
|
||||
|
||||
function AdminAuthorization(props: AuthorizationProps) {
|
||||
const session = useSession() as any
|
||||
const org = useOrg() as any
|
||||
const pathname = usePathname()
|
||||
const router = useRouter()
|
||||
const AdminAuthorization: React.FC<AuthorizationProps> = ({ children, authorizationMode }) => {
|
||||
const session = useLHSession() as any;
|
||||
const pathname = usePathname();
|
||||
const router = useRouter();
|
||||
const { isAdmin, loading } = useAdminStatus() as any
|
||||
const [isAuthorized, setIsAuthorized] = useState(false);
|
||||
|
||||
// States
|
||||
const [isLoading, setIsLoading] = React.useState(true)
|
||||
const [isAuthorized, setIsAuthorized] = React.useState(false)
|
||||
const isUserAuthenticated = useMemo(() => session.status === 'authenticated', [session.status]);
|
||||
|
||||
// Verify if the user is authenticated
|
||||
const isUserAuthenticated = () => {
|
||||
if (session.status === 'authenticated') {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
const checkPathname = useCallback((pattern: string, pathname: string) => {
|
||||
const regexPattern = new RegExp(`^${pattern.replace(/\//g, '\\/').replace(/\*/g, '.*')}$`);
|
||||
return regexPattern.test(pathname);
|
||||
}, []);
|
||||
|
||||
const isAdminPath = useMemo(() => ADMIN_PATHS.some(path => checkPathname(path, pathname)), [pathname, checkPathname]);
|
||||
|
||||
const authorizeUser = useCallback(() => {
|
||||
if (loading) {
|
||||
return; // Wait until the admin status is determined
|
||||
}
|
||||
}
|
||||
|
||||
// Verify if the user is an Admin (1), Maintainer (2) or Member (3) of the organization
|
||||
const isUserAdmin = useAdminStatus()
|
||||
if (!isUserAuthenticated) {
|
||||
router.push('/login');
|
||||
return;
|
||||
}
|
||||
|
||||
function checkPathname(pattern: string, pathname: string) {
|
||||
// Escape special characters in the pattern and replace '*' with a regex pattern
|
||||
const regexPattern = new RegExp(
|
||||
`^${pattern.replace(/\//g, '\\/').replace(/\*/g, '.*')}$`
|
||||
)
|
||||
|
||||
// Test if the pathname matches the regex pattern
|
||||
const isMatch = regexPattern.test(pathname)
|
||||
|
||||
return isMatch
|
||||
}
|
||||
|
||||
const Authorize = () => {
|
||||
if (props.authorizationMode === 'page') {
|
||||
// Check if user is in an admin path
|
||||
if (ADMIN_PATHS.some((path) => checkPathname(path, pathname))) {
|
||||
if (isUserAuthenticated()) {
|
||||
// Check if the user is an Admin
|
||||
if (isUserAdmin) {
|
||||
setIsAuthorized(true)
|
||||
} else {
|
||||
setIsAuthorized(false)
|
||||
router.push('/dash')
|
||||
}
|
||||
if (authorizationMode === 'page') {
|
||||
if (isAdminPath) {
|
||||
if (isAdmin) {
|
||||
setIsAuthorized(true);
|
||||
} else {
|
||||
router.push('/login')
|
||||
setIsAuthorized(false);
|
||||
router.push('/dash');
|
||||
}
|
||||
} else {
|
||||
if (isUserAuthenticated()) {
|
||||
setIsAuthorized(true)
|
||||
} else {
|
||||
setIsAuthorized(false)
|
||||
router.push('/login')
|
||||
}
|
||||
setIsAuthorized(true);
|
||||
}
|
||||
} else if (authorizationMode === 'component') {
|
||||
setIsAuthorized(isAdmin);
|
||||
}
|
||||
}, [loading, isUserAuthenticated, isAdmin, isAdminPath, authorizationMode, router]);
|
||||
|
||||
if (props.authorizationMode === 'component') {
|
||||
// Component mode
|
||||
if (isUserAuthenticated() && isUserAdmin) {
|
||||
setIsAuthorized(true)
|
||||
} else {
|
||||
setIsAuthorized(false)
|
||||
}
|
||||
}
|
||||
useEffect(() => {
|
||||
authorizeUser();
|
||||
}, [authorizeUser]);
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<div className="flex justify-center items-center h-screen">
|
||||
<h1 className="text-2xl">Loading...</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (session.status == 'loading') {
|
||||
return
|
||||
}
|
||||
if (authorizationMode === 'page' && !isAuthorized) {
|
||||
return (
|
||||
<div className="flex justify-center items-center h-screen">
|
||||
<h1 className="text-2xl">You are not authorized to access this page</h1>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Authorize()
|
||||
setIsLoading(false)
|
||||
}, [session, org, pathname])
|
||||
return <>{isAuthorized && children}</>;
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
{props.authorizationMode === 'component' &&
|
||||
isAuthorized === true &&
|
||||
props.children}
|
||||
{props.authorizationMode === 'page' &&
|
||||
isAuthorized === true &&
|
||||
!isLoading &&
|
||||
props.children}
|
||||
{props.authorizationMode === 'page' &&
|
||||
isAuthorized === false &&
|
||||
!isLoading && (
|
||||
<div className="flex justify-center items-center h-screen">
|
||||
<h1 className="text-2xl">
|
||||
You are not authorized to access this page
|
||||
</h1>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default AdminAuthorization
|
||||
export default AdminAuthorization;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
'use client'
|
||||
import React from 'react'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
import { useOrg } from '@components/Contexts/OrgContext'
|
||||
|
||||
interface AuthenticatedClientElementProps {
|
||||
|
|
@ -20,7 +20,7 @@ export const AuthenticatedClientElement = (
|
|||
props: AuthenticatedClientElementProps
|
||||
) => {
|
||||
const [isAllowed, setIsAllowed] = React.useState(false)
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const org = useOrg() as any
|
||||
|
||||
function isUserAllowed(
|
||||
|
|
@ -49,13 +49,13 @@ export const AuthenticatedClientElement = (
|
|||
}
|
||||
|
||||
function check() {
|
||||
if (session.status == 'authenticated') {
|
||||
if (session.status == 'unauthenticated') {
|
||||
setIsAllowed(false)
|
||||
return
|
||||
} else {
|
||||
if (props.checkMethod === 'authentication') {
|
||||
setIsAllowed(session.status == 'authenticated')
|
||||
} else if (props.checkMethod === 'roles' && session.status == 'authenticated') {
|
||||
} else if (props.checkMethod === 'roles' ) {
|
||||
return setIsAllowed(
|
||||
isUserAllowed(
|
||||
session?.data?.roles,
|
||||
|
|
@ -74,7 +74,7 @@ export const AuthenticatedClientElement = (
|
|||
}
|
||||
|
||||
check()
|
||||
}, [session, org])
|
||||
}, [session.data, org])
|
||||
|
||||
return <>{isAllowed && props.children}</>
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import Link from 'next/link'
|
|||
import { Settings } from 'lucide-react'
|
||||
import UserAvatar from '@components/Objects/UserAvatar'
|
||||
import useAdminStatus from '@components/Hooks/useAdminStatus'
|
||||
import { useSession } from 'next-auth/react'
|
||||
import { useLHSession } from '@components/Contexts/LHSessionContext'
|
||||
|
||||
export const HeaderProfileBox = () => {
|
||||
const session = useSession() as any
|
||||
const session = useLHSession() as any
|
||||
const isUserAdmin = useAdminStatus() as any
|
||||
|
||||
useEffect(() => {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue