Skip to content

Instantly share code, notes, and snippets.

@codersidprogrammer
Created March 19, 2025 01:52
Show Gist options
  • Save codersidprogrammer/7cb077254fe3bb1aba2ecb76aa2d3766 to your computer and use it in GitHub Desktop.
Save codersidprogrammer/7cb077254fe3bb1aba2ecb76aa2d3766 to your computer and use it in GitHub Desktop.
Sample of usage role as interface. So that we can generate class for every role
/**
*
[
{
"name": "VP",
"permissions": ["view_all_projects", "edit_all_projects"]
},
{
"name": "Manager",
"permissions": ["view_team_projects", "edit_team_projects"]
},
{
"name": "Employee",
"permissions": ["view_own_projects"]
}
]
*/
class ValidatorEngine {
private startRole: RoleInterface | null;
constructor() {
this.startRole = null;
}
/**
* Sets the starting role in the validation chain.
* @param role The starting role.
*/
setStartRole(role: RoleInterface): void {
this.startRole = role;
}
/**
* Validates permissions across the chain of roles.
* @param permissions The permissions to validate.
* @throws Error if any role in the chain fails validation.
*/
validate(permissions: string[]): void {
if (!this.startRole) {
throw new Error('No starting role set for validation');
}
let currentRole: RoleInterface | null = this.startRole;
while (currentRole) {
try {
currentRole.validatePermissions(permissions);
console.log(`Permissions validated for role: ${currentRole.name}`);
} catch (error) {
throw new Error(`Validation failed for role: ${currentRole.name}. ${error}`);
}
currentRole = currentRole.nextValidation;
}
}
/**
* Dynamically creates roles and sets up the validation chain from JSON data.
* @param rolesData Array of role data from JSON.
*/
setupRolesFromJson(rolesData: { name: string; permissions: string[] }[]): void {
let previousRole: RoleInterface | null = null;
rolesData.forEach((roleData, index) => {
let role: RoleInterface;
switch (roleData.name) {
case 'VP':
role = new VpRole();
break;
case 'Manager':
role = new ManagerRole();
break;
case 'Employee':
role = new EmployeeRole();
break;
default:
throw new Error(`Unknown role: ${roleData.name}`);
}
role.permissions = roleData.permissions;
if (index === 0) {
this.setStartRole(role);
}
if (previousRole) {
previousRole.setNextValidation(role);
role.setPrevValidation(previousRole);
}
previousRole = role;
});
}
}
// Example usage:
const rolesJson = [
{
name: "VP",
permissions: ["view_all_projects", "edit_all_projects"]
},
{
name: "Manager",
permissions: ["view_team_projects", "edit_team_projects"]
},
{
name: "Employee",
permissions: ["view_own_projects"]
}
];
const validatorEngine = new ValidatorEngine();
validatorEngine.setupRolesFromJson(rolesJson);
try {
// Validate permissions across the chain
validatorEngine.validate(['view_all_projects']);
validatorEngine.validate(['edit_team_projects']);
validatorEngine.validate(['view_own_projects']);
} catch (error) {
console.error(error);
}
interface RoleInterface {
name: string;
permissions: string[];
nextValidation: RoleInterface | null;
prevValidation: RoleInterface | null;
hasPermission(permission: string): boolean;
validatePermissions(permissions: string[]): void;
setNextValidation(role: RoleInterface): void;
setPrevValidation(role: RoleInterface): void;
}
class VpRole implements RoleInterface {
name: string;
permissions: string[];
nextValidation: RoleInterface | null;
prevValidation: RoleInterface | null;
constructor() {
this.name = 'VP';
this.permissions = ['view_all_projects', 'edit_all_projects'];
this.nextValidation = null;
this.prevValidation = null;
}
hasPermission(permission: string): boolean {
return this.permissions.includes(permission);
}
/**
* This function should have unique logic business
* logic for validating permissions for Vevery role
*
* @param permissions
*/
validatePermissions(permissions: string[]): void {
if (!permissions.every(permission => this.hasPermission(permission))) {
throw new Error('Invalid permissions for VP role');
}
}
setNextValidation(role: RoleInterface): void {
this.nextValidation = role;
}
setPrevValidation(role: RoleInterface): void {
this.prevValidation = role;
}
}
class ManagerRole implements RoleInterface {
name: string;
permissions: string[];
nextValidation: RoleInterface | null;
prevValidation: RoleInterface | null;
constructor() {
this.name = 'Manager';
this.permissions = ['view_team_projects', 'edit_team_projects'];
this.nextValidation = null;
this.prevValidation = null;
}
hasPermission(permission: string): boolean {
return this.permissions.includes(permission);
}
validatePermissions(permissions: string[]): void {
if (!permissions.every(permission => this.hasPermission(permission))) {
throw new Error('Invalid permissions for Manager role');
}
}
setNextValidation(role: RoleInterface): void {
this.nextValidation = role;
}
setPrevValidation(role: RoleInterface): void {
this.prevValidation = role;
}
}
class EmployeeRole implements RoleInterface {
name: string;
permissions: string[];
nextValidation: RoleInterface | null;
prevValidation: RoleInterface | null;
constructor() {
this.name = 'Employee';
this.permissions = ['view_own_projects'];
this.nextValidation = null;
this.prevValidation = null;
}
hasPermission(permission: string): boolean {
return this.permissions.includes(permission);
}
validatePermissions(permissions: string[]): void {
if (!permissions.every(permission => this.hasPermission(permission))) {
throw new Error('Invalid permissions for Employee role');
}
}
setNextValidation(role: RoleInterface): void {
this.nextValidation = role;
}
setPrevValidation(role: RoleInterface): void {
this.prevValidation = role;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment