feat(permissions): add inquiries resource (view/manage) + idempotent role backfill
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -103,6 +103,10 @@ const DEFAULT_PERMISSIONS: Record<string, Record<string, boolean>> = {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: false,
|
||||||
|
manage: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const GROUP_LABELS: Record<string, string> = {
|
const GROUP_LABELS: Record<string, string> = {
|
||||||
@@ -126,6 +130,7 @@ const GROUP_LABELS: Record<string, string> = {
|
|||||||
admin: 'Administration',
|
admin: 'Administration',
|
||||||
residential_clients: 'Residential Clients',
|
residential_clients: 'Residential Clients',
|
||||||
residential_interests: 'Residential Interests',
|
residential_interests: 'Residential Interests',
|
||||||
|
inquiries: 'Inquiries',
|
||||||
};
|
};
|
||||||
|
|
||||||
function formatAction(action: string): string {
|
function formatAction(action: string): string {
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ export const PERMISSION_CATALOG = {
|
|||||||
],
|
],
|
||||||
residential_clients: ['view', 'create', 'edit', 'delete'],
|
residential_clients: ['view', 'create', 'edit', 'delete'],
|
||||||
residential_interests: ['view', 'create', 'edit', 'delete', 'change_stage'],
|
residential_interests: ['view', 'create', 'edit', 'delete', 'change_stage'],
|
||||||
|
inquiries: ['view', 'manage'],
|
||||||
} as const satisfies {
|
} as const satisfies {
|
||||||
[R in PermissionResource]: ReadonlyArray<PermissionAction<R> & string>;
|
[R in PermissionResource]: ReadonlyArray<PermissionAction<R> & string>;
|
||||||
};
|
};
|
||||||
|
|||||||
25
src/lib/db/migrations/0092_inquiries_permission.sql
Normal file
25
src/lib/db/migrations/0092_inquiries_permission.sql
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
-- 0092_inquiries_permission.sql
|
||||||
|
-- ----------------------------------------------------------------------------
|
||||||
|
-- New `inquiries` permission resource (view/manage) backing the top-level
|
||||||
|
-- Inquiries workbench (previously the inbox lived under /admin and was gated on
|
||||||
|
-- admin.view_audit_log, which sales roles don't have).
|
||||||
|
--
|
||||||
|
-- Existing role rows are backfilled so the resource defaults to whatever the
|
||||||
|
-- role's `clients` access is: view ⟵ clients.view, manage ⟵ clients.create.
|
||||||
|
-- This lights up the right roles (anyone who can see/create clients) without a
|
||||||
|
-- manual per-role edit, and defaults to deny for read-only roles.
|
||||||
|
--
|
||||||
|
-- New-key only and idempotent via the `? 'inquiries'` guard, so re-running is a
|
||||||
|
-- no-op. Per-user / port-role override tables are intentionally left untouched:
|
||||||
|
-- the deep-merge resolver fills missing leaves from the base role (same
|
||||||
|
-- reasoning as 0041).
|
||||||
|
|
||||||
|
UPDATE roles
|
||||||
|
SET permissions = permissions || jsonb_build_object(
|
||||||
|
'inquiries', jsonb_build_object(
|
||||||
|
'view', COALESCE((permissions->'clients'->>'view')::boolean, false),
|
||||||
|
'manage', COALESCE((permissions->'clients'->>'create')::boolean, false)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
WHERE permissions IS NOT NULL
|
||||||
|
AND NOT (permissions ? 'inquiries');
|
||||||
@@ -162,6 +162,10 @@ export type RolePermissions = {
|
|||||||
delete: boolean;
|
delete: boolean;
|
||||||
change_stage: boolean;
|
change_stage: boolean;
|
||||||
};
|
};
|
||||||
|
inquiries: {
|
||||||
|
view: boolean;
|
||||||
|
manage: boolean;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -88,6 +88,10 @@ export const ALL_PERMISSIONS: RolePermissions = {
|
|||||||
delete: true,
|
delete: true,
|
||||||
change_stage: true,
|
change_stage: true,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: true,
|
||||||
|
manage: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DIRECTOR_PERMISSIONS: RolePermissions = {
|
export const DIRECTOR_PERMISSIONS: RolePermissions = {
|
||||||
@@ -167,6 +171,10 @@ export const DIRECTOR_PERMISSIONS: RolePermissions = {
|
|||||||
delete: true,
|
delete: true,
|
||||||
change_stage: true,
|
change_stage: true,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: true,
|
||||||
|
manage: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SALES_MANAGER_PERMISSIONS: RolePermissions = {
|
export const SALES_MANAGER_PERMISSIONS: RolePermissions = {
|
||||||
@@ -246,6 +254,10 @@ export const SALES_MANAGER_PERMISSIONS: RolePermissions = {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: true,
|
||||||
|
manage: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SALES_AGENT_PERMISSIONS: RolePermissions = {
|
export const SALES_AGENT_PERMISSIONS: RolePermissions = {
|
||||||
@@ -325,6 +337,10 @@ export const SALES_AGENT_PERMISSIONS: RolePermissions = {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: true,
|
||||||
|
manage: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const VIEWER_PERMISSIONS: RolePermissions = {
|
export const VIEWER_PERMISSIONS: RolePermissions = {
|
||||||
@@ -410,6 +426,10 @@ export const VIEWER_PERMISSIONS: RolePermissions = {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: true,
|
||||||
|
manage: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// Residential Partner - for an outside party who handles residential
|
// Residential Partner - for an outside party who handles residential
|
||||||
@@ -498,4 +518,8 @@ export const RESIDENTIAL_PARTNER_PERMISSIONS: RolePermissions = {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: true,
|
change_stage: true,
|
||||||
},
|
},
|
||||||
|
inquiries: {
|
||||||
|
view: false,
|
||||||
|
manage: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -384,6 +384,7 @@ export function makeFullPermissions(): RolePermissions {
|
|||||||
delete: true,
|
delete: true,
|
||||||
change_stage: true,
|
change_stage: true,
|
||||||
},
|
},
|
||||||
|
inquiries: { view: true, manage: true },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -472,6 +473,7 @@ export function makeViewerPermissions(): RolePermissions {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: { view: true, manage: false },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -560,6 +562,7 @@ export function makeSalesAgentPermissions(): RolePermissions {
|
|||||||
delete: false,
|
delete: false,
|
||||||
change_stage: false,
|
change_stage: false,
|
||||||
},
|
},
|
||||||
|
inquiries: { view: true, manage: true },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -648,6 +651,7 @@ export function makeSalesManagerPermissions(): RolePermissions {
|
|||||||
delete: true,
|
delete: true,
|
||||||
change_stage: true,
|
change_stage: true,
|
||||||
},
|
},
|
||||||
|
inquiries: { view: true, manage: true },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user