feat: implement group-based access control (Admin, Standard_User, Leadership, Read_Only)

- Add user_group migration and created_by column migration
- Replace requireRole middleware with requireGroup
- Update all backend routes to use group-based authorization
- Add Standard_User conditional delete with ownership, state, and compliance checks
- Add cascade impact check for CVE deletes
- Update AuthContext with group-based permission helpers
- Update all frontend components for group-based rendering
- Update UserManagement UI with group dropdown, confirmation dialogs, self-demotion prevention
This commit is contained in:
jramos
2026-04-06 16:18:07 -06:00
parent 1ef57b0504
commit 73fd747576
19 changed files with 1171 additions and 149 deletions

View File

@@ -72,16 +72,26 @@ export function AuthProvider({ children }) {
setUser(null);
};
// Check if user has a specific role
const hasRole = (...roles) => {
return user && roles.includes(user.role);
// Check if user belongs to one of the specified groups
const isInGroup = (...groups) => user && groups.includes(user.group);
// Check if user can perform write operations (Admin or Standard_User)
const canWrite = () => isInGroup('Admin', 'Standard_User');
// Check if user can delete a resource
// Admin: always true; Standard_User: only if they own the resource; others: false
const canDelete = (resource) => {
if (!user) return false;
if (isInGroup('Admin')) return true;
if (!isInGroup('Standard_User')) return false;
return resource?.created_by === user.id;
};
// Check if user can perform write operations (editor or admin)
const canWrite = () => hasRole('editor', 'admin');
// Check if user can export data
const canExport = () => isInGroup('Admin', 'Standard_User', 'Leadership');
// Check if user is admin
const isAdmin = () => hasRole('admin');
const isAdmin = () => isInGroup('Admin');
const value = {
user,
@@ -90,8 +100,10 @@ export function AuthProvider({ children }) {
login,
logout,
checkAuth,
hasRole,
isInGroup,
canWrite,
canDelete,
canExport,
isAdmin,
isAuthenticated: !!user
};