Add proper permission check

This commit is contained in:
Sianida26 2024-01-29 00:51:28 +07:00
parent c044f50b19
commit 152d444067
3 changed files with 56 additions and 35 deletions

View File

@ -73,6 +73,8 @@ export async function getUserFromToken(token: string) {
const user = await prisma.user.findFirst({
include:{
photoProfile: true,
roles: true,
directPermissions: true
},
where: {
id: decodedToken.id,

View File

@ -1,31 +1,31 @@
import { getUserFromToken } from "../authUtils";
import checkPermission from "./checkPermission";
import getCurrentUser from "./getCurrentUser";
type PermissionsInput = Record<string, string>;
type PermissionsOutput = Record<string, boolean>;
/**
* Checks multiple permissions for the current user and returns an object indicating
* whether each permission is granted.
*
* @param {PermissionsInput} permissions - An object with keys as permission names and values as the required roles/permissions.
* @returns {Promise<PermissionsOutput>} An object with keys as permission names and boolean values indicating whether the permission is granted.
*
* @param permissions - An object with keys as permission names and values as the required roles/permissions.
* @returns An object with keys as permission names and boolean values indicating whether the permission is granted.
*/
async function checkMultiplePermissions<T extends Record<string, string>>(permissions: T): Promise<{ [K in keyof T]: boolean }> {
const permissionResults: Partial<{ [K in keyof T]: boolean }> = {};
const currentUser = await getCurrentUser();
async function checkMultiplePermissions<T extends Record<string, string>>(
permissions: T
): Promise<{ [K in keyof T]: boolean }> {
const permissionResults: Partial<{ [K in keyof T]: boolean }> = {};
const currentUser = await getCurrentUser();
for (const permissionKey in permissions) {
if (permissions.hasOwnProperty(permissionKey)) {
const requiredPermission = permissions[permissionKey];
// const isPermissionGranted: boolean = currentUser ? currentUser.roles.includes(requiredPermission) : false;
const isPermissionGranted = true;
permissionResults[permissionKey] = isPermissionGranted;
}
}
for (const permissionKey in permissions) {
if (permissions.hasOwnProperty(permissionKey)) {
const requiredPermission = permissions[permissionKey];
const isPermissionGranted = await checkPermission(
requiredPermission,
currentUser
);
permissionResults[permissionKey] = isPermissionGranted;
}
}
return permissionResults as { [K in keyof T]: boolean };
return permissionResults as { [K in keyof T]: boolean };
}
export default checkMultiplePermissions;

View File

@ -1,23 +1,42 @@
import { cookies } from "next/headers"
import "server-only"
import { getUserFromToken } from "../authUtils";
import getCurrentUser from "./getCurrentUser";
import "server-only";
export default async function checkPermission(permission?: "guest-only" | "authenticated-only" | string & {}){
//TODO: Add permission check
/**
* Checks if the current user has the specified permissions.
*
* @param permission - The specific permission to check. If it's "guest-only", the function returns true if the user is not authenticated. If it's "authenticated-only", it returns true if the user is authenticated. For other permissions, it checks against the user's roles and direct permissions.
* @param currentUser - Optional. The current user object. If not provided, the function retrieves the current user.
* @returns true if the user has the required permission, otherwise false.
*/
export default async function checkPermission(
permission?: "guest-only" | "authenticated-only" | (string & {}),
currentUser?: Awaited<ReturnType<typeof getCurrentUser>>
): Promise<boolean> {
// Allow if no specific permission is required.
if (!permission) return true;
// Retrieve current user if not provided.
const user = currentUser ?? (await getCurrentUser());
if (!permission) return true; //allow if no permission supplied
// Handle non-authenticated users.
if (!user) {
return permission === "guest-only";
}
const user = await getCurrentUser()
// Allow authenticated users if the permission is 'authenticated-only'.
if (permission === "authenticated-only") {
return true;
}
if (!user && permission === "guest-only"){
return true;
}
// Short-circuit for super-admin role to allow all permissions.
if (user.roles.some((role) => role.code === "super-admin")) return true;
if (user && permission === "authenticated-only"){
return true;
}
// Aggregate all role codes and direct permissions into a set for efficient lookup.
const permissions = new Set<string>([
...user.roles.map((role) => role.code),
...user.directPermissions.map((dp) => dp.code),
]);
return true;
}
// Check if the user has the required permission.
return permissions.has(permission);
}