summaryrefslogtreecommitdiff
path: root/packages/backend/src/server/api/endpoints/admin
diff options
context:
space:
mode:
authordakkar <dakkar@thenautilus.net>2024-08-02 12:25:58 +0100
committerdakkar <dakkar@thenautilus.net>2024-08-02 12:25:58 +0100
commitcfa9b852df9e0293865b3acbd67d59265962e552 (patch)
treea408ad670956a45c4e162e4ecc97a3624e2b0f20 /packages/backend/src/server/api/endpoints/admin
parentmerge: rate limit all password checks - fixes #540 (!568) (diff)
parentMerge pull request #14233 from misskey-dev/develop (diff)
downloadsharkey-cfa9b852df9e0293865b3acbd67d59265962e552.tar.gz
sharkey-cfa9b852df9e0293865b3acbd67d59265962e552.tar.bz2
sharkey-cfa9b852df9e0293865b3acbd67d59265962e552.zip
Merge remote-tracking branch 'misskey/master' into feature/misskey-2024.07
Diffstat (limited to 'packages/backend/src/server/api/endpoints/admin')
-rw-r--r--packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts122
-rw-r--r--packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts44
-rw-r--r--packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts55
-rw-r--r--packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts64
-rw-r--r--packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts128
-rw-r--r--packages/backend/src/server/api/endpoints/admin/ad/create.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/ad/update.ts6
-rw-r--r--packages/backend/src/server/api/endpoints/admin/announcements/list.ts9
-rw-r--r--packages/backend/src/server/api/endpoints/admin/drive/show-file.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/invite/create.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/meta.ts11
-rw-r--r--packages/backend/src/server/api/endpoints/admin/queue/stats.ts5
-rw-r--r--packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts53
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/update.ts14
-rw-r--r--packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts85
-rw-r--r--packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts44
-rw-r--r--packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts60
-rw-r--r--packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts62
-rw-r--r--packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts91
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-meta.ts15
20 files changed, 817 insertions, 61 deletions
diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts
new file mode 100644
index 0000000000..bdfbcba518
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/create.ts
@@ -0,0 +1,122 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ApiError } from '@/server/api/error.js';
+import {
+ AbuseReportNotificationRecipientEntityService,
+} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js';
+import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
+import { DI } from '@/di-symbols.js';
+import type { UserProfilesRepository } from '@/models/_.js';
+
+export const meta = {
+ tags: ['admin', 'abuse-report', 'notification-recipient'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:abuse-report:notification-recipient',
+
+ res: {
+ type: 'object',
+ ref: 'AbuseReportNotificationRecipient',
+ },
+
+ errors: {
+ correlationCheckEmail: {
+ message: 'If "method" is email, "userId" must be set.',
+ code: 'CORRELATION_CHECK_EMAIL',
+ id: '348bb8ae-575a-6fe9-4327-5811999def8f',
+ httpStatusCode: 400,
+ },
+ correlationCheckWebhook: {
+ message: 'If "method" is webhook, "systemWebhookId" must be set.',
+ code: 'CORRELATION_CHECK_WEBHOOK',
+ id: 'b0c15051-de2d-29ef-260c-9585cddd701a',
+ httpStatusCode: 400,
+ },
+ emailAddressNotSet: {
+ message: 'Email address is not set.',
+ code: 'EMAIL_ADDRESS_NOT_SET',
+ id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f',
+ httpStatusCode: 400,
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ isActive: {
+ type: 'boolean',
+ },
+ name: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 255,
+ },
+ method: {
+ type: 'string',
+ enum: ['email', 'webhook'],
+ },
+ userId: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ systemWebhookId: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: [
+ 'isActive',
+ 'name',
+ 'method',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ @Inject(DI.userProfilesRepository)
+ private userProfilesRepository: UserProfilesRepository,
+ private abuseReportNotificationService: AbuseReportNotificationService,
+ private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ if (ps.method === 'email') {
+ const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId });
+ if (!ps.userId || !userProfile) {
+ throw new ApiError(meta.errors.correlationCheckEmail);
+ }
+
+ if (!userProfile.email || !userProfile.emailVerified) {
+ throw new ApiError(meta.errors.emailAddressNotSet);
+ }
+ }
+
+ if (ps.method === 'webhook' && !ps.systemWebhookId) {
+ throw new ApiError(meta.errors.correlationCheckWebhook);
+ }
+
+ const userId = ps.method === 'email' ? ps.userId : null;
+ const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null;
+ const result = await this.abuseReportNotificationService.createRecipient(
+ {
+ isActive: ps.isActive,
+ name: ps.name,
+ method: ps.method,
+ userId: userId ?? null,
+ systemWebhookId: systemWebhookId ?? null,
+ },
+ me,
+ );
+
+ return this.abuseReportNotificationRecipientEntityService.pack(result);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts
new file mode 100644
index 0000000000..b6dc44e09c
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/delete.ts
@@ -0,0 +1,44 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
+
+export const meta = {
+ tags: ['admin', 'abuse-report', 'notification-recipient'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:abuse-report:notification-recipient',
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: [
+ 'id',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private abuseReportNotificationService: AbuseReportNotificationService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ await this.abuseReportNotificationService.deleteRecipient(
+ ps.id,
+ me,
+ );
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts
new file mode 100644
index 0000000000..dad9161a8a
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/list.ts
@@ -0,0 +1,55 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import {
+ AbuseReportNotificationRecipientEntityService,
+} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js';
+import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
+
+export const meta = {
+ tags: ['admin', 'abuse-report', 'notification-recipient'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'read:admin:abuse-report:notification-recipient',
+
+ res: {
+ type: 'array',
+ items: {
+ type: 'object',
+ ref: 'AbuseReportNotificationRecipient',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ method: {
+ type: 'array',
+ items: {
+ type: 'string',
+ enum: ['email', 'webhook'],
+ },
+ },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private abuseReportNotificationService: AbuseReportNotificationService,
+ private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService,
+ ) {
+ super(meta, paramDef, async (ps) => {
+ const recipients = await this.abuseReportNotificationService.fetchRecipients({ method: ps.method });
+ return this.abuseReportNotificationRecipientEntityService.packMany(recipients);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts
new file mode 100644
index 0000000000..557798f946
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/show.ts
@@ -0,0 +1,64 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import {
+ AbuseReportNotificationRecipientEntityService,
+} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js';
+import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
+import { ApiError } from '@/server/api/error.js';
+
+export const meta = {
+ tags: ['admin', 'abuse-report', 'notification-recipient'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'read:admin:abuse-report:notification-recipient',
+
+ res: {
+ type: 'object',
+ ref: 'AbuseReportNotificationRecipient',
+ },
+
+ errors: {
+ noSuchRecipient: {
+ message: 'No such recipient.',
+ code: 'NO_SUCH_RECIPIENT',
+ id: '013de6a8-f757-04cb-4d73-cc2a7e3368e4',
+ kind: 'server',
+ httpStatusCode: 404,
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: ['id'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private abuseReportNotificationService: AbuseReportNotificationService,
+ private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService,
+ ) {
+ super(meta, paramDef, async (ps) => {
+ const recipients = await this.abuseReportNotificationService.fetchRecipients({ ids: [ps.id] });
+ if (recipients.length === 0) {
+ throw new ApiError(meta.errors.noSuchRecipient);
+ }
+
+ return this.abuseReportNotificationRecipientEntityService.pack(recipients[0]);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts
new file mode 100644
index 0000000000..bd4b485217
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/abuse-report/notification-recipient/update.ts
@@ -0,0 +1,128 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Inject, Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { ApiError } from '@/server/api/error.js';
+import {
+ AbuseReportNotificationRecipientEntityService,
+} from '@/core/entities/AbuseReportNotificationRecipientEntityService.js';
+import { AbuseReportNotificationService } from '@/core/AbuseReportNotificationService.js';
+import { DI } from '@/di-symbols.js';
+import type { UserProfilesRepository } from '@/models/_.js';
+
+export const meta = {
+ tags: ['admin', 'abuse-report', 'notification-recipient'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:abuse-report:notification-recipient',
+
+ res: {
+ type: 'object',
+ ref: 'AbuseReportNotificationRecipient',
+ },
+
+ errors: {
+ correlationCheckEmail: {
+ message: 'If "method" is email, "userId" must be set.',
+ code: 'CORRELATION_CHECK_EMAIL',
+ id: '348bb8ae-575a-6fe9-4327-5811999def8f',
+ httpStatusCode: 400,
+ },
+ correlationCheckWebhook: {
+ message: 'If "method" is webhook, "systemWebhookId" must be set.',
+ code: 'CORRELATION_CHECK_WEBHOOK',
+ id: 'b0c15051-de2d-29ef-260c-9585cddd701a',
+ httpStatusCode: 400,
+ },
+ emailAddressNotSet: {
+ message: 'Email address is not set.',
+ code: 'EMAIL_ADDRESS_NOT_SET',
+ id: '7cc1d85e-2f58-fc31-b644-3de8d0d3421f',
+ httpStatusCode: 400,
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ isActive: {
+ type: 'boolean',
+ },
+ name: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 255,
+ },
+ method: {
+ type: 'string',
+ enum: ['email', 'webhook'],
+ },
+ userId: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ systemWebhookId: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: [
+ 'id',
+ 'isActive',
+ 'name',
+ 'method',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ @Inject(DI.userProfilesRepository)
+ private userProfilesRepository: UserProfilesRepository,
+ private abuseReportNotificationService: AbuseReportNotificationService,
+ private abuseReportNotificationRecipientEntityService: AbuseReportNotificationRecipientEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ if (ps.method === 'email') {
+ const userProfile = await this.userProfilesRepository.findOneBy({ userId: ps.userId });
+ if (!ps.userId || !userProfile) {
+ throw new ApiError(meta.errors.correlationCheckEmail);
+ }
+
+ if (!userProfile.email || !userProfile.emailVerified) {
+ throw new ApiError(meta.errors.emailAddressNotSet);
+ }
+ }
+
+ if (ps.method === 'webhook' && !ps.systemWebhookId) {
+ throw new ApiError(meta.errors.correlationCheckWebhook);
+ }
+
+ const userId = ps.method === 'email' ? ps.userId : null;
+ const systemWebhookId = ps.method === 'webhook' ? ps.systemWebhookId : null;
+ const result = await this.abuseReportNotificationService.updateRecipient(
+ {
+ id: ps.id,
+ isActive: ps.isActive,
+ name: ps.name,
+ method: ps.method,
+ userId: userId ?? null,
+ systemWebhookId: systemWebhookId ?? null,
+ },
+ me,
+ );
+
+ return this.abuseReportNotificationRecipientEntityService.pack(result);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/create.ts b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
index 1e7a9fb3ec..955154f4fb 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/create.ts
@@ -50,7 +50,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
- const ad = await this.adsRepository.insert({
+ const ad = await this.adsRepository.insertOne({
id: this.idService.gen(),
expiresAt: new Date(ps.expiresAt),
startsAt: new Date(ps.startsAt),
@@ -61,7 +61,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
ratio: ps.ratio,
place: ps.place,
memo: ps.memo,
- }).then(r => this.adsRepository.findOneByOrFail({ id: r.identifiers[0].id }));
+ });
this.moderationLogService.log(me, 'createAd', {
adId: ad.id,
diff --git a/packages/backend/src/server/api/endpoints/admin/ad/update.ts b/packages/backend/src/server/api/endpoints/admin/ad/update.ts
index 62358457ff..4e3d731aca 100644
--- a/packages/backend/src/server/api/endpoints/admin/ad/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/ad/update.ts
@@ -40,7 +40,7 @@ export const paramDef = {
startsAt: { type: 'integer' },
dayOfWeek: { type: 'integer' },
},
- required: ['id', 'memo', 'url', 'imageUrl', 'place', 'priority', 'ratio', 'expiresAt', 'startsAt', 'dayOfWeek'],
+ required: ['id'],
} as const;
@Injectable()
@@ -63,8 +63,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
ratio: ps.ratio,
memo: ps.memo,
imageUrl: ps.imageUrl,
- expiresAt: new Date(ps.expiresAt),
- startsAt: new Date(ps.startsAt),
+ expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : undefined,
+ startsAt: ps.startsAt ? new Date(ps.startsAt) : undefined,
dayOfWeek: ps.dayOfWeek,
});
diff --git a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
index 87eaad31a3..7596bf44e3 100644
--- a/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
+++ b/packages/backend/src/server/api/endpoints/admin/announcements/list.ts
@@ -69,6 +69,7 @@ export const paramDef = {
sinceId: { type: 'string', format: 'misskey:id' },
untilId: { type: 'string', format: 'misskey:id' },
userId: { type: 'string', format: 'misskey:id', nullable: true },
+ status: { type: 'string', enum: ['all', 'active', 'archived'], default: 'active' },
},
required: [],
} as const;
@@ -87,7 +88,13 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
) {
super(meta, paramDef, async (ps, me) => {
const query = this.queryService.makePaginationQuery(this.announcementsRepository.createQueryBuilder('announcement'), ps.sinceId, ps.untilId);
- query.andWhere('announcement.isActive = true');
+
+ if (ps.status === 'archived') {
+ query.andWhere('announcement.isActive = false');
+ } else if (ps.status === 'active') {
+ query.andWhere('announcement.isActive = true');
+ }
+
if (ps.userId) {
query.andWhere('announcement.userId = :userId', { userId: ps.userId });
} else {
diff --git a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
index 459d8880fa..a7136d8c8c 100644
--- a/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
+++ b/packages/backend/src/server/api/endpoints/admin/drive/show-file.ts
@@ -61,7 +61,7 @@ export const meta = {
name: {
type: 'string',
optional: false, nullable: false,
- example: 'lenna.jpg',
+ example: '192.jpg',
},
type: {
type: 'string',
diff --git a/packages/backend/src/server/api/endpoints/admin/invite/create.ts b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
index 0f551e1ba2..5ecae3161a 100644
--- a/packages/backend/src/server/api/endpoints/admin/invite/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/invite/create.ts
@@ -66,11 +66,11 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
const ticketsPromises = [];
for (let i = 0; i < ps.count; i++) {
- ticketsPromises.push(this.registrationTicketsRepository.insert({
+ ticketsPromises.push(this.registrationTicketsRepository.insertOne({
id: this.idService.gen(),
expiresAt: ps.expiresAt ? new Date(ps.expiresAt) : null,
code: generateInviteCode(),
- }).then(x => this.registrationTicketsRepository.findOneByOrFail(x.identifiers[0])));
+ }));
}
const tickets = await Promise.all(ticketsPromises);
diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts
index ca4d63b834..063bb6751b 100644
--- a/packages/backend/src/server/api/endpoints/admin/meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/meta.ts
@@ -132,6 +132,16 @@ export const meta = {
nullable: false,
},
},
+ mediaSilencedHosts: {
+ type: 'array',
+ optional: false,
+ nullable: false,
+ items: {
+ type: 'string',
+ optional: false,
+ nullable: false,
+ },
+ },
pinnedUsers: {
type: 'array',
optional: false, nullable: false,
@@ -586,6 +596,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts,
silencedHosts: instance.silencedHosts,
+ mediaSilencedHosts: instance.mediaSilencedHosts,
sensitiveWords: instance.sensitiveWords,
prohibitedWords: instance.prohibitedWords,
preservedUsernames: instance.preservedUsernames,
diff --git a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
index 9694b3fa40..d7f9e4eaa3 100644
--- a/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
+++ b/packages/backend/src/server/api/endpoints/admin/queue/stats.ts
@@ -5,7 +5,7 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, WebhookDeliverQueue } from '@/core/QueueModule.js';
+import type { DbQueue, DeliverQueue, EndedPollNotificationQueue, InboxQueue, ObjectStorageQueue, SystemQueue, UserWebhookDeliverQueue, SystemWebhookDeliverQueue } from '@/core/QueueModule.js';
export const meta = {
tags: ['admin'],
@@ -53,7 +53,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
@Inject('queue:inbox') public inboxQueue: InboxQueue,
@Inject('queue:db') public dbQueue: DbQueue,
@Inject('queue:objectStorage') public objectStorageQueue: ObjectStorageQueue,
- @Inject('queue:webhookDeliver') public webhookDeliverQueue: WebhookDeliverQueue,
+ @Inject('queue:userWebhookDeliver') public userWebhookDeliverQueue: UserWebhookDeliverQueue,
+ @Inject('queue:systemWebhookDeliver') public systemWebhookDeliverQueue: SystemWebhookDeliverQueue,
) {
super(meta, paramDef, async (ps, me) => {
const deliverJobCounts = await this.deliverQueue.getJobCounts();
diff --git a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
index 8b0456068b..9b79100fcf 100644
--- a/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
+++ b/packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts
@@ -5,12 +5,10 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
-import type { UsersRepository, AbuseUserReportsRepository } from '@/models/_.js';
-import { InstanceActorService } from '@/core/InstanceActorService.js';
-import { QueueService } from '@/core/QueueService.js';
-import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
+import type { AbuseUserReportsRepository } from '@/models/_.js';
import { DI } from '@/di-symbols.js';
-import { ModerationLogService } from '@/core/ModerationLogService.js';
+import { ApiError } from '@/server/api/error.js';
+import { AbuseReportService } from '@/core/AbuseReportService.js';
export const meta = {
tags: ['admin'],
@@ -18,6 +16,16 @@ export const meta = {
requireCredential: true,
requireModerator: true,
kind: 'write:admin:resolve-abuse-user-report',
+
+ errors: {
+ noSuchAbuseReport: {
+ message: 'No such abuse report.',
+ code: 'NO_SUCH_ABUSE_REPORT',
+ id: 'ac3794dd-2ce4-d878-e546-73c60c06b398',
+ kind: 'server',
+ httpStatusCode: 404,
+ },
+ },
} as const;
export const paramDef = {
@@ -29,47 +37,20 @@ export const paramDef = {
required: ['reportId'],
} as const;
-// TODO: ロジックをサービスに切り出す
-
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.usersRepository)
- private usersRepository: UsersRepository,
-
@Inject(DI.abuseUserReportsRepository)
private abuseUserReportsRepository: AbuseUserReportsRepository,
-
- private queueService: QueueService,
- private instanceActorService: InstanceActorService,
- private apRendererService: ApRendererService,
- private moderationLogService: ModerationLogService,
+ private abuseReportService: AbuseReportService,
) {
super(meta, paramDef, async (ps, me) => {
const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId });
-
- if (report == null) {
- throw new Error('report not found');
+ if (!report) {
+ throw new ApiError(meta.errors.noSuchAbuseReport);
}
- if (ps.forward && report.targetUserHost != null) {
- const actor = await this.instanceActorService.getInstanceActor();
- const targetUser = await this.usersRepository.findOneByOrFail({ id: report.targetUserId });
-
- this.queueService.deliver(actor, this.apRendererService.addContext(this.apRendererService.renderFlag(actor, targetUser.uri!, report.comment)), targetUser.inbox, false);
- }
-
- await this.abuseUserReportsRepository.update(report.id, {
- resolved: true,
- assigneeId: me.id,
- forwarded: ps.forward && report.targetUserHost != null,
- });
-
- this.moderationLogService.log(me, 'resolveAbuseReport', {
- reportId: report.id,
- report: report,
- forwarded: ps.forward && report.targetUserHost != null,
- });
+ await this.abuseReportService.resolve([{ reportId: report.id, forward: ps.forward }], me);
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/update.ts b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
index 5242e0be2f..465ad7aaaf 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
@@ -6,7 +6,6 @@
import { Inject, Injectable } from '@nestjs/common';
import { Endpoint } from '@/server/api/endpoint-base.js';
import type { RolesRepository } from '@/models/_.js';
-import { GlobalEventService } from '@/core/GlobalEventService.js';
import { DI } from '@/di-symbols.js';
import { ApiError } from '@/server/api/error.js';
import { RoleService } from '@/core/RoleService.js';
@@ -50,19 +49,6 @@ export const paramDef = {
},
required: [
'roleId',
- 'name',
- 'description',
- 'color',
- 'iconUrl',
- 'target',
- 'condFormula',
- 'isPublic',
- 'isModerator',
- 'isAdministrator',
- 'asBadge',
- 'canEditMembersByModerator',
- 'displayOrder',
- 'policies',
],
} as const;
diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts
new file mode 100644
index 0000000000..28071e7a33
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/create.ts
@@ -0,0 +1,85 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js';
+import { systemWebhookEventTypes } from '@/models/SystemWebhook.js';
+import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+
+export const meta = {
+ tags: ['admin', 'system-webhook'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:system-webhook',
+
+ res: {
+ type: 'object',
+ ref: 'SystemWebhook',
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ isActive: {
+ type: 'boolean',
+ },
+ name: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 255,
+ },
+ on: {
+ type: 'array',
+ items: {
+ type: 'string',
+ enum: systemWebhookEventTypes,
+ },
+ },
+ url: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 1024,
+ },
+ secret: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 1024,
+ },
+ },
+ required: [
+ 'isActive',
+ 'name',
+ 'on',
+ 'url',
+ 'secret',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private systemWebhookService: SystemWebhookService,
+ private systemWebhookEntityService: SystemWebhookEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const result = await this.systemWebhookService.createSystemWebhook(
+ {
+ isActive: ps.isActive,
+ name: ps.name,
+ on: ps.on,
+ url: ps.url,
+ secret: ps.secret,
+ },
+ me,
+ );
+
+ return this.systemWebhookEntityService.pack(result);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts
new file mode 100644
index 0000000000..9cdfc7e70f
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/delete.ts
@@ -0,0 +1,44 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+
+export const meta = {
+ tags: ['admin', 'system-webhook'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:system-webhook',
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: [
+ 'id',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private systemWebhookService: SystemWebhookService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ await this.systemWebhookService.deleteSystemWebhook(
+ ps.id,
+ me,
+ );
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts
new file mode 100644
index 0000000000..7a440a774e
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/list.ts
@@ -0,0 +1,60 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js';
+import { systemWebhookEventTypes } from '@/models/SystemWebhook.js';
+import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+
+export const meta = {
+ tags: ['admin', 'system-webhook'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:system-webhook',
+
+ res: {
+ type: 'array',
+ items: {
+ type: 'object',
+ ref: 'SystemWebhook',
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ isActive: {
+ type: 'boolean',
+ },
+ on: {
+ type: 'array',
+ items: {
+ type: 'string',
+ enum: systemWebhookEventTypes,
+ },
+ },
+ },
+ required: [],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private systemWebhookService: SystemWebhookService,
+ private systemWebhookEntityService: SystemWebhookEntityService,
+ ) {
+ super(meta, paramDef, async (ps) => {
+ const webhooks = await this.systemWebhookService.fetchSystemWebhooks({
+ isActive: ps.isActive,
+ on: ps.on,
+ });
+ return this.systemWebhookEntityService.packMany(webhooks);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts
new file mode 100644
index 0000000000..75862c96a7
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/show.ts
@@ -0,0 +1,62 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js';
+import { ApiError } from '@/server/api/error.js';
+import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+
+export const meta = {
+ tags: ['admin', 'system-webhook'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:system-webhook',
+
+ res: {
+ type: 'object',
+ ref: 'SystemWebhook',
+ },
+
+ errors: {
+ noSuchSystemWebhook: {
+ message: 'No such SystemWebhook.',
+ code: 'NO_SUCH_SYSTEM_WEBHOOK',
+ id: '38dd1ffe-04b4-6ff5-d8ba-4e6a6ae22c9d',
+ kind: 'server',
+ httpStatusCode: 404,
+ },
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ },
+ required: ['id'],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private systemWebhookService: SystemWebhookService,
+ private systemWebhookEntityService: SystemWebhookEntityService,
+ ) {
+ super(meta, paramDef, async (ps) => {
+ const webhooks = await this.systemWebhookService.fetchSystemWebhooks({ ids: [ps.id] });
+ if (webhooks.length === 0) {
+ throw new ApiError(meta.errors.noSuchSystemWebhook);
+ }
+
+ return this.systemWebhookEntityService.pack(webhooks[0]);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts
new file mode 100644
index 0000000000..8d68bb8f87
--- /dev/null
+++ b/packages/backend/src/server/api/endpoints/admin/system-webhook/update.ts
@@ -0,0 +1,91 @@
+/*
+ * SPDX-FileCopyrightText: syuilo and misskey-project
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+import { Injectable } from '@nestjs/common';
+import { Endpoint } from '@/server/api/endpoint-base.js';
+import { SystemWebhookEntityService } from '@/core/entities/SystemWebhookEntityService.js';
+import { systemWebhookEventTypes } from '@/models/SystemWebhook.js';
+import { SystemWebhookService } from '@/core/SystemWebhookService.js';
+
+export const meta = {
+ tags: ['admin', 'system-webhook'],
+
+ requireCredential: true,
+ requireModerator: true,
+ secure: true,
+ kind: 'write:admin:system-webhook',
+
+ res: {
+ type: 'object',
+ ref: 'SystemWebhook',
+ },
+} as const;
+
+export const paramDef = {
+ type: 'object',
+ properties: {
+ id: {
+ type: 'string',
+ format: 'misskey:id',
+ },
+ isActive: {
+ type: 'boolean',
+ },
+ name: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 255,
+ },
+ on: {
+ type: 'array',
+ items: {
+ type: 'string',
+ enum: systemWebhookEventTypes,
+ },
+ },
+ url: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 1024,
+ },
+ secret: {
+ type: 'string',
+ minLength: 1,
+ maxLength: 1024,
+ },
+ },
+ required: [
+ 'id',
+ 'isActive',
+ 'name',
+ 'on',
+ 'url',
+ 'secret',
+ ],
+} as const;
+
+@Injectable()
+export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
+ constructor(
+ private systemWebhookService: SystemWebhookService,
+ private systemWebhookEntityService: SystemWebhookEntityService,
+ ) {
+ super(meta, paramDef, async (ps, me) => {
+ const result = await this.systemWebhookService.updateSystemWebhook(
+ {
+ id: ps.id,
+ isActive: ps.isActive,
+ name: ps.name,
+ on: ps.on,
+ url: ps.url,
+ secret: ps.secret,
+ },
+ me,
+ );
+
+ return this.systemWebhookEntityService.pack(result);
+ });
+ }
+}
diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
index 015a1e1f7c..6bda1ae6ad 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts
@@ -158,6 +158,13 @@ export const paramDef = {
type: 'string',
},
},
+ mediaSilencedHosts: {
+ type: 'array',
+ nullable: true,
+ items: {
+ type: 'string',
+ },
+ },
summalyProxy: {
type: 'string', nullable: true,
description: '[Deprecated] Use "urlPreviewSummaryProxyUrl" instead.',
@@ -211,6 +218,14 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
return h !== '' && h !== lv && !set.blockedHosts?.includes(h);
});
}
+ if (Array.isArray(ps.mediaSilencedHosts)) {
+ let lastValue = '';
+ set.mediaSilencedHosts = ps.mediaSilencedHosts.sort().filter((h) => {
+ const lv = lastValue;
+ lastValue = h;
+ return h !== '' && h !== lv && !set.blockedHosts?.includes(h);
+ });
+ }
if (ps.themeColor !== undefined) {
set.themeColor = ps.themeColor;
}