mirror of
https://github.com/versia-pub/server.git
synced 2025-12-06 16:38:19 +01:00
feat(api): ✨ Implement glitch-soc /v1/notifications/destroy_multiple route
This commit is contained in:
parent
6dff872822
commit
5030d03404
112
server/api/api/v1/notifications/destroy_multiple/index.test.ts
Normal file
112
server/api/api/v1/notifications/destroy_multiple/index.test.ts
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
import { afterAll, beforeAll, describe, expect, test } from "bun:test";
|
||||
import { config } from "config-manager";
|
||||
import {
|
||||
deleteOldTestUsers,
|
||||
getTestStatuses,
|
||||
getTestUsers,
|
||||
sendTestRequest,
|
||||
} from "~tests/utils";
|
||||
import type { Notification as APINotification } from "~types/mastodon/notification";
|
||||
import { meta } from "./index";
|
||||
|
||||
await deleteOldTestUsers();
|
||||
|
||||
const { users, tokens, deleteUsers } = await getTestUsers(2);
|
||||
const statuses = await getTestStatuses(40, users[0]);
|
||||
let notifications: APINotification[] = [];
|
||||
|
||||
// Create some test notifications
|
||||
beforeAll(async () => {
|
||||
await fetch(
|
||||
new URL(`/api/v1/accounts/${users[0].id}/follow`, config.http.base_url),
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[1].accessToken}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
for (const i of [0, 1, 2, 3]) {
|
||||
await fetch(
|
||||
new URL(
|
||||
`/api/v1/statuses/${statuses[i].id}/favourite`,
|
||||
config.http.base_url,
|
||||
),
|
||||
{
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[1].accessToken}`,
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
notifications = await fetch(
|
||||
new URL("/api/v1/notifications", config.http.base_url),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[0].accessToken}`,
|
||||
},
|
||||
},
|
||||
).then((r) => r.json());
|
||||
|
||||
expect(notifications.length).toBe(5);
|
||||
});
|
||||
|
||||
afterAll(async () => {
|
||||
await deleteUsers();
|
||||
});
|
||||
|
||||
// /api/v1/notifications/destroy_multiple
|
||||
describe(meta.route, () => {
|
||||
test("should return 401 if not authenticated", async () => {
|
||||
const response = await sendTestRequest(
|
||||
new Request(new URL(meta.route, config.http.base_url), {
|
||||
method: "DELETE",
|
||||
}),
|
||||
);
|
||||
|
||||
expect(response.status).toBe(401);
|
||||
});
|
||||
|
||||
test("should dismiss notifications", async () => {
|
||||
const response = await sendTestRequest(
|
||||
new Request(
|
||||
new URL(
|
||||
`${meta.route}?${new URLSearchParams(
|
||||
notifications.slice(1).map((n) => ["ids[]", n.id]),
|
||||
).toString()}`,
|
||||
config.http.base_url,
|
||||
),
|
||||
{
|
||||
method: "DELETE",
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[0].accessToken}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
});
|
||||
|
||||
test("should not display dismissed notification", async () => {
|
||||
const response = await sendTestRequest(
|
||||
new Request(
|
||||
new URL("/api/v1/notifications", config.http.base_url),
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${tokens[0].accessToken}`,
|
||||
},
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
expect(response.status).toBe(200);
|
||||
|
||||
const output = await response.json();
|
||||
|
||||
expect(output.length).toBe(1);
|
||||
});
|
||||
});
|
||||
41
server/api/api/v1/notifications/destroy_multiple/index.ts
Normal file
41
server/api/api/v1/notifications/destroy_multiple/index.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { apiRoute, applyConfig, idValidator } from "@api";
|
||||
import { errorResponse, jsonResponse } from "@response";
|
||||
import { inArray } from "drizzle-orm";
|
||||
import { z } from "zod";
|
||||
import { db } from "~drizzle/db";
|
||||
import { notification } from "~drizzle/schema";
|
||||
|
||||
export const meta = applyConfig({
|
||||
allowedMethods: ["DELETE"],
|
||||
route: "/api/v1/notifications/destroy_multiple",
|
||||
ratelimits: {
|
||||
max: 100,
|
||||
duration: 60,
|
||||
},
|
||||
auth: {
|
||||
required: true,
|
||||
oauthPermissions: ["write:notifications"],
|
||||
},
|
||||
});
|
||||
|
||||
export const schema = z.object({
|
||||
ids: z.array(z.string().regex(idValidator)),
|
||||
});
|
||||
|
||||
export default apiRoute<typeof meta, typeof schema>(
|
||||
async (req, matchedRoute, extraData) => {
|
||||
const { user } = extraData.auth;
|
||||
if (!user) return errorResponse("Unauthorized", 401);
|
||||
|
||||
const { ids } = extraData.parsedRequest;
|
||||
|
||||
await db
|
||||
.update(notification)
|
||||
.set({
|
||||
dismissed: true,
|
||||
})
|
||||
.where(inArray(notification.id, ids));
|
||||
|
||||
return jsonResponse({});
|
||||
},
|
||||
);
|
||||
Loading…
Reference in a new issue