mirror of
https://github.com/R0m1k3/LogiFlow.git
synced 2026-10-11 17:27:31 +02:00
Implement a new hardcoded permissions system for enhanced user access control
This commit replaces the previous dynamic, database-driven permissions system with a hardcoded, role-based access control (RBAC) structure. New files in `client/src/lib/permissions.ts` and `server/permissions.ts` define permissions per module and role, simplifying management and improving performance. Database tables related to roles, permissions, and user roles have been removed, and associated storage interface methods and routes have been deprecated or updated to reflect the new architecture. The `replit.md` file has also been updated to document these significant changes. Replit-Commit-Author: Agent Replit-Commit-Session-Id: a8a78c07-e900-425c-a577-5b4c5894379d Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/1957c339-2757-4d1f-8e92-e9f71a1ce58e/a8a78c07-e900-425c-a577-5b4c5894379d/7SnSmh4
This commit is contained in:
1 parent
70da3e9f5b
commit
df479800e3
9 files changed
+441
-873
No files matched your search
@@ -0,0 +1,149 @@
|
||||
// Système de permissions hardcodé par module
|
||||
// Remplace l'ancien système flexible basé sur la base de données
|
||||
|
||||
export type Permission = 'view' | 'create' | 'edit' | 'delete' | 'validate';
|
||||
export type Role = 'admin' | 'directeur' | 'manager' | 'employee';
|
||||
export type Module =
|
||||
| 'dashboard'
|
||||
| 'calendar'
|
||||
| 'orders'
|
||||
| 'deliveries'
|
||||
| 'reconciliation'
|
||||
| 'publicity'
|
||||
| 'customer-orders'
|
||||
| 'dlc'
|
||||
| 'tasks';
|
||||
|
||||
// Définition des permissions par module et par rôle
|
||||
const PERMISSIONS: Record<Module, Record<Role, Permission[]>> = {
|
||||
// Tableau de bord - tous les rôles peuvent le voir
|
||||
dashboard: {
|
||||
admin: ['view'],
|
||||
directeur: ['view'],
|
||||
manager: ['view'],
|
||||
employee: ['view']
|
||||
},
|
||||
|
||||
// Calendrier - Admin/Directeur tout, Manager tout sauf delete, Employé view
|
||||
calendar: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit', 'delete'],
|
||||
manager: ['view', 'create', 'edit'],
|
||||
employee: ['view']
|
||||
},
|
||||
|
||||
// Commandes - Admin/Directeur tout, Manager tout sauf delete, Employé view
|
||||
orders: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit', 'delete'],
|
||||
manager: ['view', 'create', 'edit'],
|
||||
employee: ['view']
|
||||
},
|
||||
|
||||
// Livraisons - Admin/Directeur tout, Manager tout sauf delete, Employé view
|
||||
deliveries: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit', 'delete'],
|
||||
manager: ['view', 'create', 'edit'],
|
||||
employee: ['view']
|
||||
},
|
||||
|
||||
// Rapprochement - Admin tout, Directeur tout sauf delete, Manager/Employé rien
|
||||
reconciliation: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit'],
|
||||
manager: [],
|
||||
employee: []
|
||||
},
|
||||
|
||||
// Publicité - Admin tout, autres view seulement
|
||||
publicity: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view'],
|
||||
manager: ['view'],
|
||||
employee: ['view']
|
||||
},
|
||||
|
||||
// Commandes client - Admin/Directeur tout, Manager tout sauf delete, Employé view + create
|
||||
'customer-orders': {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit', 'delete'],
|
||||
manager: ['view', 'create', 'edit'],
|
||||
employee: ['view', 'create']
|
||||
},
|
||||
|
||||
// DLC - Admin/Directeur tout, Manager tout sauf delete, Employé create + view
|
||||
dlc: {
|
||||
admin: ['view', 'create', 'edit', 'delete'],
|
||||
directeur: ['view', 'create', 'edit', 'delete'],
|
||||
manager: ['view', 'create', 'edit'],
|
||||
employee: ['view', 'create']
|
||||
},
|
||||
|
||||
// Tâches - Admin/Directeur tout, Manager view + validate, Employé view
|
||||
tasks: {
|
||||
admin: ['view', 'create', 'edit', 'delete', 'validate'],
|
||||
directeur: ['view', 'create', 'edit', 'delete', 'validate'],
|
||||
manager: ['view', 'validate'],
|
||||
employee: ['view']
|
||||
}
|
||||
};
|
||||
|
||||
// Hook pour vérifier les permissions
|
||||
export function usePermissions(userRole?: string) {
|
||||
const role = userRole?.toLowerCase() as Role;
|
||||
|
||||
// Vérifie si l'utilisateur peut accéder à un module
|
||||
const canAccessModule = (module: Module): boolean => {
|
||||
if (!role || !PERMISSIONS[module]) return false;
|
||||
const permissions = PERMISSIONS[module][role] || [];
|
||||
return permissions.length > 0;
|
||||
};
|
||||
|
||||
// Vérifie si l'utilisateur peut effectuer une action sur un module
|
||||
const canPerformAction = (module: Module, action: Permission): boolean => {
|
||||
if (!role || !PERMISSIONS[module]) return false;
|
||||
const permissions = PERMISSIONS[module][role] || [];
|
||||
return permissions.includes(action);
|
||||
};
|
||||
|
||||
// Retourne toutes les permissions pour un module
|
||||
const getModulePermissions = (module: Module): Permission[] => {
|
||||
if (!role || !PERMISSIONS[module]) return [];
|
||||
return PERMISSIONS[module][role] || [];
|
||||
};
|
||||
|
||||
// Vérifie si l'utilisateur peut voir le module (a au moins une permission)
|
||||
const canView = (module: Module): boolean => canPerformAction(module, 'view');
|
||||
const canCreate = (module: Module): boolean => canPerformAction(module, 'create');
|
||||
const canEdit = (module: Module): boolean => canPerformAction(module, 'edit');
|
||||
const canDelete = (module: Module): boolean => canPerformAction(module, 'delete');
|
||||
const canValidate = (module: Module): boolean => canPerformAction(module, 'validate');
|
||||
|
||||
return {
|
||||
canAccessModule,
|
||||
canPerformAction,
|
||||
getModulePermissions,
|
||||
canView,
|
||||
canCreate,
|
||||
canEdit,
|
||||
canDelete,
|
||||
canValidate
|
||||
};
|
||||
}
|
||||
|
||||
// Fonction utilitaire pour les middlewares serveur
|
||||
export function hasPermission(userRole: string, module: Module, action: Permission): boolean {
|
||||
const role = userRole?.toLowerCase() as Role;
|
||||
if (!role || !PERMISSIONS[module]) return false;
|
||||
const permissions = PERMISSIONS[module][role] || [];
|
||||
return permissions.includes(action);
|
||||
}
|
||||
|
||||
// Fonction utilitaire pour vérifier l'accès à un module
|
||||
export function hasModuleAccess(userRole: string, module: Module): boolean {
|
||||
const role = userRole?.toLowerCase() as Role;
|
||||
if (!role || !PERMISSIONS[module]) return false;
|
||||
const permissions = PERMISSIONS[module][role] || [];
|
||||
return permissions.length > 0;
|
||||
}
|
||||
+1
-119
@@ -136,40 +136,7 @@ export const publicityParticipations = pgTable("publicity_participations", {
|
||||
pk: primaryKey({ columns: [table.publicityId, table.groupId] })
|
||||
}));
|
||||
|
||||
// Roles - Dynamic role management
|
||||
export const roles = pgTable("roles", {
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name").notNull().unique(),
|
||||
displayName: varchar("display_name").notNull(),
|
||||
description: text("description"),
|
||||
color: varchar("color").default("#6b7280"), // Couleur d'affichage
|
||||
isSystem: boolean("is_system").default(false), // Rôles système non supprimables
|
||||
isActive: boolean("is_active").default(true),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
updatedAt: timestamp("updated_at").defaultNow(),
|
||||
});
|
||||
|
||||
// Permissions - Available permissions in the system
|
||||
export const permissions = pgTable("permissions", {
|
||||
id: serial("id").primaryKey(),
|
||||
name: varchar("name").notNull().unique(),
|
||||
displayName: varchar("display_name").notNull(),
|
||||
description: text("description"),
|
||||
category: varchar("category").notNull(), // dashboard, orders, deliveries, users, etc.
|
||||
action: varchar("action").notNull(), // read, create, update, delete, validate
|
||||
resource: varchar("resource").notNull(), // orders, deliveries, users, etc.
|
||||
isSystem: boolean("is_system").default(true), // Permissions système
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
});
|
||||
|
||||
// Role Permissions - Many to many relationship
|
||||
export const rolePermissions = pgTable("role_permissions", {
|
||||
roleId: integer("role_id").notNull(),
|
||||
permissionId: integer("permission_id").notNull(),
|
||||
createdAt: timestamp("created_at").defaultNow(),
|
||||
}, (table) => ({
|
||||
pk: primaryKey({ columns: [table.roleId, table.permissionId] })
|
||||
}));
|
||||
|
||||
// NocoDB configuration globale (une seule instance NocoDB partagée)
|
||||
export const nocodbConfig = pgTable("nocodb_config", {
|
||||
@@ -221,15 +188,7 @@ export const customerOrders = pgTable("customer_orders", {
|
||||
updatedAt: timestamp("updated_at").defaultNow(),
|
||||
});
|
||||
|
||||
// User Roles - Many to many relationship (supports multiple roles per user)
|
||||
export const userRoles = pgTable("user_roles", {
|
||||
userId: varchar("user_id").notNull(),
|
||||
roleId: integer("role_id").notNull(),
|
||||
assignedBy: varchar("assigned_by").notNull(), // Who assigned this role
|
||||
assignedAt: timestamp("assigned_at").defaultNow(),
|
||||
}, (table) => ({
|
||||
pk: primaryKey({ columns: [table.userId, table.roleId] })
|
||||
}));
|
||||
|
||||
|
||||
// DLC Products (Date Limite de Consommation)
|
||||
export const dlcProducts = pgTable("dlc_products", {
|
||||
@@ -273,7 +232,6 @@ export const tasks = pgTable("tasks", {
|
||||
// Relations
|
||||
export const usersRelations = relations(users, ({ many }) => ({
|
||||
userGroups: many(userGroups),
|
||||
userRoles: many(userRoles),
|
||||
createdOrders: many(orders),
|
||||
createdDeliveries: many(deliveries),
|
||||
createdPublicities: many(publicities),
|
||||
@@ -368,36 +326,7 @@ export const publicityParticipationsRelations = relations(publicityParticipation
|
||||
}),
|
||||
}));
|
||||
|
||||
export const rolesRelations = relations(roles, ({ many }) => ({
|
||||
userRoles: many(userRoles),
|
||||
rolePermissions: many(rolePermissions),
|
||||
}));
|
||||
|
||||
export const userRolesRelations = relations(userRoles, ({ one }) => ({
|
||||
user: one(users, {
|
||||
fields: [userRoles.userId],
|
||||
references: [users.id],
|
||||
}),
|
||||
role: one(roles, {
|
||||
fields: [userRoles.roleId],
|
||||
references: [roles.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const permissionsRelations = relations(permissions, ({ many }) => ({
|
||||
rolePermissions: many(rolePermissions),
|
||||
}));
|
||||
|
||||
export const rolePermissionsRelations = relations(rolePermissions, ({ one }) => ({
|
||||
role: one(roles, {
|
||||
fields: [rolePermissions.roleId],
|
||||
references: [roles.id],
|
||||
}),
|
||||
permission: one(permissions, {
|
||||
fields: [rolePermissions.permissionId],
|
||||
references: [permissions.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export const customerOrdersRelations = relations(customerOrders, ({ one }) => ({
|
||||
group: one(groups, {
|
||||
@@ -502,24 +431,7 @@ export const insertPublicityParticipationSchema = createInsertSchema(publicityPa
|
||||
createdAt: true,
|
||||
});
|
||||
|
||||
export const insertRoleSchema = createInsertSchema(roles).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
updatedAt: true,
|
||||
});
|
||||
|
||||
export const insertPermissionSchema = createInsertSchema(permissions).omit({
|
||||
id: true,
|
||||
createdAt: true,
|
||||
});
|
||||
|
||||
export const insertRolePermissionSchema = createInsertSchema(rolePermissions).omit({
|
||||
createdAt: true,
|
||||
});
|
||||
|
||||
export const insertUserRoleSchema = createInsertSchema(userRoles).omit({
|
||||
assignedAt: true,
|
||||
});
|
||||
|
||||
export const insertNocodbConfigSchema = createInsertSchema(nocodbConfig).omit({
|
||||
id: true,
|
||||
@@ -606,31 +518,6 @@ export type PublicityWithRelations = Publicity & {
|
||||
participations: (PublicityParticipation & { group: Group })[];
|
||||
};
|
||||
|
||||
export type Role = typeof roles.$inferSelect;
|
||||
export type InsertRole = z.infer<typeof insertRoleSchema>;
|
||||
|
||||
export type Permission = typeof permissions.$inferSelect;
|
||||
export type InsertPermission = z.infer<typeof insertPermissionSchema>;
|
||||
|
||||
export type RolePermission = typeof rolePermissions.$inferSelect;
|
||||
export type InsertRolePermission = z.infer<typeof insertRolePermissionSchema>;
|
||||
|
||||
export type UserRole = typeof userRoles.$inferSelect;
|
||||
export type InsertUserRole = z.infer<typeof insertUserRoleSchema>;
|
||||
|
||||
export type RoleWithPermissions = Role & {
|
||||
rolePermissions: (RolePermission & { permission: Permission })[];
|
||||
};
|
||||
|
||||
export type UserWithRoles = User & {
|
||||
userRoles: (UserRole & { role: Role })[];
|
||||
};
|
||||
|
||||
export type PermissionWithActions = Permission & {
|
||||
action: string;
|
||||
resource: string;
|
||||
};
|
||||
|
||||
export type NocodbConfig = typeof nocodbConfig.$inferSelect;
|
||||
export type InsertNocodbConfig = z.infer<typeof insertNocodbConfigSchema>;
|
||||
|
||||
@@ -643,11 +530,6 @@ export type CustomerOrderWithRelations = CustomerOrder & {
|
||||
supplier: Supplier;
|
||||
};
|
||||
|
||||
export type UserWithRole = User & {
|
||||
dynamicRole?: Role | null;
|
||||
userGroups: (UserGroup & { group: Group })[];
|
||||
};
|
||||
|
||||
export type DlcProduct = typeof dlcProducts.$inferSelect;
|
||||
export type InsertDlcProduct = z.infer<typeof insertDlcProductSchema>;
|
||||
|
||||
|
||||
Reference in new issue
Block a user