UNPKG

permissions.js

Version:

This module is a manager for permissions. With this module you can defined and host the permissions of user as a integer which makes it possible to limit the use of memory.

260 lines (259 loc) 9.53 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Permissions = void 0; /** * Create a Permissions class. * @class * @param {Array<Object>} [permissions] - The list of permissions. * @param {Bits} [bits = 0] - Actual permissions of user. */ class Permissions { constructor(permissions, bits) { this.bits = 0n; // User bits permissions if (!permissions) throw new TypeError("Permissions must be specified."); if (bits) this.bits = BigInt(bits); const permsArray = []; permissions.forEach((p, i) => { permsArray.push({ name: p, value: BigInt(1 << i) }); }); this.permissions = permsArray; } /** * The default permission. * @type {number} The default permission as a bit. */ get default() { return 0; } /** * Return all permissions as a integer. * @type {number} The bits permissions. */ get MAX() { let bit = BigInt(0); for (let flag of this.permissions) { bit += flag.value; } return bit.toString(); } /** * Return the permissions of member as a number. * @type {number} Return the bits of the permissions of user. */ get permissionCalc() { return this.bits.toString(); } /** * Get the value of the permission required. * @param {string|Array<string>} permissions The permission(s). * @returns {number} The value of permission(s) as a number. */ find(permissions) { if (typeof permissions === 'string' || typeof permissions === 'number') { const permission = this.permissions.find(f => f.name === permissions.toString().toUpperCase() || f.value === permissions); return permission ? permission : undefined; } if (Array.isArray(permissions)) { let result = []; permissions.map(p => { const permission = this.permissions.find(perm => perm.name === p.toString().toUpperCase() || perm.value === p); if (permission) result.push(permission); }); return result; } } /** * Return the permissions of user as an array * @returns {Array<string>} An array of permissions as a string. */ toArray() { let userPermissions = []; for (const permission of this.permissions) { if (this.bits & permission.value) userPermissions.push(permission.name); } return userPermissions; } /** * The permissions of user as a string. * @returns {string} A string representation of user permissions separated by `, `. */ toString() { return this.toArray().join(', '); } /** * Calcul the permissions of user * @returns {Array} */ calculate() { let bits = this.bits; const flags = [...this.permissions].reverse(); const userPermissions = []; for (let permission of flags) { const rest = bits % permission.value; if (rest == 0n && bits != 0n) { userPermissions.push(permission); break; } if (rest < bits) { userPermissions.push(permission); bits = rest; } } return userPermissions; } /** * Check if the user have permissions. * @returns {boolean} true if the user has permissions */ hasAnyPermissions() { if (this.bits > 0) return true; return false; } /** * Check if the user has a specific permission. * @param {Array<string>|String|Number} [permission] The permission required. * @returns {boolean} Return true if user has the specified permission. */ hasPermission(permission) { if (Array.isArray(permission)) return permission.every(p => this.hasPermission(p)); const permissionsArray = this.toArray(); if (permissionsArray.includes('ADMINISTRATOR')) return true; if (typeof permission === 'string') { if (permissionsArray.includes(permission)) return true; else return false; } if (typeof permission === 'number') { let hasPermissions = false; this.calculate().map(p => { if (p.value === permission) hasPermissions = true; }); return hasPermissions; } return false; } /** * Check if the user have specified permissions. * @param {string|Array<string|number>|number} permissionsList The permissions list. * @returns {null|permissions} Return null if user have all permissions or the missings permissions. */ missing(permissionsList) { if (Array.isArray(permissionsList)) permissionsList.every(pl => this.missing(pl)); if (!this.hasPermission(permissionsList)) return permissionsList; return null; } /** * * @param {string|number|Array<string|number>} permissionsother The permission(s) to compare. * @returns {boolean} true if the permissions specified are the same of user and false otherwise. */ equals(other) { let total = 0; if (Array.isArray(other)) return other.every(o => this.equals(o)); if (typeof other === 'string') { if (this.toArray().includes(other)) return true; } if (typeof other === 'number') { if (this.bits == BigInt(other)) return true; } if (BigInt(total) === this.bits) return true; return false; } /** * Add all permissions to the user. * @returns {number} the new permissions bits. */ addAllPermissions() { this.bits = BigInt(this.MAX); return this.bits.toString(); } /** * Add a permission to a user. * @param {string|Array<string>|number} permissionToAdd The new permission for user. * @returns {number} the new bits of permissions. */ addPermission(permissionToAdd) { const type = typeof permissionToAdd; if (Array.isArray(permissionToAdd)) return permissionToAdd.every(pta => this.addPermission(pta)); if (type === 'string') { const permission = this.permissions.find(p => p.name === permissionToAdd); const has = this.calculate().filter(p => p.name === permission?.name); if (has || !has.length) return this.bits.toString(); if (!permission) return new TypeError('Permission does not exist.'); this.bits += permission.value; return this.bits.toString(); } if (type === 'number') { const permission = this.permissions.find(p => p.value === permissionToAdd); const has = this.calculate().filter(p => p.value === permission?.value); if (has || !has.length) return this.bits.toString(); if (!permission) return new TypeError('Permission does not exist.'); this.bits += permission.value; return this.bits.toString(); } return new TypeError('The permission must be a string, an array or a number.'); } /** * Remove all permissions of the user. * @returns {number} the new bits of permissions. */ removeAllPermissions() { this.bits = 0n; return this.bits.toString(); } /** * Remove a permission to as user. * @param {string|Array<string>|number} permissionToAdd The permission to remove for user. * @returns {number} the new bits of permissions. */ removePermission(permissionToRemove) { const type = typeof permissionToRemove; if (Array.isArray(permissionToRemove)) return permissionToRemove.every(pta => this.addPermission(pta)); if (type === 'string') { const permission = this.permissions.find(p => p.name === permissionToRemove); const has = this.calculate().filter(p => p.name === permission?.name); if (!has || !has.length) return this.bits.toString(); if (!permission) return new TypeError('Permission does not exist.'); this.bits -= permission.value; return this.bits.toString(); } if (type === 'number') { const permission = this.permissions.find(p => p.value === permissionToRemove); const has = this.calculate().filter(p => p.value === permission?.value); if (!has || !has.length) return this.bits.toString(); if (!permission) return new TypeError('Permission does not exist.'); this.bits -= permission.value; return this.bits.toString(); } return new TypeError('The permission must be a string, an array or a number.'); } } exports.Permissions = Permissions;