1
0
Fork 0

feat: implement ACL for actions

fix-1
Paul Makles 2023-07-30 17:23:05 +01:00
parent 6d7681e2a1
commit 5969746252
No known key found for this signature in database
GPG Key ID: 5059F398521BB0F6
2 changed files with 59 additions and 36 deletions

View File

@ -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) {

View File

@ -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")