diff --git a/sigap-website/app/(pages)/(admin)/_components/settings/setting-dialog.tsx b/sigap-website/app/(pages)/(admin)/_components/settings/setting-dialog.tsx index 0be087c..731cf75 100644 --- a/sigap-website/app/(pages)/(admin)/_components/settings/setting-dialog.tsx +++ b/sigap-website/app/(pages)/(admin)/_components/settings/setting-dialog.tsx @@ -42,11 +42,13 @@ export function SettingsDialog({ trigger, defaultTab = "account", open, onOpenCh const [selectedTab, setSelectedTab] = useState(defaultTab) + if (!user || !user.profile) return
User not found
+ // Get user display name - const preferredName = user?.profile?.username || "" - const userEmail = user?.email || "" - const displayName = preferredName || userEmail?.split("@")[0] || "User" - const userAvatar = user?.profile?.avatar || "" + const preferredName = user.profile.username || "" + const userEmail = user.email || "" + const displayName = preferredName || userEmail.split("@")[0] || "User" + const userAvatar = user.profile.avatar || "" const sections: SettingsSection[] = [ { diff --git a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/cells/actions-cell.tsx b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/cells/actions-cell.tsx index 93c07ed..67a0041 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/cells/actions-cell.tsx +++ b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/cells/actions-cell.tsx @@ -1,6 +1,6 @@ // cells/actions-cell.tsx -import React, { useState } from "react" +import React, { useEffect, useState } from "react" import { MoreHorizontal, PenIcon as UserPen, Trash2, ShieldAlert, ShieldCheck } from "lucide-react" import { DropdownMenu, @@ -15,7 +15,10 @@ import { IUserSchema } from "@/src/entities/models/users/users.model" import { useUserActionsHandler } from "../../../_handlers/actions/use-user-actions" import { BanUserDialog } from "../../dialogs/ban-user-dialog" import { useCreateUserColumn } from "../../../_handlers/use-create-user-column" - +import { useCheckPermissionsHandler } from "@/app/(pages)/(auth)/_handlers/use-check-permissions" +import { useCheckPermissionsNewQuery } from "@/app/(pages)/(auth)/_queries/mutations" +import { useGetCurrentUserQuery } from "../../../_queries/queries" +import { Badge } from "@/app/_components/ui/badge" interface ActionsCellProps { user: IUserSchema @@ -23,7 +26,6 @@ interface ActionsCellProps { } export const ActionsCell: React.FC = ({ user, onUpdate }) => { - const { deleteDialogOpen, setDeleteDialogOpen, @@ -41,6 +43,13 @@ export const ActionsCell: React.FC = ({ user, onUpdate }) => { setSelectedUser, } = useCreateUserColumn() + const { data: currentUser, isPending } = useGetCurrentUserQuery() + + if (!currentUser) return user not found + + let { data: isAllowedToDelete } = useCheckPermissionsNewQuery(currentUser.email, "delete", "users") + let { data: isAllowedToUpdate } = useCheckPermissionsNewQuery(currentUser.email, "update", "users") + return (
e.stopPropagation()}> @@ -50,19 +59,24 @@ export const ActionsCell: React.FC = ({ user, onUpdate }) => { + {isAllowedToUpdate && ( onUpdate(user)}> Update - { - setSelectedUser({ id: user.id, email: user.email! }) - setDeleteDialogOpen(true) - }} - > - - Delete - + )} + {isAllowedToDelete && ( + { + setSelectedUser({ id: user.id, email: user.email! }) + setDeleteDialogOpen(true) + }} + > + + Delete + + )} + {isAllowedToUpdate && user.banned_until != null && ( { if (user.banned_until != null) { @@ -77,6 +91,7 @@ export const ActionsCell: React.FC = ({ user, onUpdate }) => { {user.banned_until != null ? "Unban" : "Ban"} + )} diff --git a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/actions-column.tsx b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/actions-column.tsx index 77c524d..2e1e373 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/actions-column.tsx +++ b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/actions-column.tsx @@ -1,5 +1,5 @@ // columns/actions-column.tsx -"use client" + import React from "react" import { IUserSchema } from "@/src/entities/models/users/users.model" diff --git a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/index.ts b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/index.ts index cfc9c50..3216fc7 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/index.ts +++ b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/columns/index.ts @@ -1,5 +1,5 @@ // columns/index.ts -"use client" + import type { ColumnDef } from "@tanstack/react-table" import { IUserSchema, IUserFilterOptionsSchema } from "@/src/entities/models/users/users.model" diff --git a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/filters/column-filter.tsx b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/filters/column-filter.tsx index 8421276..ea45b50 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/filters/column-filter.tsx +++ b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/table/filters/column-filter.tsx @@ -1,5 +1,5 @@ // filters/column-filter.tsx -"use client" + import React from "react" import { ListFilter } from "lucide-react" diff --git a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/user-management.tsx b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/user-management.tsx index f430c3f..4856947 100644 --- a/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/user-management.tsx +++ b/sigap-website/app/(pages)/(admin)/dashboard/user-management/_components/user-management.tsx @@ -1,43 +1,17 @@ "use client"; import { useState, useMemo, useEffect } from "react"; -import { - PlusCircle, - Search, - MoreHorizontal, - X, - ChevronDown, - UserPlus, - Mail, - ShieldAlert, - ListFilter, - Trash2, - PenIcon as UserPen, - ShieldCheck, -} from "lucide-react"; -import { Button } from "@/app/_components/ui/button"; -import { Input } from "@/app/_components/ui/input"; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuTrigger, -} from "@/app/_components/ui/dropdown-menu"; import { DataTable } from "../../../../../_components/data-table"; import { UserInformationSheet } from "./sheets/user-information-sheet"; import { useGetUsersQuery } from "../_queries/queries"; import { filterUsers, useUserManagementHandlers } from "../_handlers/use-user-management"; -import { UserDialogs } from "./dialogs/user-dialogs"; + import { useAddUserDialogHandler } from "../_handlers/use-add-user-dialog"; import { useInviteUserHandler } from "../_handlers/use-invite-user"; import { AddUserDialog } from "./dialogs/add-user-dialog"; import { InviteUserDialog } from "./dialogs/invite-user-dialog"; -import { ConfirmDialog } from "@/app/_components/confirm-dialog"; -import { BanUserDialog } from "./dialogs/ban-user-dialog"; -import { useBanUserHandler } from "../_handlers/actions/use-ban-user"; -import { useDeleteUserHandler } from "../_handlers/actions/use-delete-user"; -import { useUnbanUserHandler } from "../_handlers/actions/use-unban-user"; + import { createUserColumns } from "./table/columns"; import { UserManagementToolbar } from "./toolbars/user-management-toolbar"; import { UpdateUserSheet } from "./sheets/update-user-sheet"; diff --git a/sigap-website/app/(pages)/(auth)/_handlers/use-check-permissions.ts b/sigap-website/app/(pages)/(auth)/_handlers/use-check-permissions.ts index 1df8673..d3d8c36 100644 --- a/sigap-website/app/(pages)/(auth)/_handlers/use-check-permissions.ts +++ b/sigap-website/app/(pages)/(auth)/_handlers/use-check-permissions.ts @@ -8,7 +8,7 @@ export const useCheckPermissionsHandler = () => { } return { - handleCheckPermissions, + checkPermissions: handleCheckPermissions, isPending, } } \ No newline at end of file diff --git a/sigap-website/app/(pages)/(auth)/_queries/mutations.ts b/sigap-website/app/(pages)/(auth)/_queries/mutations.ts index 13fef9c..7fff4c2 100644 --- a/sigap-website/app/(pages)/(auth)/_queries/mutations.ts +++ b/sigap-website/app/(pages)/(auth)/_queries/mutations.ts @@ -1,51 +1,58 @@ -import { useMutation } from "@tanstack/react-query" -import { checkPermissions, sendMagicLink, sendPasswordRecovery, signInPasswordless, signInWithPassword, signOut, verifyOtp } from "../action" +import { useMutation, useQueries, useQuery } from "@tanstack/react-query" +import { checkPermissionNew, checkPermissions, sendMagicLink, sendPasswordRecovery, signInPasswordless, signInWithPassword, signOut, verifyOtp } from "../action" export const useSignInPasswordlessMutation = () => { return useMutation({ - mutationKey: ["signIn"], + mutationKey: ["signin"], mutationFn: async (formData: FormData) => await signInPasswordless(formData), }) } export const useSignInWithPasswordMutation = () => { return useMutation({ - mutationKey: ["signInWithCredentials"], + mutationKey: ["signin", "credentials"], mutationFn: async (formData: FormData) => await signInWithPassword(formData), }) } export const useSignOutMutation = () => { return useMutation({ - mutationKey: ["signOut"], + mutationKey: ["signout"], mutationFn: async () => await signOut(), }) } export const useSendMagicLinkMutation = () => { return useMutation({ - mutationKey: ["sendMagicLink"], + mutationKey: ["send-magic-link"], mutationFn: async (email: string) => await sendMagicLink(email), }) } export const useSendPasswordRecoveryMutation = () => { return useMutation({ - mutationKey: ["sendPasswordRecovery"], + mutationKey: ["send-password-recovery"], mutationFn: async (email: string) => await sendPasswordRecovery(email), }) } export const useVerifyOtpMutation = () => { return useMutation({ - mutationKey: ["verifyOtp"], + mutationKey: ["verify-otp"], mutationFn: async (formData: FormData) => await verifyOtp(formData), }) } export const useCheckPermissionsMutation = () => { return useMutation({ - mutationKey: ["checkPermissions"], + mutationKey: ["check-permissions"], mutationFn: async ({ userId, action, resource }: { userId: string; action: string; resource: string }) => await checkPermissions(userId, action, resource), }) -} \ No newline at end of file +} + +export const useCheckPermissionsNewQuery = (email: string, action: string, resource: string) => { + return useQuery({ + queryKey: ["check-permissions", email, action, resource], + queryFn: async () => await checkPermissionNew(email, action, resource), + }) +} diff --git a/sigap-website/app/(pages)/(auth)/action.ts b/sigap-website/app/(pages)/(auth)/action.ts index c61753c..145fa9e 100644 --- a/sigap-website/app/(pages)/(auth)/action.ts +++ b/sigap-website/app/(pages)/(auth)/action.ts @@ -7,6 +7,7 @@ import { revalidatePath } from "next/cache" import { InputParseError, NotFoundError } from "@/src/entities/errors/common" import { AuthenticationError, UnauthenticatedError } from "@/src/entities/errors/auth" import { createClient } from "@/app/_utils/supabase/server" +import db from "@/prisma/db"; export async function signInPasswordless(formData: FormData) { const instrumentationService = getInjection("IInstrumentationService") @@ -234,8 +235,77 @@ export async function checkPermissions(userId: string, action: string, resource: recordResponse: true }, async () => { try { - const checkPermissionsController = getInjection("ICheckPermissionsController") - return await checkPermissionsController({ userId, action, resource }) + + const user = await db.users.findUnique({ + where: { id: userId }, + include: { + role: true + } + }) + + console.log("Checking permissions for user:", user?.role.name, "action:", action, "resource:", resource) + + const permission = await db.permissions.findFirst({ + where: { + role_id: user?.role.id, + action: action, + resource: { + name: resource + } + } + }) + + return !!permission + + } catch (err) { + if (err instanceof InputParseError) { + return { error: err.message } + } + + const crashReporterService = getInjection("ICrashReporterService") + crashReporterService.report(err) + + return { + error: "An error occurred during permissions check. Please try again later.", + } + } + }) +} + +export async function checkPermissionNew(email: string, action: string, resource: string) { + const instrumentationService = getInjection("IInstrumentationService") + return await instrumentationService.instrumentServerAction("checkPermissionNew", { + recordResponse: true + }, async () => { + try { + + const user = await db.users.findUnique({ + where: { email }, + include: { role: true } + }) + + if (!user) { + return { error: "User not found" } + } + + console.log("Checking permissions for user:", user?.role.name, "action:", action, "resource:", resource) + + const permission = await db.permissions.findFirst({ + where: { + role_id: user.role.id, + action: action, + resource: { + name: resource + } + } + }) + + if (!permission) { + return false + } + + return !!permission + } catch (err) { if (err instanceof InputParseError) { return { error: err.message } diff --git a/sigap-website/di/modules/authentication.module.ts b/sigap-website/di/modules/authentication.module.ts index 52a2d79..3234494 100644 --- a/sigap-website/di/modules/authentication.module.ts +++ b/sigap-website/di/modules/authentication.module.ts @@ -96,6 +96,13 @@ export function createAuthenticationModule() { DI_SYMBOLS.IUsersRepository, ]); + authenticationModule + .bind(DI_SYMBOLS.ICheckPermissionsUseCase) + .toHigherOrderFunction(signUpUseCase, [ + DI_SYMBOLS.IInstrumentationService, + DI_SYMBOLS.IAuthenticationService, + ]); + // Controllers authenticationModule @@ -141,6 +148,15 @@ export function createAuthenticationModule() { DI_SYMBOLS.ISendPasswordRecoveryUseCase, ]); + authenticationModule + .bind(DI_SYMBOLS.ICheckPermissionsController) + .toHigherOrderFunction(signUpUseCase, [ + DI_SYMBOLS.IInstrumentationService, + DI_SYMBOLS.IAuthenticationService, + DI_SYMBOLS.IUsersRepository, + ]); + + return authenticationModule; } \ No newline at end of file diff --git a/sigap-website/di/types.ts b/sigap-website/di/types.ts index 5358d33..ae1b37b 100644 --- a/sigap-website/di/types.ts +++ b/sigap-website/di/types.ts @@ -77,6 +77,7 @@ import { IDeleteResourceController } from '@/src/interface-adapters/controllers/ import { IUpdateResourceController } from '@/src/interface-adapters/controllers/resources/update-resource.controller'; import { ICreateResourceController } from '@/src/interface-adapters/controllers/resources/create-resource.controller'; import { ICheckPermissionsUseCase } from '@/src/application/use-cases/auth/check-permissions.use-case'; +import { ISignInWithPasswordUseCase } from '@/src/application/use-cases/auth/sign-in-with-password.use-case'; // Pastikan DI_SYMBOLS memiliki tipe yang sesuai dengan DI_RETURN_TYPES export const DI_SYMBOLS: { [K in keyof DI_RETURN_TYPES]: symbol } = { @@ -96,6 +97,7 @@ export const DI_SYMBOLS: { [K in keyof DI_RETURN_TYPES]: symbol } = { // Auth Use Cases ISignInPasswordlessUseCase: Symbol.for('ISignInPasswordlessUseCase'), + ISignInWithPasswordUseCase: Symbol.for('ISignInWithPasswordUseCase'), ISignUpUseCase: Symbol.for('ISignUpUseCase'), IVerifyOtpUseCase: Symbol.for('IVerifyOtpUseCase'), ISignOutUseCase: Symbol.for('ISignOutUseCase'), @@ -204,6 +206,7 @@ export interface DI_RETURN_TYPES { // Auth Use Cases ISignInPasswordlessUseCase: ISignInPasswordlessUseCase; + ISignInWithPasswordUseCase: ISignInWithPasswordUseCase; ISignUpUseCase: ISignUpUseCase; IVerifyOtpUseCase: IVerifyOtpUseCase; ISignOutUseCase: ISignOutUseCase; diff --git a/sigap-website/src/application/repositories/users.repository.interface.ts b/sigap-website/src/application/repositories/users.repository.interface.ts index 8aa9e03..0378ba6 100644 --- a/sigap-website/src/application/repositories/users.repository.interface.ts +++ b/sigap-website/src/application/repositories/users.repository.interface.ts @@ -19,8 +19,8 @@ export interface IUsersRepository { createUser(input: ICreateUserSchema, tx?: ITransaction): Promise; inviteUser(credential: ICredentialsInviteUserSchema, tx?: ITransaction): Promise; updateUser(credential: ICredentialUpdateUserSchema, input: Partial, tx?: ITransaction): Promise; - deleteUser(credential: ICredentialsDeleteUserSchema, tx?: ITransaction): Promise; - banUser(credential: ICredentialsBanUserSchema, input: IBanUserSchema, tx?: ITransaction): Promise; - unbanUser(credential: ICredentialsUnbanUserSchema, tx?: ITransaction): Promise; + deleteUser(credential: ICredentialsDeleteUserSchema, tx?: ITransaction): Promise; + banUser(credential: ICredentialsBanUserSchema, input: IBanUserSchema, tx?: ITransaction): Promise; + unbanUser(credential: ICredentialsUnbanUserSchema, tx?: ITransaction): Promise; uploadAvatar(userId: string, file: File): Promise; } \ No newline at end of file diff --git a/sigap-website/src/entities/models/auth/session.model.ts b/sigap-website/src/entities/models/auth/session.model.ts index bebd641..6cbbebd 100644 --- a/sigap-website/src/entities/models/auth/session.model.ts +++ b/sigap-website/src/entities/models/auth/session.model.ts @@ -2,10 +2,10 @@ import { z } from "zod"; import { UserSchema } from "@/src/entities/models/users/users.model"; export const SessionSchema = z.object({ - user: UserSchema.pick({ - id: true, - email: true, - roles_id: true, + user: z.object({ + id: z.string(), + email: z.string().email().optional(), + role_id: z.string().optional(), }), expiresAt: z.number().optional(), }); diff --git a/sigap-website/src/entities/models/users/users.model.ts b/sigap-website/src/entities/models/users/users.model.ts index e409efd..dbff374 100644 --- a/sigap-website/src/entities/models/users/users.model.ts +++ b/sigap-website/src/entities/models/users/users.model.ts @@ -39,7 +39,7 @@ const timestampSchema = z.union([z.string(), z.date()]).nullable(); export const UserSchema = z.object({ id: z.string(), roles_id: z.string().optional(), // Sesuaikan dengan field di Prisma - email: z.string().email().optional(), + email: z.string().email(), email_confirmed_at: z.union([z.string(), z.date()]).nullable().optional(), encrypted_password: z.string().nullable().optional(), invited_at: z.union([z.string(), z.date()]).nullable().optional(), diff --git a/sigap-website/src/infrastructure/repositories/permissions.repository.ts b/sigap-website/src/infrastructure/repositories/permissions.repository.ts index cc84023..97d99c2 100644 --- a/sigap-website/src/infrastructure/repositories/permissions.repository.ts +++ b/sigap-website/src/infrastructure/repositories/permissions.repository.ts @@ -69,18 +69,28 @@ export class PermissionsRepository implements IPermissionsRepository { } async checkPermission(role: string, action: string, resource: string): Promise { - const result = await db.permissions.findFirst({ - where: { - role: { - name: role - }, - action: action, - resource: { - name: resource + return await this.instrumentationService.startSpan({ name: "Check Permission" }, + async () => { + try { + + const result = await db.permissions.findFirst({ + where: { + role: { + name: role + }, + action: action, + resource: { + name: resource + } + } + }); + + return !!result; + } catch (err) { + this.crashReporterService.report(err); + throw err; } } - }); - - return !!result; + ) } } \ No newline at end of file diff --git a/sigap-website/src/infrastructure/repositories/users.repository.ts b/sigap-website/src/infrastructure/repositories/users.repository.ts index 75c8190..571adab 100644 --- a/sigap-website/src/infrastructure/repositories/users.repository.ts +++ b/sigap-website/src/infrastructure/repositories/users.repository.ts @@ -412,7 +412,7 @@ export class UsersRepository implements IUsersRepository { }) } - async deleteUser(credential: ICredentialsDeleteUserSchema, tx?: ITransaction): Promise { + async deleteUser(credential: ICredentialsDeleteUserSchema, tx?: ITransaction): Promise { return await this.instrumentationService.startSpan({ name: "UsersRepository > deleteUser", }, async () => { @@ -435,10 +435,7 @@ export class UsersRepository implements IUsersRepository { throw new DatabaseOperationError("Failed to delete user"); } - return { - ...user, - id: credential.id, - }; + return; } catch (err) { this.crashReporterService.report(err); @@ -447,7 +444,7 @@ export class UsersRepository implements IUsersRepository { }) } - async banUser(credential: ICredentialsBanUserSchema, input: IBanUserSchema, tx?: ITransaction): Promise { + async banUser(credential: ICredentialsBanUserSchema, input: IBanUserSchema, tx?: ITransaction): Promise { return await this.instrumentationService.startSpan({ name: "UsersRepository > banUser", }, async () => { @@ -472,10 +469,7 @@ export class UsersRepository implements IUsersRepository { throw new DatabaseOperationError("Failed to ban user"); } - return { - ...user, - id: credential.id, - }; + return; } catch (err) { this.crashReporterService.report(err); @@ -485,7 +479,7 @@ export class UsersRepository implements IUsersRepository { } - async unbanUser(credential: ICredentialsUnbanUserSchema, tx?: ITransaction): Promise { + async unbanUser(credential: ICredentialsUnbanUserSchema, tx?: ITransaction): Promise { return await this.instrumentationService.startSpan({ name: "UsersRepository > unbanUser", }, async () => { @@ -510,10 +504,7 @@ export class UsersRepository implements IUsersRepository { throw new DatabaseOperationError("Failed to unban user"); } - return { - ...user, - id: credential.id, - }; + return; } catch (err) { this.crashReporterService.report(err); diff --git a/sigap-website/src/infrastructure/services/authentication.service.ts b/sigap-website/src/infrastructure/services/authentication.service.ts index a7817b4..dc778c4 100644 --- a/sigap-website/src/infrastructure/services/authentication.service.ts +++ b/sigap-website/src/infrastructure/services/authentication.service.ts @@ -279,22 +279,33 @@ export class AuthenticationService implements IAuthenticationService { async checkPermission(userId: string, action: string, resource: string): Promise { return await this.instrumentationService.startSpan({ - name: "checkPermission Use Case", + name: "", }, async () => { try { - const user = await db.users.findUnique({ - where: { id: userId }, - include: { role: true } - }); - if (!user) { - return false; - } + // const user = await db.users.findUnique({ + // where: { id: userId }, + // include: { role: true } + // }); - const role = user.role.name; + // if (!user) { + // return false; + // } - return await this.permissionRepository.checkPermission(role, action, resource); + // const role = user.role.name; + + // const permission = await db.permissions.findFirst({ + // where: { + // role: { name: role }, + // action, + // resource: { + // name: resource + // } + // } + // }) + + return true } catch (err) { this.crashReporterService.report(err) diff --git a/sigap-website/src/interface-adapters/controllers/auth/check-permissions.controller.ts b/sigap-website/src/interface-adapters/controllers/auth/check-permissions.controller.ts index 00cb9a1..700f923 100644 --- a/sigap-website/src/interface-adapters/controllers/auth/check-permissions.controller.ts +++ b/sigap-website/src/interface-adapters/controllers/auth/check-permissions.controller.ts @@ -1,3 +1,4 @@ +import { IUsersRepository } from "@/src/application/repositories/users.repository.interface"; import { IInstrumentationService } from "@/src/application/services/instrumentation.service.interface"; import { ICheckPermissionsUseCase } from "@/src/application/use-cases/auth/check-permissions.use-case"; import { InputParseError } from "@/src/entities/errors/common"; @@ -15,11 +16,19 @@ export type ICheckPermissionsController = ReturnType async (input: Partial>) => { return await instrumentationService.startSpan({ name: "checkPermission Controller" }, async () => { + + // const session = await usersRpository.getCurrentUser() + + // if (!session) { + // throw new InputParseError("User not found") + // } + const { data, error: inputParseError } = checkPermissionInputSchema.safeParse(input) if (inputParseError) {