Refactor roles management to use role code as primary key

- Updated the roles table schema to use role code as the primary key, enhancing readability in junction tables.
- Modified related tables (user_roles, product_role_visibility) to reference role code instead of role ID.
- Adjusted seeding logic and utility functions to accommodate the new primary key structure, ensuring consistent role management across the application.
- Added a migration script to facilitate the database schema changes.
This commit is contained in:
Bastian Masanek
2025-11-03 10:45:11 +01:00
parent a6d09d76fd
commit 68ab42f2f4
5 changed files with 93 additions and 38 deletions

View File

@@ -99,21 +99,21 @@ export async function isProductVisibleForUser(
export async function getVisibleProductIdsForUser(userId: string): Promise<string[]> {
const db = useDatabase()
// Get user's approved role IDs
// Get user's approved role codes
const userRoleRecords = await db.query.userRoles.findMany({
where: and(eq(userRoles.userId, userId), eq(userRoles.status, 'approved')),
})
const userRoleIds = userRoleRecords.map((ur) => ur.roleId)
const userRoleCodes = userRoleRecords.map((ur) => ur.roleCode)
// If user has no approved roles, they can't see any products
if (userRoleIds.length === 0) {
if (userRoleCodes.length === 0) {
return []
}
// Get all products assigned to these roles
const visibleProducts = await db.query.productRoleVisibility.findMany({
where: inArray(productRoleVisibility.roleId, userRoleIds),
where: inArray(productRoleVisibility.roleCode, userRoleCodes),
})
// Return unique product IDs
@@ -138,18 +138,9 @@ export async function assignRoleToUser(
) {
const db = useDatabase()
// Find role by code
const role = await db.query.roles.findFirst({
where: eq(roles.code, roleCode),
})
if (!role) {
throw new Error(`Role '${roleCode}' not found`)
}
// Check if user already has this role
const existing = await db.query.userRoles.findFirst({
where: and(eq(userRoles.userId, userId), eq(userRoles.roleId, role.id)),
where: and(eq(userRoles.userId, userId), eq(userRoles.roleCode, roleCode)),
})
if (existing) {
@@ -157,11 +148,12 @@ export async function assignRoleToUser(
}
// Create user role assignment (approved in MVP)
// Note: No need to lookup role - we can use roleCode directly as FK
const [userRole] = await db
.insert(userRoles)
.values({
userId,
roleId: role.id,
roleCode, // Direct reference to roles.code (PK)
status: 'approved', // MVP: Always approved
organizationName: options?.organizationName,
adminNotes: options?.adminNotes,
@@ -227,20 +219,16 @@ export async function assignRolesToProductByCategory(
return []
}
// Get role IDs
const roleRecords = await db.query.roles.findMany({
where: inArray(roles.code, roleCodes),
})
const assignments = []
// Create product-role assignments
for (const role of roleRecords) {
// Note: No need to lookup roles - we can use roleCode directly as FK
for (const roleCode of roleCodes) {
// Check if assignment already exists
const existing = await db.query.productRoleVisibility.findFirst({
where: and(
eq(productRoleVisibility.productId, productId),
eq(productRoleVisibility.roleId, role.id)
eq(productRoleVisibility.roleCode, roleCode)
),
})
@@ -249,7 +237,7 @@ export async function assignRolesToProductByCategory(
.insert(productRoleVisibility)
.values({
productId,
roleId: role.id,
roleCode, // Direct reference to roles.code (PK)
})
.returning()