diff --git a/web/src/app/projects/[projectId]/datasets/[datasetId]/page.tsx b/web/src/app/projects/[projectId]/datasets/[datasetId]/page.tsx index 02fdaac6..1654257f 100644 --- a/web/src/app/projects/[projectId]/datasets/[datasetId]/page.tsx +++ b/web/src/app/projects/[projectId]/datasets/[datasetId]/page.tsx @@ -9,8 +9,8 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { DatasetHeader } from "@/components/dataset/dataset-header"; import { useQueryClient } from "@tanstack/react-query"; import { useDataset } from "@/lib/queries/dataset/get-dataset"; -import { useAuthStore } from "@/lib/stores/auth-store"; import { useSidebar } from "@/components/ui/sidebar"; +import { useResourcePermissions } from "@/hooks/use-permissions"; export default function DatasetPage({ params, @@ -19,7 +19,6 @@ export default function DatasetPage({ }) { const { datasetId, projectId } = React.use(params); const queryClient = useQueryClient(); - const { role, user } = useAuthStore(); const { setOpen } = useSidebar(); const { data: dataset, isLoading } = useDataset({ @@ -29,6 +28,8 @@ export default function DatasetPage({ }, }); + const permissions = useResourcePermissions(dataset?.created_by); + const tableSchema = dataset?.columns || []; // Close sidebar only on initial mount @@ -125,7 +126,7 @@ export default function DatasetPage({ dataset={dataset} projectId={projectId} onUpdate={handleUpdate} - canEdit={role === "admin" || dataset.created_by === user?.id} + canEdit={permissions.canEdit} /> diff --git a/web/src/hooks/use-permissions.ts b/web/src/hooks/use-permissions.ts new file mode 100644 index 00000000..6e3ed82a --- /dev/null +++ b/web/src/hooks/use-permissions.ts @@ -0,0 +1,61 @@ +import { useAuthStore } from "@/lib/stores/auth-store"; + +export interface PermissionCheck { + canRead: boolean; + canCreate: boolean; + canEdit: boolean; + canDelete: boolean; + isAdmin: boolean; + isMember: boolean; + role: string | null; +} + +/** + * Hook to check user permissions based on organization role + * + * Access Matrix: + * - Member: Read only + * - Admin: Create, Read, Edit, Delete + */ +export function usePermissions(): PermissionCheck { + const { role } = useAuthStore(); + const isAuthDisabled = String(process.env.NEXT_PUBLIC_ENABLE_AUTH).trim() !== "true"; + + const effectiveRole = isAuthDisabled ? "admin" : role; + + const isAdmin = effectiveRole === "admin"; + const isMember = effectiveRole === "member" || !effectiveRole; + + return { + canRead: true, + canCreate: isAdmin, + canEdit: isAdmin, + canDelete: isAdmin, + isAdmin, + isMember, + role: effectiveRole, + }; +} + +/** + * Hook to check if user has permissions for a specific resource + * Combines role-based permissions with creator ownership + * + * @param createdBy - The user ID of the resource creator + * @returns Permission checks including creator-specific permissions + */ +export function useResourcePermissions(createdBy?: string | null): PermissionCheck & { + isCreator: boolean; +} { + const { user } = useAuthStore(); + const permissions = usePermissions(); + + const isCreator = !!createdBy && user?.id === createdBy; + + return { + ...permissions, + canEdit: permissions.canEdit || isCreator, + canDelete: permissions.canDelete || isCreator, + isCreator, + }; +}