Added documentation
This commit is contained in:
parent
e6ffe4112d
commit
cb3969ac40
|
|
@ -1,34 +1,31 @@
|
|||
"use server";
|
||||
|
||||
import "server-only";
|
||||
import AuthError from "../error/AuthError";
|
||||
import getMyDetail from "../services/getMyDetail";
|
||||
import AuthError from "../error/AuthError";
|
||||
import BaseError from "@/core/error/BaseError";
|
||||
import ServerResponseAction from "@/modules/dashboard/types/ServerResponseAction";
|
||||
import handleCatch from "@/modules/dashboard/utils/handleCatch";
|
||||
import BaseError from "@/core/error/BaseError";
|
||||
import "server-only";
|
||||
|
||||
/**
|
||||
* Retrieves the user details based on the JWT token from cookies.
|
||||
* This function is designed to be used in a server-side context within a Next.js application.
|
||||
* It attempts to parse the user's token, fetch the user's details, and format the response.
|
||||
* If the token is invalid or the user cannot be found, it gracefully handles these cases.
|
||||
* Asynchronously retrieves the authenticated user's details from a server-side context in a Next.js application.
|
||||
* This function uses a JWT token obtained from cookies to authenticate the user and fetch their details.
|
||||
* If the authentication fails due to an invalid JWT token, or if any other error occurs, the function handles these errors gracefully.
|
||||
*
|
||||
* @returns A promise that resolves to the user's details object or null if the user cannot be authenticated or an error occurs.
|
||||
* @throws an error if an unexpected error occurs during execution.
|
||||
* @returns A promise that resolves to a `ServerResponseAction` object. This object includes a `success` flag indicating the operation's outcome, the user's details in the `data` field if successful, or an error object in the `error` field if an error occurs.
|
||||
* @throws an unhandled error if an unexpected error occurs during the function execution.
|
||||
*/
|
||||
export default async function getMyDetailAction(): Promise<
|
||||
ServerResponseAction<Awaited<ReturnType<typeof getMyDetail>>>
|
||||
> {
|
||||
export default async function getMyDetailAction(): Promise<ServerResponseAction<Awaited<ReturnType<typeof getMyDetail>>>> {
|
||||
try {
|
||||
// Attempt to fetch and return the user's details.
|
||||
const userDetails = await getMyDetail();
|
||||
return {
|
||||
success: true,
|
||||
data: await getMyDetail(),
|
||||
data: userDetails,
|
||||
};
|
||||
} catch (e: unknown) {
|
||||
if (
|
||||
e instanceof AuthError &&
|
||||
["INVALID_JWT_TOKEN"].includes(e.errorCode)
|
||||
) {
|
||||
// Check if the error is an instance of AuthError and handle it.
|
||||
if (e instanceof AuthError && e.errorCode === "INVALID_JWT_TOKEN") {
|
||||
return {
|
||||
success: false,
|
||||
error: new BaseError({
|
||||
|
|
@ -37,6 +34,7 @@ export default async function getMyDetailAction(): Promise<
|
|||
}),
|
||||
};
|
||||
}
|
||||
// Handle other types of errors.
|
||||
return handleCatch(e);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,20 @@
|
|||
"use server";
|
||||
|
||||
import { redirect } from "next/navigation";
|
||||
import getUser from "./getMyDetailAction";
|
||||
import getMyDetail from "../services/getMyDetail";
|
||||
|
||||
export default async function guestOnly() {
|
||||
const user = await getUser();
|
||||
/**
|
||||
* Enforces a guest-only access policy by redirecting authenticated users to the dashboard.
|
||||
* This function asynchronously checks if the user is authenticated by attempting to retrieve user details.
|
||||
* If the user is authenticated, they are redirected to the dashboard page.
|
||||
*
|
||||
* @returns A promise that resolves when the operation completes. The function itself does not return a value.
|
||||
*/
|
||||
export default async function guestOnly(): Promise<void> {
|
||||
const user = await getMyDetail();
|
||||
|
||||
// If an authenticated user is detected, redirect them to the dashboard.
|
||||
if (user) {
|
||||
redirect("dashboard");
|
||||
redirect("/dashboard");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,71 +1,90 @@
|
|||
// Directive to enforce client-side operation in a Next.js application.
|
||||
"use client";
|
||||
import React, {
|
||||
ReactElement,
|
||||
ReactNode,
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from "react";
|
||||
import getUser from "../actions/getMyDetailAction";
|
||||
import withServerAction from "@/modules/dashboard/utils/withServerAction";
|
||||
import getMyDetailAction from "../actions/getMyDetailAction";
|
||||
|
||||
// Importing React functionalities and required components.
|
||||
import React, { ReactElement, ReactNode, createContext, useCallback, useContext, useEffect, useState } from "react";
|
||||
import { notifications } from "@mantine/notifications";
|
||||
import getMyDetailAction from "../actions/getMyDetailAction";
|
||||
import withServerAction from "@/modules/dashboard/utils/withServerAction";
|
||||
|
||||
// Defining the structure for user data within the authentication context.
|
||||
interface UserData {
|
||||
name: string;
|
||||
email: string;
|
||||
photoUrl: string | null;
|
||||
// Add additional user fields as needed
|
||||
name: string;
|
||||
email: string;
|
||||
photoUrl: string | null;
|
||||
// Additional user fields can be added here.
|
||||
}
|
||||
|
||||
// State structure for the authentication context.
|
||||
interface AuthContextState {
|
||||
user: UserData | null;
|
||||
fetchUserData: () => void;
|
||||
logout: () => void;
|
||||
user: UserData | null;
|
||||
fetchUserData: () => void;
|
||||
logout: () => void;
|
||||
}
|
||||
|
||||
// Props type definition for the AuthContextProvider component.
|
||||
interface Props {
|
||||
children: ReactNode;
|
||||
children: ReactNode;
|
||||
}
|
||||
|
||||
// Creating the authentication context with an undefined initial value.
|
||||
const AuthContext = createContext<AuthContextState | undefined>(undefined);
|
||||
|
||||
export const AuthContextProvider = ({ children }: Props) => {
|
||||
const [user, setUser] = useState<UserData | null>(null);
|
||||
/**
|
||||
* Provides an authentication context to wrap around components that require authentication data.
|
||||
* This component initializes user data state, fetches user data upon component mount, and provides
|
||||
* a logout function to clear the user data.
|
||||
*
|
||||
* @param {Props} props - Component props containing children to be rendered within the provider.
|
||||
* @returns {ReactElement} A provider component wrapping children with access to authentication context.
|
||||
*/
|
||||
export const AuthContextProvider = ({ children }: Props): ReactElement => {
|
||||
const [user, setUser] = useState<UserData | null>(null);
|
||||
|
||||
const fetchUserData = useCallback(() => {
|
||||
|
||||
withServerAction(getMyDetailAction)
|
||||
.then((response) => {
|
||||
setUser(response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error("Error while retrieving user data")
|
||||
})
|
||||
}, []);
|
||||
// Function to fetch user data and update state accordingly.
|
||||
const fetchUserData = useCallback(() => {
|
||||
withServerAction(getMyDetailAction)
|
||||
.then((response) => {
|
||||
setUser(response.data);
|
||||
})
|
||||
.catch((error) => {
|
||||
notifications.show({
|
||||
title: 'Error',
|
||||
message: 'Error while retrieving user data',
|
||||
color: 'red',
|
||||
});
|
||||
console.error("Error while retrieving user data", error);
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
fetchUserData();
|
||||
}, [fetchUserData]);
|
||||
// Fetch user data on component mount.
|
||||
useEffect(() => {
|
||||
fetchUserData();
|
||||
}, [fetchUserData]);
|
||||
|
||||
const logout = () => {
|
||||
setUser(null);
|
||||
};
|
||||
// Function to clear user data, effectively logging the user out.
|
||||
const logout = () => {
|
||||
setUser(null);
|
||||
};
|
||||
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, fetchUserData, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
// Providing authentication state and functions to the context consumers.
|
||||
return (
|
||||
<AuthContext.Provider value={{ user, fetchUserData, logout }}>
|
||||
{children}
|
||||
</AuthContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export const useAuth = () => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth must be used within an AuthContextProvider");
|
||||
}
|
||||
return context;
|
||||
/**
|
||||
* Custom hook to consume the authentication context. This hook ensures the context is used within a provider.
|
||||
*
|
||||
* @returns {AuthContextState} The authentication context state including user data and auth functions.
|
||||
* @throws {Error} Throws an error if the hook is used outside of an AuthContextProvider.
|
||||
*/
|
||||
export const useAuth = (): AuthContextState => {
|
||||
const context = useContext(AuthContext);
|
||||
if (!context) {
|
||||
throw new Error("useAuth must be used within an AuthContextProvider");
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -10,6 +10,16 @@ import hashPassword from "../utils/hashPassword";
|
|||
import { createJwtToken } from "../utils/createJwtToken";
|
||||
import { cookies } from "next/headers";
|
||||
|
||||
/**
|
||||
* Creates a new user in the database after validating the input data.
|
||||
* It throws errors if the input data is invalid or if the user already exists.
|
||||
* On successful creation, it returns a token for the created user.
|
||||
*
|
||||
* @param userData - The user data to create a new user. Must conform to CreateUserSchema.
|
||||
* @returns An object containing the JWT token for the newly created user.
|
||||
* @throws If the input validation fails.
|
||||
* @throws If the user already exists in the database.
|
||||
*/
|
||||
export default async function createUser(userData: CreateUserSchema) {
|
||||
const validatedFields = createUserSchema.safeParse(userData);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,25 @@
|
|||
import { cookies } from "next/headers";
|
||||
import getUserFromToken from "../utils/getUserFromToken";
|
||||
|
||||
/**
|
||||
* Retrieves the details of the currently authenticated user based on the JWT token.
|
||||
* If the token is not present or the user cannot be found, it returns null.
|
||||
* Otherwise, it returns the user's name, email, and photo URL.
|
||||
*
|
||||
* @returns An object containing the user's name, email, and photo URL, or null if the user cannot be authenticated.
|
||||
*/
|
||||
export default async function getMyDetail() {
|
||||
const token = cookies().get("token");
|
||||
|
||||
// Return null if token is not present
|
||||
if (!token) return null;
|
||||
|
||||
const user = await getUserFromToken(token.value);
|
||||
|
||||
// Return null if user is not found
|
||||
if (!user) return null;
|
||||
|
||||
// Return user details
|
||||
return {
|
||||
name: user.name ?? "",
|
||||
email: user.email ?? "",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user