/** * Plugin for handling permissions. */ class PermissionsPlugin { /** * Predefined roles and their corresponding permissions. */ static defaultRoles = { OWNER: 0o777, ADMIN: 0o755, MODERATOR: 0o644, MEMBER: 0o444, GUEST: 0o400, }; /** * Actions and their corresponding required permissions. */ static defaultActions = { SEND_MESSAGE: 0o400, MUTE_MEMBER: 0o200, KICK_MEMBER: 0o200, GRANT_PERMISSION: 0o100, REVOKE_PERMISSION: 0o100, ASSIGN_ROLE: 0o100, }; /** * Create a new instance of the PermissionsPlugin. * @param {Object} [config={}] - The configuration object. * @param {Object} [config.roles] - The custom roles and their corresponding permissions. * @param {Object} [config.actions] - The custom actions and their corresponding required permissions. */ constructor(config = {}) { this.roles = { ...PermissionsPlugin.defaultRoles, ...config.roles }; this.actions = { ...PermissionsPlugin.defaultActions, ...config.actions }; } /** * Initialize the plugin. * @param {Object} server - The server instance. */ initialize(server) { this.server = server; this.contexts = new Map(); // Listen for the 'permissions:init' event server.on('permissions:init', (pluginId, context, initContext) => { const key = pluginId + context; this.contexts.set(key, new Map()); initContext({ get: (...args) => this.getPermissions(key, ...args), has: (...args) => this.hasPermission(key, ...args), can: (...args) => this.hasPermission(key, ...args), add: (...args) => this.grantPermission(key, ...args), remove: (...args) => this.revokePermission(key, ...args), role: (...args) => this.assignRole(key, ...args), }); }); } /** * Get the permissions for the specified key and identifier. * @param {string} key - The unique key identifying the plugin and context. * @param {string} identifier - The identifier of the entity (e.g., user, member). * @returns {Object} The permissions object. */ getPermissions(key, identifier) { const context = this.contexts.get(key); if (context) { const permissions = context.get(identifier); if (permissions) { const result = {}; for (const [action, requiredPermission] of Object.entries(this.actions)) { result[action] = this.hasPermission(permissions, requiredPermission); } return result; } } return {}; } /** * Check if the specified key and identifier has the given permission. * @param {string} key - The unique key identifying the plugin and context. * @param {string} identifier - The identifier of the entity (e.g., user, member). * @param {string} action - The action to check permissions for. * @returns {boolean} True if the identifier has the permission, false otherwise. */ hasPermission(key, identifier, action) { const context = this.contexts.get(key); if (context) { const permissions = context.get(identifier); if (permissions) { const requiredPermission = this.actions[action]; return (permissions & requiredPermission) === requiredPermission; } } return false; } /** * Grant permission to the specified key and identifier for the given action. * @param {string} key - The unique key identifying the plugin and context. * @param {string} identifier - The identifier of the entity (e.g., user, member). * @param {string} action - The action to grant permission for. */ grantPermission(key, identifier, action) { const context = this.contexts.get(key); if (context) { const permissions = context.get(identifier) || 0; context.set(identifier, permissions | this.actions[action]); } } /** * Revoke permission from the specified key and identifier for the given action. * @param {string} key - The unique key identifying the plugin and context. * @param {string} identifier - The identifier of the entity (e.g., user, member). * @param {string} action - The action to revoke permission for. */ revokePermission(key, identifier, action) { const context = this.contexts.get(key); if (context) { const permissions = context.get(identifier); if (permissions) { context.set(identifier, permissions & ~this.actions[action]); } } } /** * Assign a role to the specified key and identifier. * @param {string} key - The unique key identifying the plugin and context. * @param {string} identifier - The identifier of the entity (e.g., user, member). * @param {string} role - The role to assign. */ assignRole(key, identifier, role) { const context = this.contexts.get(key); if (context) { context.set(identifier, this.roles[role]); } } }