feat: better permissions management

This commit is contained in:
Yuzu 2022-08-19 11:44:39 -05:00
parent ba2d44246d
commit 673e5c9a3c

View File

@ -1,5 +1,13 @@
import { BitwisePermissionFlags } from '@biscuitland/api-types';
export interface BitField<T extends number | bigint> {
add(...bits: T[]): this;
remove(...bits: T[]): this;
has(bit: T): boolean;
any(bit: T): boolean;
equals(bit: T): boolean;
}
export type PermissionString = keyof typeof BitwisePermissionFlags;
export type PermissionResolvable =
| bigint
@ -7,22 +15,84 @@ export type PermissionResolvable =
| PermissionString[]
| BitwisePermissionFlags;
export class Permissions {
export class Permissions implements BitField<bigint> {
/** Stores a reference to BitwisePermissionFlags */
static Flags = BitwisePermissionFlags;
/** Falsy; Stores the lack of permissions*/
static None = 0n;
/** Stores all entity permissions */
bitfield: bigint;
/** Wheter to grant all other permissions to the administrator */
__admin__: boolean = true;
constructor(bitfield: PermissionResolvable) {
this.bitfield = Permissions.resolve(bitfield);
}
get array(): PermissionString[] {
// unsafe cast, do not edit
const permissions = Object.keys(Permissions.Flags) as PermissionString[];
return permissions.filter(bit => typeof bit === 'number' && this.has(bit));
}
add(...bits: PermissionResolvable[]): this {
let reduced: bigint = 0n;
for (const bit of bits) {
reduced |= Permissions.resolve(bit);
}
this.bitfield |= reduced;
return this;
}
remove(...bits: PermissionResolvable[]): this {
let reduced: bigint = 0n;
for (const bit of bits) {
reduced |= Permissions.resolve(bit);
}
this.bitfield &= ~reduced;
return this;
}
has(bit: PermissionResolvable): boolean {
if (this.bitfield & BigInt(Permissions.Flags.ADMINISTRATOR)) {
const bbit = Permissions.resolve(bit);
if (this.__admin__ && this.bitfield & BigInt(Permissions.Flags.ADMINISTRATOR)) {
return true;
}
return !!(this.bitfield & Permissions.resolve(bit));
return (this.bitfield & bbit) === bbit;
}
any(bit: PermissionResolvable): boolean {
const bbit = Permissions.resolve(bit);
if (this.__admin__ && this.bitfield & BigInt(Permissions.Flags.ADMINISTRATOR)) {
return true;
}
return (this.bitfield & bbit) === 0n;
}
equals(bit: PermissionResolvable): boolean {
return !!(this.bitfield & Permissions.resolve(bit));
}
/** Gets all permissions */
static get All(): bigint {
let reduced = 0n;
for (const key in BitwisePermissionFlags) {
const perm = BitwisePermissionFlags[key];
if (typeof perm === 'number') {
reduced += perm;
}
}
return reduced;
}
static resolve(bit: PermissionResolvable): bigint {
switch (typeof bit) {
case 'bigint':
@ -42,8 +112,16 @@ export class Permissions {
}
}
*[Symbol.iterator]() {
yield* this.array;
}
valueOf() {
return this.bitfield;
}
toJSON(): { fields: string[] } {
const fields = Object.keys(Permissions.Flags).filter((bit) => typeof bit !== 'string' && this.has(bit));
const fields = Object.keys(Permissions.Flags).filter((bit) => typeof bit === 'number' && this.has(bit));
return { fields };
}