3
0
Fork 0
mirror of https://github.com/ZeppelinBot/Zeppelin.git synced 2025-03-18 15:00:00 +00:00
zeppelin/shared/src/apiPermissions.ts

105 lines
3.1 KiB
TypeScript
Raw Normal View History

2019-11-02 22:12:07 +02:00
export enum ApiPermissions {
Owner = "OWNER",
ManageAccess = "MANAGE_ACCESS",
EditConfig = "EDIT_CONFIG",
ReadConfig = "READ_CONFIG",
ViewGuild = "VIEW_GUILD",
2019-11-02 22:12:07 +02:00
}
2019-11-08 00:04:24 +02:00
const reverseApiPermissions = Object.entries(ApiPermissions).reduce((map, [key, value]) => {
map[value] = key;
return map;
}, {});
export const permissionNames = {
[ApiPermissions.Owner]: "Server owner",
[ApiPermissions.ManageAccess]: "Bot manager",
[ApiPermissions.EditConfig]: "Bot operator",
2019-11-08 00:04:24 +02:00
[ApiPermissions.ReadConfig]: "Read config",
[ApiPermissions.ViewGuild]: "View server",
2019-11-02 22:12:07 +02:00
};
2019-11-08 00:04:24 +02:00
export type TPermissionHierarchy = Array<ApiPermissions | [ApiPermissions, TPermissionHierarchy]>;
// prettier-ignore
2019-11-08 00:04:24 +02:00
export const permissionHierarchy: TPermissionHierarchy = [
[ApiPermissions.Owner, [
[ApiPermissions.ManageAccess, [
[ApiPermissions.EditConfig, [
[ApiPermissions.ReadConfig, [
ApiPermissions.ViewGuild,
]],
]],
]],
]],
2019-11-08 00:04:24 +02:00
];
export function permissionArrToSet(permissions: string[]): Set<ApiPermissions> {
2021-09-11 19:06:51 +03:00
return new Set(permissions.filter((p) => reverseApiPermissions[p])) as Set<ApiPermissions>;
2019-11-08 00:04:24 +02:00
}
2019-11-02 22:12:07 +02:00
/**
* Checks whether granted permissions include the specified permission, taking into account permission hierarchy i.e.
* that in the case of nested permissions, having a top level permission implicitly grants you any permissions nested
* under it as well
*/
2019-11-08 00:04:24 +02:00
export function hasPermission(grantedPermissions: Set<ApiPermissions>, permissionToCheck: ApiPermissions): boolean {
2019-11-02 22:12:07 +02:00
// Directly granted
2019-11-08 00:04:24 +02:00
if (grantedPermissions.has(permissionToCheck)) {
2019-11-02 22:12:07 +02:00
return true;
}
// Check by hierarchy
if (checkTreeForPermission(permissionHierarchy, grantedPermissions, permissionToCheck)) {
return true;
}
return false;
}
function checkTreeForPermission(
2019-11-08 00:04:24 +02:00
tree: TPermissionHierarchy,
grantedPermissions: Set<ApiPermissions>,
2019-11-02 22:12:07 +02:00
permission: ApiPermissions,
): boolean {
2019-11-08 00:04:24 +02:00
for (const item of tree) {
const [perm, nested] = Array.isArray(item) ? item : [item];
2019-11-02 22:12:07 +02:00
// Top-level permission granted, implicitly grant all nested permissions as well
2019-11-08 00:04:24 +02:00
if (grantedPermissions.has(perm)) {
2019-11-02 22:12:07 +02:00
// Permission we were looking for was found nested under this permission -> granted
2019-11-08 00:04:24 +02:00
if (nested && treeIncludesPermission(nested, permission)) {
2019-11-02 22:12:07 +02:00
return true;
}
// Permission we were looking for was not found nested under this permission
// Since direct grants are not handled by this function, we can skip any further checks for this nested tree
continue;
}
// Top-level permission not granted, check further nested permissions
2019-11-08 00:04:24 +02:00
if (nested && checkTreeForPermission(nested, grantedPermissions, permission)) {
2019-11-02 22:12:07 +02:00
return true;
}
}
return false;
}
2019-11-08 00:04:24 +02:00
function treeIncludesPermission(tree: TPermissionHierarchy, permission: ApiPermissions): boolean {
for (const item of tree) {
const [perm, nested] = Array.isArray(item) ? item : [item];
2019-11-02 22:12:07 +02:00
if (perm === permission) {
return true;
}
2019-11-08 00:04:24 +02:00
const nestedResult = nested && treeIncludesPermission(nested, permission);
2019-11-02 22:12:07 +02:00
if (nestedResult) {
return true;
}
}
return false;
}