init model rbac

This commit is contained in:
vergiLgood1 2025-04-07 20:50:57 +07:00
parent 0205f6b5c7
commit a468f3db68
32 changed files with 68 additions and 35 deletions

View File

@ -17,7 +17,7 @@ import { NavPreMain } from "./navigations/nav-pre-main";
import { navData } from "@/prisma/data/nav";
import { TeamSwitcher } from "../../../_components/team-switcher";
import { useGetCurrentUserQuery } from "../dashboard/user-management/_queries/queries";
import { useUserStore } from "@/app/_utils/zustand/stores/user";
import { useUserStore } from "@/app/_lib/zustand/stores/user";
import { useUserActionsHandler } from "../dashboard/user-management/_handlers/actions/use-user-actions";

View File

@ -30,7 +30,7 @@ import { SettingsDialog } from "../settings/setting-dialog";
import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogHeader, AlertDialogFooter, AlertDialogTitle, AlertDialogDescription, AlertDialogCancel, AlertDialogAction } from "@/app/_components/ui/alert-dialog";
import { useSignOutHandler } from "@/app/(pages)/(auth)/_handlers/use-sign-out";
import { useGetCurrentUserQuery } from "../../dashboard/user-management/_queries/queries";
import { useUserStore } from "@/app/_utils/zustand/stores/user";
import { useUserStore } from "@/app/_lib/zustand/stores/user";
interface NavUserProps {
user: IUserSchema | null;

View File

@ -30,7 +30,7 @@ import { ImageIcon, Loader2 } from "lucide-react";
import { createClient } from "@/app/_utils/supabase/client";
import { getFullName, getInitials } from "@/app/_utils/common";
import { useProfileFormHandlers } from "../dashboard/user-management/_handlers/use-profile-form";
import { CTexts } from "@/app/_lib/const/texts";
import { CTexts } from "@/app/_utils/const/texts";
// Profile update form schema
const profileFormSchema = z.object({

View File

@ -32,7 +32,7 @@ import {
updateUser,
} from "@/app/(pages)/(admin)/dashboard/user-management/action";
import { useProfileFormHandlers } from "../../dashboard/user-management/_handlers/use-profile-form";
import { CTexts } from "@/app/_lib/const/texts";
import { CTexts } from "@/app/_utils/const/texts";
const profileFormSchema = z.object({
username: z.string().nullable().optional(),

View File

@ -36,7 +36,7 @@ import NotificationsSetting from "./notification-settings";
import PreferencesSettings from "./preference-settings";
import ImportData from "./import-data";
import { IUserSchema } from "@/src/entities/models/users/users.model";
import { useUserStore } from "@/app/_utils/zustand/stores/user";
import { useUserStore } from "@/app/_lib/zustand/stores/user";
interface SettingsDialogProps {
trigger: React.ReactNode;

View File

@ -13,7 +13,7 @@ import { RadioGroup, RadioGroupItem } from "@/app/_components/ui/radio-group"
import { Label } from "@/app/_components/ui/label"
import { Input } from "@/app/_components/ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/app/_components/ui/select"
import { ValidBanDuration } from "@/app/_lib/types/ban-duration"
import { ValidBanDuration } from "@/app/_utils/types/ban-duration"
import { toast } from "sonner"
interface BanUserDialogProps {

View File

@ -2,7 +2,7 @@
import { useState } from "react"
import { useBanUserMutation } from "../../_queries/mutations"
import type { ValidBanDuration } from "@/app/_lib/types/ban-duration"
import type { ValidBanDuration } from "@/app/_utils/types/ban-duration"
import { toast } from "sonner"
import { useUserActionsHandler } from "./use-user-actions"

View File

@ -1,6 +1,6 @@
import { useState } from "react"
import { useBanUserMutation, useDeleteUserMutation, useUnbanUserMutation } from "../_queries/mutations"
import { ValidBanDuration } from "@/app/_lib/types/ban-duration"
import { ValidBanDuration } from "@/app/_utils/types/ban-duration"
import { useQueryClient } from "@tanstack/react-query"
import { toast } from "sonner"
import { useForm } from "react-hook-form"

View File

@ -2,7 +2,7 @@ import { IUserSchema } from "@/src/entities/models/users/users.model";
import { toast } from "sonner";
import { useBanUserMutation, useDeleteUserMutation, useUnbanUserMutation } from "../_queries/mutations";
import { useSendMagicLinkMutation, useSendPasswordRecoveryMutation } from "@/app/(pages)/(auth)/_queries/mutations";
import { ValidBanDuration } from "@/app/_lib/types/ban-duration";
import { ValidBanDuration } from "@/app/_utils/types/ban-duration";
import { copyItem } from "@/app/_utils/common";
import { useQueryClient } from "@tanstack/react-query";
import { useUserActionsHandler } from "./actions/use-user-actions";

View File

@ -11,8 +11,8 @@ import { z } from "zod"
import { useUnbanUserMutation, useUpdateUserMutation, useUploadAvatarMutation } from "../_queries/mutations"
import { useQueryClient } from "@tanstack/react-query"
import { toast } from "sonner"
import { CNumbers } from "@/app/_lib/const/numbers"
import { CTexts } from "@/app/_lib/const/texts"
import { CNumbers } from "@/app/_utils/const/numbers"
import { CTexts } from "@/app/_utils/const/texts"
import { useUserActionsHandler } from "./actions/use-user-actions"
// Profile update form schema

View File

@ -5,7 +5,7 @@ import { IUpdateUserSchema } from "@/src/entities/models/users/update-user.model
import { ICredentialsInviteUserSchema } from "@/src/entities/models/users/invite-user.model";
import { IBanUserSchema, ICredentialsBanUserSchema } from "@/src/entities/models/users/ban-user.model";
import { ICredentialsUnbanUserSchema } from "@/src/entities/models/users/unban-user.model";
import { ValidBanDuration } from "@/app/_lib/types/ban-duration";
import { ValidBanDuration } from "@/app/_utils/types/ban-duration";
export const useCreateUserMutation = () => {
return useMutation({

View File

@ -6,7 +6,7 @@ import { useForm } from "react-hook-form";
import { ISignInPasswordlessSchema, SignInPasswordlessSchema } from "@/src/entities/models/auth/sign-in.model";
import { zodResolver } from "@hookform/resolvers/zod";
import { createRoute } from "@/app/_utils/common";
import { ROUTES } from "@/app/_lib/const/routes";
import { ROUTES } from "@/app/_utils/const/routes";
export function useSignInPasswordlessHandler() {
const { mutateAsync: signIn, isPending, error: queryError } = useSignInPasswordlessMutation();

View File

@ -6,7 +6,7 @@ import { ISignInWithPasswordSchema, SignInWithPasswordSchema } from "@/src/entit
import { zodResolver } from "@hookform/resolvers/zod";
import { toast } from "sonner";
import { createRoute } from "@/app/_utils/common";
import { ROUTES } from "@/app/_lib/const/routes";
import { ROUTES } from "@/app/_utils/const/routes";
export const useSignInWithPasswordHandler = () => {
const { mutateAsync: signInWithPassword, isPending, error: queryError } = useSignInWithPasswordMutation();

View File

@ -10,7 +10,7 @@ import { useSignInPasswordlessHandler } from "../../_handlers/use-sign-in-passwo
import { useSignInWithPasswordHandler } from "../../_handlers/use-sign-in-with-password";
import { useNavigations } from "@/app/_hooks/use-navigations";
import { createRoute } from "@/app/_utils/common";
import { ROUTES } from "@/app/_lib/const/routes";
import { ROUTES } from "@/app/_utils/const/routes";
export function SignInWithPasswordForm({
className,

View File

@ -1,7 +1,7 @@
import { Geist } from "next/font/google";
import { ThemeProvider } from "next-themes";
import "@/app/_styles/globals.css";
import ReactQueryProvider from "@/app/_utils/react-query-provider";
import ReactQueryProvider from "@/app/_lib/react-query-provider";
import { Toaster } from "@/app/_components/ui/sonner";
const defaultUrl = process.env.VERCEL_URL

View File

@ -1,10 +1,10 @@
import { IUserSchema } from "@/src/entities/models/users/users.model"
type Role = "viewer" | "editor" | "admin";
type Role = "viewer" | "staff" | "admin";
const PERMISSIONS: Record<Role, string[]> = {
viewer: ["view:post"],
editor: ["view:post", "edit:post"],
staff: ["view:post", "edit:post"],
admin: ["view:post", "create:post", "edit:post", "delete:post"],
};
export const CheckPermission = (user: IUserSchema, action: string, resource: string) => {

View File

@ -1,6 +1,6 @@
import { format } from "date-fns";
import { redirect } from "next/navigation";
import { DateFormatOptions, DateFormatPattern } from "../_lib/types/date-format.interface";
import { DateFormatOptions, DateFormatPattern } from "./types/date-format.interface";
import { toast } from "sonner";
import { IUserSchema } from "@/src/entities/models/users/users.model";

View File

@ -1,5 +1,5 @@
import { CTexts } from "../_lib/const/texts";
import { CRegex } from "../_lib/const/regex";
import { CTexts } from "./const/texts";
import { CRegex } from "./const/regex";
/**
* Validates if a given phone number starts with any of the predefined prefixes.

View File

@ -147,7 +147,7 @@ model profiles {
model users {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
role roles @default(user)
roles_id String @db.Uuid
email String @unique @db.VarChar(255)
phone String? @unique @db.VarChar(20)
encrypted_password String? @db.VarChar(255)
@ -163,11 +163,44 @@ model users {
banned_until DateTime? @db.Timestamptz(6)
is_anonymous Boolean @default(false)
profile profiles?
role roles @relation(fields: [roles_id], references: [id])
@@index([is_anonymous])
@@index([created_at])
@@index([updated_at])
@@index([role])
}
model roles {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String @unique @db.VarChar(255)
description String?
permissions permissions[]
users users[]
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
}
model resources {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
name String @unique @db.VarChar(255)
description String?
instance_role String?
relations String?
attributes Json?
permissions permissions[]
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
}
model permissions {
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
action String
resource_id String
role_id String
resource resources @relation(fields: [resource_id], references: [id])
role roles @relation(fields: [role_id], references: [id])
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @updatedAt @db.Timestamptz(6)
}
enum crime_rates {
@ -182,11 +215,11 @@ enum crime_status {
resolved
}
enum roles {
admin
staff
user
}
// enum roles {
// admin
// staff
// user
// }
enum status_contact_messages {
new

View File

@ -1,4 +1,4 @@
import { ServerActionErrorParams } from "@/app/_lib/types/error-server-action.interface";
import { ServerActionErrorParams } from "@/app/_utils/types/error-server-action.interface";
export class DatabaseOperationError extends Error {
constructor(message: string, options?: ErrorOptions) {

View File

@ -1,6 +1,6 @@
// Schema Zod untuk validasi runtime
import { CRegex } from "@/app/_lib/const/regex";
import { ValidBanDuration } from "@/app/_lib/types/ban-duration";
import { CRegex } from "@/app/_utils/const/regex";
import { ValidBanDuration } from "@/app/_utils/types/ban-duration";
import { z } from "zod";
export const BanDurationSchema = z.custom<ValidBanDuration>(

View File

@ -1,5 +1,5 @@
import { CNumbers } from "@/app/_lib/const/numbers";
import { CTexts } from "@/app/_lib/const/texts";
import { CNumbers } from "@/app/_utils/const/numbers";
import { CTexts } from "@/app/_utils/const/texts";
import { phonePrefixValidation, phoneRegexValidation } from "@/app/_utils/validation";
import { z } from "zod";

View File

@ -1,5 +1,5 @@
import { CNumbers } from "@/app/_lib/const/numbers";
import { CTexts } from "@/app/_lib/const/texts";
import { CNumbers } from "@/app/_utils/const/numbers";
import { CTexts } from "@/app/_utils/const/texts";
import { IInstrumentationService } from "@/src/application/services/instrumentation.service.interface";
import { IUploadAvatarUseCase } from "@/src/application/use-cases/users/upload-avatar.use-case";
import { z } from "zod";