v3: added playlist moderation permission
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 43s
All checks were successful
Build and Publish Docker Image / build-and-push (push) Successful in 43s
This commit is contained in:
@@ -2,11 +2,16 @@ import { type AuthPayload, type Role } from "../model/interfaces.ts";
|
||||
|
||||
// Named capabilities checked at enforcement points. Extend this union as new
|
||||
// gated capabilities are added (e.g. "invite:manage").
|
||||
export type Permission = "dump:moderate" | "comment:moderate" | "user:manage";
|
||||
export type Permission =
|
||||
| "dump:moderate"
|
||||
| "comment:moderate"
|
||||
| "playlist:moderate"
|
||||
| "user:manage";
|
||||
|
||||
const ALL_PERMISSIONS: readonly Permission[] = [
|
||||
"dump:moderate",
|
||||
"comment:moderate",
|
||||
"playlist:moderate",
|
||||
"user:manage",
|
||||
];
|
||||
|
||||
@@ -14,7 +19,7 @@ const ALL_PERMISSIONS: readonly Permission[] = [
|
||||
// and future); `moderator` gets the content-moderation permissions only.
|
||||
export const ROLE_PERMISSIONS: Record<Role, readonly Permission[]> = {
|
||||
admin: ALL_PERMISSIONS,
|
||||
moderator: ["dump:moderate", "comment:moderate"],
|
||||
moderator: ["dump:moderate", "comment:moderate", "playlist:moderate"],
|
||||
user: [],
|
||||
};
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
isUpdatePlaylistRequest,
|
||||
} from "../model/interfaces.ts";
|
||||
import { authMiddleware, type AuthState } from "../middleware/auth.ts";
|
||||
import { can } from "../lib/permissions.ts";
|
||||
import {
|
||||
addDumpToPlaylist,
|
||||
createPlaylist,
|
||||
@@ -72,13 +73,18 @@ router.put("/:playlistId", authMiddleware, async (ctx) => {
|
||||
ctx.params.playlistId,
|
||||
body,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
ctx.response.body = { success: true, data: playlist };
|
||||
});
|
||||
|
||||
// DELETE /api/playlists/:playlistId
|
||||
router.delete("/:playlistId", authMiddleware, (ctx) => {
|
||||
deletePlaylist(ctx.params.playlistId, ctx.state.user.userId);
|
||||
deletePlaylist(
|
||||
ctx.params.playlistId,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
|
||||
@@ -88,6 +94,7 @@ router.post("/:playlistId/dumps/:dumpId", authMiddleware, (ctx) => {
|
||||
ctx.params.playlistId,
|
||||
ctx.params.dumpId,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
@@ -98,6 +105,7 @@ router.delete("/:playlistId/dumps/:dumpId", authMiddleware, (ctx) => {
|
||||
ctx.params.playlistId,
|
||||
ctx.params.dumpId,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
ctx.response.status = 204;
|
||||
});
|
||||
@@ -129,6 +137,7 @@ router.post("/:playlistId/image", authMiddleware, async (ctx) => {
|
||||
ctx.params.playlistId,
|
||||
mime,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
const filePath = `${PLAYLIST_IMAGES_DIR}/${playlist.id}`;
|
||||
await Deno.mkdir(PLAYLIST_IMAGES_DIR, { recursive: true });
|
||||
@@ -166,7 +175,12 @@ router.put("/:playlistId/order", authMiddleware, async (ctx) => {
|
||||
"Invalid request",
|
||||
);
|
||||
}
|
||||
reorderPlaylist(ctx.params.playlistId, body.dumpIds, ctx.state.user.userId);
|
||||
reorderPlaylist(
|
||||
ctx.params.playlistId,
|
||||
body.dumpIds,
|
||||
ctx.state.user.userId,
|
||||
can(ctx.state.user, "playlist:moderate"),
|
||||
);
|
||||
ctx.response.body = { success: true, data: null };
|
||||
});
|
||||
|
||||
|
||||
@@ -159,10 +159,11 @@ export function updatePlaylist(
|
||||
playlistId: string,
|
||||
req: UpdatePlaylistRequest,
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): Playlist {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
|
||||
@@ -212,10 +213,11 @@ export function updatePlaylist(
|
||||
export function deletePlaylist(
|
||||
playlistId: string,
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): void {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
|
||||
@@ -227,9 +229,10 @@ export function setPlaylistImage(
|
||||
playlistId: string,
|
||||
imageMime: string,
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): Playlist {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
db.prepare(`UPDATE playlists SET image_mime = ? WHERE id = ?;`).run(
|
||||
@@ -245,10 +248,11 @@ export function addDumpToPlaylist(
|
||||
playlistId: string,
|
||||
dumpId: string,
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): void {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
|
||||
@@ -298,10 +302,11 @@ export function removeDumpFromPlaylist(
|
||||
playlistId: string,
|
||||
dumpId: string,
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): void {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
|
||||
@@ -317,10 +322,11 @@ export function reorderPlaylist(
|
||||
playlistId: string,
|
||||
dumpIds: string[],
|
||||
requestingUserId: string,
|
||||
canModerate: boolean,
|
||||
): void {
|
||||
const playlist = getPlaylistById(playlistId);
|
||||
|
||||
if (playlist.userId !== requestingUserId) {
|
||||
if (playlist.userId !== requestingUserId && !canModerate) {
|
||||
throw new APIException(APIErrorCode.UNAUTHORIZED, 403, "Forbidden");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user