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
JavaScript
"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;