mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-11-30 07:53:09 +02:00
improve moderation log
This commit is contained in:
parent
2ad3b1fd74
commit
ed983a5baf
9 changed files with 177 additions and 14 deletions
4
locales/index.d.ts
vendored
4
locales/index.d.ts
vendored
|
@ -2262,6 +2262,10 @@ export interface Locale {
|
||||||
"deleteNote": string;
|
"deleteNote": string;
|
||||||
"createGlobalAnnouncement": string;
|
"createGlobalAnnouncement": string;
|
||||||
"createUserAnnouncement": string;
|
"createUserAnnouncement": string;
|
||||||
|
"updateGlobalAnnouncement": string;
|
||||||
|
"updateUserAnnouncement": string;
|
||||||
|
"deleteGlobalAnnouncement": string;
|
||||||
|
"deleteUserAnnouncement": string;
|
||||||
"resetPassword": string;
|
"resetPassword": string;
|
||||||
"suspendRemoteInstance": string;
|
"suspendRemoteInstance": string;
|
||||||
"unsuspendRemoteInstance": string;
|
"unsuspendRemoteInstance": string;
|
||||||
|
|
|
@ -2175,6 +2175,10 @@ _moderationLogTypes:
|
||||||
deleteNote: "ノートを削除"
|
deleteNote: "ノートを削除"
|
||||||
createGlobalAnnouncement: "全体のお知らせを作成"
|
createGlobalAnnouncement: "全体のお知らせを作成"
|
||||||
createUserAnnouncement: "ユーザーへお知らせを作成"
|
createUserAnnouncement: "ユーザーへお知らせを作成"
|
||||||
|
updateGlobalAnnouncement: "全体のお知らせを更新"
|
||||||
|
updateUserAnnouncement: "ユーザーのお知らせを更新"
|
||||||
|
deleteGlobalAnnouncement: "全体のお知らせを削除"
|
||||||
|
deleteUserAnnouncement: "ユーザーのお知らせを削除"
|
||||||
resetPassword: "パスワードをリセット"
|
resetPassword: "パスワードをリセット"
|
||||||
suspendRemoteInstance: "リモートサーバーを停止"
|
suspendRemoteInstance: "リモートサーバーを停止"
|
||||||
unsuspendRemoteInstance: "リモートサーバーを再開"
|
unsuspendRemoteInstance: "リモートサーバーを再開"
|
||||||
|
|
|
@ -60,7 +60,7 @@ export class AnnouncementService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async create(values: Partial<MiAnnouncement>, moderator: MiUser): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> {
|
public async create(values: Partial<MiAnnouncement>, moderator?: MiUser): Promise<{ raw: MiAnnouncement; packed: Packed<'Announcement'> }> {
|
||||||
const announcement = await this.announcementsRepository.insert({
|
const announcement = await this.announcementsRepository.insert({
|
||||||
id: this.idService.genId(),
|
id: this.idService.genId(),
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
|
@ -82,21 +82,25 @@ export class AnnouncementService {
|
||||||
announcement: packed,
|
announcement: packed,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (moderator) {
|
||||||
this.moderationLogService.log(moderator, 'createUserAnnouncement', {
|
this.moderationLogService.log(moderator, 'createUserAnnouncement', {
|
||||||
announcementId: announcement.id,
|
announcementId: announcement.id,
|
||||||
announcement: announcement,
|
announcement: announcement,
|
||||||
userId: values.userId,
|
userId: values.userId,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.globalEventService.publishBroadcastStream('announcementCreated', {
|
this.globalEventService.publishBroadcastStream('announcementCreated', {
|
||||||
announcement: packed,
|
announcement: packed,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (moderator) {
|
||||||
this.moderationLogService.log(moderator, 'createGlobalAnnouncement', {
|
this.moderationLogService.log(moderator, 'createGlobalAnnouncement', {
|
||||||
announcementId: announcement.id,
|
announcementId: announcement.id,
|
||||||
announcement: announcement,
|
announcement: announcement,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
raw: announcement,
|
raw: announcement,
|
||||||
|
@ -104,6 +108,59 @@ export class AnnouncementService {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public async update(announcement: MiAnnouncement, values: Partial<MiAnnouncement>, moderator?: MiUser): Promise<void> {
|
||||||
|
await this.announcementsRepository.update(announcement.id, {
|
||||||
|
updatedAt: new Date(),
|
||||||
|
title: values.title,
|
||||||
|
text: values.text,
|
||||||
|
/* eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing -- 空の文字列の場合、nullを渡すようにするため */
|
||||||
|
imageUrl: values.imageUrl || null,
|
||||||
|
display: values.display,
|
||||||
|
icon: values.icon,
|
||||||
|
forExistingUsers: values.forExistingUsers,
|
||||||
|
needConfirmationToRead: values.needConfirmationToRead,
|
||||||
|
isActive: values.isActive,
|
||||||
|
});
|
||||||
|
|
||||||
|
const after = await this.announcementsRepository.findOneByOrFail({ id: announcement.id });
|
||||||
|
|
||||||
|
if (moderator) {
|
||||||
|
if (announcement.userId) {
|
||||||
|
this.moderationLogService.log(moderator, 'updateUserAnnouncement', {
|
||||||
|
announcementId: announcement.id,
|
||||||
|
before: announcement,
|
||||||
|
after: after,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.moderationLogService.log(moderator, 'updateGlobalAnnouncement', {
|
||||||
|
announcementId: announcement.id,
|
||||||
|
before: announcement,
|
||||||
|
after: after,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@bindThis
|
||||||
|
public async delete(announcement: MiAnnouncement, moderator?: MiUser): Promise<void> {
|
||||||
|
await this.announcementsRepository.delete(announcement.id);
|
||||||
|
|
||||||
|
if (moderator) {
|
||||||
|
if (announcement.userId) {
|
||||||
|
this.moderationLogService.log(moderator, 'deleteUserAnnouncement', {
|
||||||
|
announcementId: announcement.id,
|
||||||
|
announcement: announcement,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.moderationLogService.log(moderator, 'deleteGlobalAnnouncement', {
|
||||||
|
announcementId: announcement.id,
|
||||||
|
announcement: announcement,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@bindThis
|
@bindThis
|
||||||
public async read(user: MiUser, announcementId: MiAnnouncement['id']): Promise<void> {
|
public async read(user: MiUser, announcementId: MiAnnouncement['id']): Promise<void> {
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { AnnouncementsRepository } from '@/models/_.js';
|
import type { AnnouncementsRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { AnnouncementService } from '@/core/AnnouncementService.js';
|
||||||
import { ApiError } from '../../../error.js';
|
import { ApiError } from '../../../error.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -37,13 +38,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.announcementsRepository)
|
@Inject(DI.announcementsRepository)
|
||||||
private announcementsRepository: AnnouncementsRepository,
|
private announcementsRepository: AnnouncementsRepository,
|
||||||
|
|
||||||
|
private announcementService: AnnouncementService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
|
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
|
||||||
|
|
||||||
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
|
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
|
||||||
|
|
||||||
await this.announcementsRepository.delete(announcement.id);
|
await this.announcementService.delete(announcement, me);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { Endpoint } from '@/server/api/endpoint-base.js';
|
import { Endpoint } from '@/server/api/endpoint-base.js';
|
||||||
import type { AnnouncementsRepository } from '@/models/_.js';
|
import type { AnnouncementsRepository } from '@/models/_.js';
|
||||||
import { DI } from '@/di-symbols.js';
|
import { DI } from '@/di-symbols.js';
|
||||||
|
import { AnnouncementService } from '@/core/AnnouncementService.js';
|
||||||
import { ApiError } from '../../../error.js';
|
import { ApiError } from '../../../error.js';
|
||||||
|
|
||||||
export const meta = {
|
export const meta = {
|
||||||
|
@ -45,13 +46,15 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
constructor(
|
constructor(
|
||||||
@Inject(DI.announcementsRepository)
|
@Inject(DI.announcementsRepository)
|
||||||
private announcementsRepository: AnnouncementsRepository,
|
private announcementsRepository: AnnouncementsRepository,
|
||||||
|
|
||||||
|
private announcementService: AnnouncementService,
|
||||||
) {
|
) {
|
||||||
super(meta, paramDef, async (ps, me) => {
|
super(meta, paramDef, async (ps, me) => {
|
||||||
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
|
const announcement = await this.announcementsRepository.findOneBy({ id: ps.id });
|
||||||
|
|
||||||
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
|
if (announcement == null) throw new ApiError(meta.errors.noSuchAnnouncement);
|
||||||
|
|
||||||
await this.announcementsRepository.update(announcement.id, {
|
await this.announcementService.update(announcement, {
|
||||||
updatedAt: new Date(),
|
updatedAt: new Date(),
|
||||||
title: ps.title,
|
title: ps.title,
|
||||||
text: ps.text,
|
text: ps.text,
|
||||||
|
@ -62,7 +65,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
forExistingUsers: ps.forExistingUsers,
|
forExistingUsers: ps.forExistingUsers,
|
||||||
needConfirmationToRead: ps.needConfirmationToRead,
|
needConfirmationToRead: ps.needConfirmationToRead,
|
||||||
isActive: ps.isActive,
|
isActive: ps.isActive,
|
||||||
});
|
}, me);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,10 @@ export const moderationLogTypes = [
|
||||||
'deleteNote',
|
'deleteNote',
|
||||||
'createGlobalAnnouncement',
|
'createGlobalAnnouncement',
|
||||||
'createUserAnnouncement',
|
'createUserAnnouncement',
|
||||||
|
'updateGlobalAnnouncement',
|
||||||
|
'updateUserAnnouncement',
|
||||||
|
'deleteGlobalAnnouncement',
|
||||||
|
'deleteUserAnnouncement',
|
||||||
'resetPassword',
|
'resetPassword',
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
|
@ -107,6 +111,24 @@ export type ModerationLogPayloads = {
|
||||||
announcement: any;
|
announcement: any;
|
||||||
userId: string;
|
userId: string;
|
||||||
};
|
};
|
||||||
|
updateGlobalAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
before: any;
|
||||||
|
after: any;
|
||||||
|
};
|
||||||
|
updateUserAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
before: any;
|
||||||
|
after: any;
|
||||||
|
};
|
||||||
|
deleteGlobalAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
announcement: any;
|
||||||
|
};
|
||||||
|
deleteUserAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
announcement: any;
|
||||||
|
};
|
||||||
resetPassword: {
|
resetPassword: {
|
||||||
targetId: string;
|
targetId: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -2556,6 +2556,30 @@ type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'promoteQueue';
|
type: 'promoteQueue';
|
||||||
info: ModerationLogPayloads['promoteQueue'];
|
info: ModerationLogPayloads['promoteQueue'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteDriveFile';
|
||||||
|
info: ModerationLogPayloads['deleteDriveFile'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteNote';
|
||||||
|
info: ModerationLogPayloads['deleteNote'];
|
||||||
|
} | {
|
||||||
|
type: 'createGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['createGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'createUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['createUserAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'updateGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['updateGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'updateUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['updateUserAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['deleteGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['deleteUserAnnouncement'];
|
||||||
} | {
|
} | {
|
||||||
type: 'resetPassword';
|
type: 'resetPassword';
|
||||||
info: ModerationLogPayloads['resetPassword'];
|
info: ModerationLogPayloads['resetPassword'];
|
||||||
|
@ -2568,7 +2592,7 @@ type ModerationLog = {
|
||||||
});
|
});
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "assignRole", "unassignRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance"];
|
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "assignRole", "unassignRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance"];
|
||||||
|
|
||||||
// @public (undocumented)
|
// @public (undocumented)
|
||||||
export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"];
|
export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"];
|
||||||
|
|
|
@ -61,6 +61,10 @@ export const moderationLogTypes = [
|
||||||
'deleteNote',
|
'deleteNote',
|
||||||
'createGlobalAnnouncement',
|
'createGlobalAnnouncement',
|
||||||
'createUserAnnouncement',
|
'createUserAnnouncement',
|
||||||
|
'updateGlobalAnnouncement',
|
||||||
|
'updateUserAnnouncement',
|
||||||
|
'deleteGlobalAnnouncement',
|
||||||
|
'deleteUserAnnouncement',
|
||||||
'resetPassword',
|
'resetPassword',
|
||||||
'suspendRemoteInstance',
|
'suspendRemoteInstance',
|
||||||
'unsuspendRemoteInstance',
|
'unsuspendRemoteInstance',
|
||||||
|
@ -125,6 +129,24 @@ export type ModerationLogPayloads = {
|
||||||
announcement: any;
|
announcement: any;
|
||||||
userId: string;
|
userId: string;
|
||||||
};
|
};
|
||||||
|
updateGlobalAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
before: any;
|
||||||
|
after: any;
|
||||||
|
};
|
||||||
|
updateUserAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
before: any;
|
||||||
|
after: any;
|
||||||
|
};
|
||||||
|
deleteGlobalAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
announcement: any;
|
||||||
|
};
|
||||||
|
deleteUserAnnouncement: {
|
||||||
|
announcementId: string;
|
||||||
|
announcement: any;
|
||||||
|
};
|
||||||
resetPassword: {
|
resetPassword: {
|
||||||
targetId: string;
|
targetId: string;
|
||||||
};
|
};
|
||||||
|
|
|
@ -607,6 +607,30 @@ export type ModerationLog = {
|
||||||
} | {
|
} | {
|
||||||
type: 'promoteQueue';
|
type: 'promoteQueue';
|
||||||
info: ModerationLogPayloads['promoteQueue'];
|
info: ModerationLogPayloads['promoteQueue'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteDriveFile';
|
||||||
|
info: ModerationLogPayloads['deleteDriveFile'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteNote';
|
||||||
|
info: ModerationLogPayloads['deleteNote'];
|
||||||
|
} | {
|
||||||
|
type: 'createGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['createGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'createUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['createUserAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'updateGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['updateGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'updateUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['updateUserAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteGlobalAnnouncement';
|
||||||
|
info: ModerationLogPayloads['deleteGlobalAnnouncement'];
|
||||||
|
} | {
|
||||||
|
type: 'deleteUserAnnouncement';
|
||||||
|
info: ModerationLogPayloads['deleteUserAnnouncement'];
|
||||||
} | {
|
} | {
|
||||||
type: 'resetPassword';
|
type: 'resetPassword';
|
||||||
info: ModerationLogPayloads['resetPassword'];
|
info: ModerationLogPayloads['resetPassword'];
|
||||||
|
|
Loading…
Reference in a new issue