- 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
55 lines
2.1 KiB
TypeScript
55 lines
2.1 KiB
TypeScript
import { pgTable, uuid, varchar, text, timestamp, boolean, uniqueIndex } from 'drizzle-orm/pg-core'
|
|
import { companies } from './stores.js'
|
|
import { users } from './users.js'
|
|
|
|
export const permissions = pgTable('permission', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
slug: varchar('slug', { length: 100 }).notNull().unique(),
|
|
domain: varchar('domain', { length: 50 }).notNull(),
|
|
action: varchar('action', { length: 50 }).notNull(),
|
|
description: varchar('description', { length: 255 }).notNull(),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export const roles = pgTable('role', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
companyId: uuid('company_id')
|
|
.notNull()
|
|
.references(() => companies.id),
|
|
name: varchar('name', { length: 100 }).notNull(),
|
|
slug: varchar('slug', { length: 100 }).notNull(),
|
|
description: text('description'),
|
|
isSystem: boolean('is_system').notNull().default(false),
|
|
isActive: boolean('is_active').notNull().default(true),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
updatedAt: timestamp('updated_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export const rolePermissions = pgTable('role_permission', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
roleId: uuid('role_id')
|
|
.notNull()
|
|
.references(() => roles.id),
|
|
permissionId: uuid('permission_id')
|
|
.notNull()
|
|
.references(() => permissions.id),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export const userRoles = pgTable('user_role_assignment', {
|
|
id: uuid('id').primaryKey().defaultRandom(),
|
|
userId: uuid('user_id')
|
|
.notNull()
|
|
.references(() => users.id),
|
|
roleId: uuid('role_id')
|
|
.notNull()
|
|
.references(() => roles.id),
|
|
assignedBy: uuid('assigned_by'),
|
|
createdAt: timestamp('created_at', { withTimezone: true }).notNull().defaultNow(),
|
|
})
|
|
|
|
export type Permission = typeof permissions.$inferSelect
|
|
export type Role = typeof roles.$inferSelect
|
|
export type RolePermission = typeof rolePermissions.$inferSelect
|
|
export type UserRole = typeof userRoles.$inferSelect
|