forked from administration/panel
feat: implement ACL for actions
parent
6d7681e2a1
commit
5969746252
|
@ -2,8 +2,16 @@ import { getServerSession } from "next-auth";
|
||||||
|
|
||||||
type Permission =
|
type Permission =
|
||||||
| "authifier"
|
| "authifier"
|
||||||
| `accounts${"" | `/fetch${"" | "/by-id"}`}`
|
| `accounts${
|
||||||
| `bots${"" | `/fetch${"" | "/by-id" | "/by-user"}`}`
|
| ""
|
||||||
|
| `/fetch${"" | "/by-id"}`
|
||||||
|
| "/disable"
|
||||||
|
| "/restore"
|
||||||
|
| `/deletion${"" | "/queue" | "/cancel"}`}`
|
||||||
|
| `bots${
|
||||||
|
| ""
|
||||||
|
| `/fetch${"" | "/by-id" | "/by-user"}`
|
||||||
|
| `/update${"" | "/discoverability"}`}`
|
||||||
| `channels${"" | `/fetch${"" | "/by-id" | "/dm"}` | `/create${"" | "/dm"}`}`
|
| `channels${"" | `/fetch${"" | "/by-id" | "/dm"}` | `/create${"" | "/dm"}`}`
|
||||||
| `messages${"" | `/fetch${"" | "/by-id"}`}`
|
| `messages${"" | `/fetch${"" | "/by-id"}`}`
|
||||||
| `reports${
|
| `reports${
|
||||||
|
@ -13,19 +21,43 @@ type Permission =
|
||||||
| "/by-id"
|
| "/by-id"
|
||||||
| "/open"
|
| "/open"
|
||||||
| `/related${"" | "/by-content" | "/by-user"}`
|
| `/related${"" | "/by-content" | "/by-user"}`
|
||||||
| `/snapshots${"" | "/by-report" | "/by-user"}`}`}`
|
| `/snapshots${"" | "/by-report" | "/by-user"}`}`
|
||||||
|
| `/update${
|
||||||
|
| ""
|
||||||
|
| "/notes"
|
||||||
|
| "/resolve"
|
||||||
|
| "/reject"
|
||||||
|
| "/reopen"
|
||||||
|
| `/bulk-close${"" | "/by-user"}`}`}`
|
||||||
| `sessions${"" | `/fetch${"" | "/by-account-id"}`}`
|
| `sessions${"" | `/fetch${"" | "/by-account-id"}`}`
|
||||||
| `servers${"" | `/fetch${"" | "/by-id"}`}`
|
| `servers${
|
||||||
| `users${"" | `/fetch${"" | "/by-id" | "/memberships"}`}`;
|
| ""
|
||||||
|
| `/fetch${"" | "/by-id"}`
|
||||||
|
| `/update${"" | "/flags" | "/discoverability"}`}`
|
||||||
|
| `users${
|
||||||
|
| ""
|
||||||
|
| `/fetch${"" | "/by-id" | "/memberships"}`
|
||||||
|
| `/create${"" | "/alert" | "/strike"}`
|
||||||
|
| `/update${"" | "/badges"}`
|
||||||
|
| `/action${"" | "/unsuspend" | "/suspend" | "/wipe" | "/ban"}`}`;
|
||||||
|
|
||||||
const ACL: Record<string, Set<Permission>> = {
|
const PermissionSets = {
|
||||||
"insert@revolt.chat": new Set([
|
"view-open-reports": [
|
||||||
|
// Required for viewing open reports
|
||||||
"users/fetch/by-id",
|
"users/fetch/by-id",
|
||||||
"reports/fetch/open",
|
"reports/fetch/open",
|
||||||
"reports/fetch/by-id",
|
"reports/fetch/by-id",
|
||||||
"reports/fetch/related",
|
"reports/fetch/related",
|
||||||
"reports/fetch/snapshots/by-report",
|
"reports/fetch/snapshots/by-report",
|
||||||
] as Permission[]),
|
] as Permission[],
|
||||||
|
};
|
||||||
|
|
||||||
|
const Roles = {
|
||||||
|
moderator: [...PermissionSets["view-open-reports"]],
|
||||||
|
};
|
||||||
|
|
||||||
|
const ACL: Record<string, Set<Permission>> = {
|
||||||
|
"insert@revolt.chat": new Set([...Roles["moderator"]] as Permission[]),
|
||||||
};
|
};
|
||||||
|
|
||||||
function hasPermission(email: string, permission: Permission) {
|
function hasPermission(email: string, permission: Permission) {
|
||||||
|
|
|
@ -25,9 +25,10 @@ import {
|
||||||
SessionInfo,
|
SessionInfo,
|
||||||
User,
|
User,
|
||||||
} from "revolt-api";
|
} from "revolt-api";
|
||||||
|
import { checkPermission } from "./accessPermissions";
|
||||||
|
|
||||||
export async function sendAlert(userId: string, content: string) {
|
export async function sendAlert(userId: string, content: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/create/alert");
|
||||||
|
|
||||||
const messageId = ulid();
|
const messageId = ulid();
|
||||||
|
|
||||||
|
@ -47,7 +48,7 @@ export async function createStrike(
|
||||||
givenReason: string,
|
givenReason: string,
|
||||||
additionalContext: string
|
additionalContext: string
|
||||||
) {
|
) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/create/strike");
|
||||||
|
|
||||||
const strike: AccountStrike & { moderator_id: string } = {
|
const strike: AccountStrike & { moderator_id: string } = {
|
||||||
_id: ulid(),
|
_id: ulid(),
|
||||||
|
@ -74,7 +75,7 @@ Further violations will result in suspension or a permanent ban depending on sev
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateReportNotes(reportId: string, notes: string) {
|
export async function updateReportNotes(reportId: string, notes: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("reports/update/notes");
|
||||||
|
|
||||||
return await mongo()
|
return await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
|
@ -90,7 +91,7 @@ export async function updateReportNotes(reportId: string, notes: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function resolveReport(reportId: string) {
|
export async function resolveReport(reportId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("reports/update/resolve");
|
||||||
|
|
||||||
const $set = {
|
const $set = {
|
||||||
status: "Resolved",
|
status: "Resolved",
|
||||||
|
@ -108,7 +109,7 @@ export async function resolveReport(reportId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function rejectReport(reportId: string, reason: string) {
|
export async function rejectReport(reportId: string, reason: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("reports/update/reject");
|
||||||
|
|
||||||
const $set = {
|
const $set = {
|
||||||
status: "Rejected",
|
status: "Rejected",
|
||||||
|
@ -127,7 +128,7 @@ export async function rejectReport(reportId: string, reason: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function reopenReport(reportId: string) {
|
export async function reopenReport(reportId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("reports/update/reopen");
|
||||||
|
|
||||||
const $set = {
|
const $set = {
|
||||||
status: "Created",
|
status: "Created",
|
||||||
|
@ -172,7 +173,7 @@ export async function closeReportsByUser(userId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function disableAccount(userId: string) {
|
export async function disableAccount(userId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("accounts/disable");
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
|
@ -185,8 +186,7 @@ export async function disableAccount(userId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function suspendUser(userId: string) {
|
export async function suspendUser(userId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/action/suspend");
|
||||||
|
|
||||||
await disableAccount(userId);
|
await disableAccount(userId);
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
|
@ -217,8 +217,7 @@ export async function suspendUser(userId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateUserBadges(userId: string, badges: number) {
|
export async function updateUserBadges(userId: string, badges: number) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/update/badges");
|
||||||
|
|
||||||
await mongo().db("revolt").collection<User>("users").updateOne(
|
await mongo().db("revolt").collection<User>("users").updateOne(
|
||||||
{
|
{
|
||||||
_id: userId,
|
_id: userId,
|
||||||
|
@ -244,7 +243,7 @@ export async function updateUserBadges(userId: string, badges: number) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function wipeUser(userId: string, flags = 4) {
|
export async function wipeUser(userId: string, flags = 4) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/action/wipe");
|
||||||
|
|
||||||
// retrieve messages, dm channels, relationships, server memberships
|
// retrieve messages, dm channels, relationships, server memberships
|
||||||
const backup = {
|
const backup = {
|
||||||
|
@ -341,14 +340,12 @@ export async function wipeUser(userId: string, flags = 4) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function banUser(userId: string) {
|
export async function banUser(userId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/action/ban");
|
||||||
|
|
||||||
return await wipeUser(userId, 4);
|
return await wipeUser(userId, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function unsuspendUser(userId: string) {
|
export async function unsuspendUser(userId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("users/action/unsuspend");
|
||||||
|
|
||||||
await restoreAccount(userId);
|
await restoreAccount(userId);
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
|
@ -367,8 +364,7 @@ export async function unsuspendUser(userId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateServerFlags(serverId: string, flags: number) {
|
export async function updateServerFlags(serverId: string, flags: number) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("servers/update/flags");
|
||||||
|
|
||||||
await mongo().db("revolt").collection<Server>("servers").updateOne(
|
await mongo().db("revolt").collection<Server>("servers").updateOne(
|
||||||
{
|
{
|
||||||
_id: serverId,
|
_id: serverId,
|
||||||
|
@ -394,8 +390,7 @@ export async function updateServerDiscoverability(
|
||||||
serverId: string,
|
serverId: string,
|
||||||
state: boolean
|
state: boolean
|
||||||
) {
|
) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("servers/update/discoverability");
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
.collection<Server>("servers")
|
.collection<Server>("servers")
|
||||||
|
@ -413,8 +408,7 @@ export async function updateServerDiscoverability(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function updateBotDiscoverability(botId: string, state: boolean) {
|
export async function updateBotDiscoverability(botId: string, state: boolean) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("bots/update/discoverability");
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
.collection<Bot>("bots")
|
.collection<Bot>("bots")
|
||||||
|
@ -432,8 +426,7 @@ export async function updateBotDiscoverability(botId: string, state: boolean) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function restoreAccount(accountId: string) {
|
export async function restoreAccount(accountId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("accounts/restore");
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
.collection<Account>("accounts")
|
.collection<Account>("accounts")
|
||||||
|
@ -450,8 +443,7 @@ export async function restoreAccount(accountId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function queueAccountDeletion(accountId: string) {
|
export async function queueAccountDeletion(accountId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("accounts/deletion/queue");
|
||||||
|
|
||||||
const twoWeeksFuture = new Date();
|
const twoWeeksFuture = new Date();
|
||||||
twoWeeksFuture.setDate(twoWeeksFuture.getDate() + 14);
|
twoWeeksFuture.setDate(twoWeeksFuture.getDate() + 14);
|
||||||
|
|
||||||
|
@ -477,8 +469,7 @@ export async function queueAccountDeletion(accountId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function cancelAccountDeletion(accountId: string) {
|
export async function cancelAccountDeletion(accountId: string) {
|
||||||
if (Math.random() > -1) throw "TODO: ACL";
|
await checkPermission("accounts/deletion/cancel");
|
||||||
|
|
||||||
await mongo()
|
await mongo()
|
||||||
.db("revolt")
|
.db("revolt")
|
||||||
.collection<Account>("accounts")
|
.collection<Account>("accounts")
|
||||||
|
|
Loading…
Reference in New Issue