Implement RBAC with permissions, roles, and route guards
- permission, role, role_permission, user_role_assignment tables - 42 system permissions across 13 domains - 6 default roles: Admin, Manager, Sales Associate, Technician, Instructor, Viewer - Permission inheritance: admin implies edit implies view - requirePermission() Fastify decorator on ALL routes - System permissions and roles seeded per company - Test helpers and API test runner seed RBAC data - All 42 API tests pass with permissions enforced
This commit is contained in:
43
packages/backend/src/db/migrations/0013_rbac.sql
Normal file
43
packages/backend/src/db/migrations/0013_rbac.sql
Normal file
@@ -0,0 +1,43 @@
|
||||
-- Permissions and role-based access control
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "permission" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"slug" varchar(100) NOT NULL UNIQUE,
|
||||
"domain" varchar(50) NOT NULL,
|
||||
"action" varchar(50) NOT NULL,
|
||||
"description" varchar(255) NOT NULL,
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "role" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"company_id" uuid NOT NULL REFERENCES "company"("id"),
|
||||
"name" varchar(100) NOT NULL,
|
||||
"slug" varchar(100) NOT NULL,
|
||||
"description" text,
|
||||
"is_system" boolean NOT NULL DEFAULT false,
|
||||
"is_active" boolean NOT NULL DEFAULT true,
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now(),
|
||||
"updated_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "role_company_slug" ON "role" ("company_id", "slug");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "role_permission" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"role_id" uuid NOT NULL REFERENCES "role"("id"),
|
||||
"permission_id" uuid NOT NULL REFERENCES "permission"("id"),
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "role_permission_unique" ON "role_permission" ("role_id", "permission_id");
|
||||
|
||||
CREATE TABLE IF NOT EXISTS "user_role_assignment" (
|
||||
"id" uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
"user_id" uuid NOT NULL REFERENCES "user"("id"),
|
||||
"role_id" uuid NOT NULL REFERENCES "role"("id"),
|
||||
"assigned_by" uuid,
|
||||
"created_at" timestamp with time zone NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX "user_role_assignment_unique" ON "user_role_assignment" ("user_id", "role_id");
|
||||
@@ -92,6 +92,13 @@
|
||||
"when": 1774720000000,
|
||||
"tag": "0012_file_storage",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 13,
|
||||
"version": "7",
|
||||
"when": 1774730000000,
|
||||
"tag": "0013_rbac",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user