feat: Update rbac to allow multiple scopes

This commit is contained in:
IAmTomahawkx
2026-03-18 14:18:09 -07:00
parent fb968ec2da
commit 0df824fe99
3 changed files with 35 additions and 11 deletions
+23 -2
View File
@@ -1,7 +1,7 @@
import { getServerSession } from "next-auth";
import { redirect } from "next/navigation";
import { checkPermission, flattenPermissionsFor } from "./rbacEngine";
import { checkAnyPermission, flattenPermissionsFor } from "./rbacEngine";
/**
* Check whether the currently authorised user has a given scope and return them if such
@@ -16,7 +16,7 @@ export async function getScopedUser(scope: string) {
email: session.user.email,
});
if (!checkPermission(permissions, scope)) {
if (!checkAnyPermission(permissions, [scope])) {
console.debug(`${session.user.email} rejected, lacking ${scope}`);
return redirect("/panel/access-denied?missing=" + scope);
}
@@ -24,6 +24,27 @@ export async function getScopedUser(scope: string) {
return session.user.email;
}
/**
* Check whether the currently authorised user has a given scope and return them if such
* @param scope Required scope
* @returns User email
*/
export async function getMultiScopedUser(scopes: string[]) {
const session = await getServerSession();
if (!session?.user?.email) return redirect("/panel/access-denied");
const permissions = await flattenPermissionsFor({
email: session.user.email,
});
if (!checkAnyPermission(permissions, scopes)) {
console.debug(`${session.user.email} rejected, lacking any of ${scopes}`);
return redirect("/panel/access-denied?missing=" + scopes);
}
return session.user.email;
}
/**
* Check which of the given scopes are allowed to the given user
* @param scopes Scopes to check
+10 -7
View File
@@ -18,16 +18,19 @@ export async function flattenPermissionsFor(
return roles.flatMap((role) => role.permissions);
}
export function checkPermission(permissions: string[], permission: string) {
export function checkAnyPermission(permissions: string[], requested_permissions: string[]) {
if (permissions.includes("*")) return true;
const segments = permission.split(".");
while (segments.length) {
if (permissions.includes(segments.join("."))) {
return true;
}
for(let i=0; i<permissions.length; i++){
const permission = permissions[i];
const segments = permission.split(".");
while (segments.length) {
if (permissions.includes(segments.join("."))) {
return true;
}
segments.pop();
segments.pop();
}
}
return false;
+2 -2
View File
@@ -8,9 +8,9 @@ type AuthorisedUser = {
};
export function emailToImage(email: string) {
return email === "insert@revolt.chat"
return email === "insert@stoat.chat"
? "https://cdn.stoatusercontent.com/avatars/6rgg372gI2LrxCUx0CiA2R1Qs6eTtmC-2NpMq1Xa_3/e4332b6d70619b8a98086e532dbd4b9e.png"
: email === "tom@revolt.chat"
: email === "tom@stoat.chat"
? "https://cdn.stoatusercontent.com/avatars/gXhOXC82uHPk2EtWe0cvcE1Du7h1rjKFOhFcvqxKHp?max_side=256"
: "https://cdn.stoatusercontent.com/avatars/pYjK-QyMv92hy8GUM-b4IK1DMzYILys9s114khzzKY";
}