summaryrefslogtreecommitdiff
path: root/packages
diff options
context:
space:
mode:
authorsyuilo <Syuilotan@yahoo.co.jp>2023-09-25 17:12:28 +0900
committerGitHub <noreply@github.com>2023-09-25 17:12:28 +0900
commite57b5367672f08c022027fef29d451afadc4e512 (patch)
tree907e17c00b89000f97316eff170a1357a7613cf7 /packages
parentMerge pull request #11874 from misskey-dev/develop (diff)
parentbuild(deps): bump actions/checkout from 4.0.0 to 4.1.0 (#11900) (diff)
downloadmisskey-e57b5367672f08c022027fef29d451afadc4e512.tar.gz
misskey-e57b5367672f08c022027fef29d451afadc4e512.tar.bz2
misskey-e57b5367672f08c022027fef29d451afadc4e512.zip
Merge pull request #11898 from misskey-dev/develop
2023.9.1
Diffstat (limited to 'packages')
-rw-r--r--packages/backend/migration/1695605508898-mutingNotificationTypes.js21
-rw-r--r--packages/backend/src/core/AnnouncementService.ts12
-rw-r--r--packages/backend/src/core/CustomEmojiService.ts7
-rw-r--r--packages/backend/src/core/DriveService.ts8
-rw-r--r--packages/backend/src/core/NoteDeleteService.ts3
-rw-r--r--packages/backend/src/core/RoleService.ts46
-rw-r--r--packages/backend/src/server/api/endpoints/admin/reset-password.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/resolve-abuse-user-report.ts8
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/create.ts35
-rw-r--r--packages/backend/src/server/api/endpoints/admin/roles/update.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/admin/suspend-user.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts4
-rw-r--r--packages/backend/src/server/api/endpoints/admin/update-user-note.ts2
-rw-r--r--packages/backend/src/server/api/endpoints/announcements.ts2
-rw-r--r--packages/backend/src/types.ts42
-rw-r--r--packages/frontend/src/pages/admin/modlog.ModLog.vue53
-rw-r--r--packages/frontend/src/scripts/get-note-menu.ts4
-rw-r--r--packages/misskey-js/etc/misskey-js.api.md5
-rw-r--r--packages/misskey-js/src/consts.ts42
-rw-r--r--packages/misskey-js/src/entities.ts3
20 files changed, 248 insertions, 59 deletions
diff --git a/packages/backend/migration/1695605508898-mutingNotificationTypes.js b/packages/backend/migration/1695605508898-mutingNotificationTypes.js
new file mode 100644
index 0000000000..8c0e52a2f0
--- /dev/null
+++ b/packages/backend/migration/1695605508898-mutingNotificationTypes.js
@@ -0,0 +1,21 @@
+export class MutingNotificationTypes1695605508898 {
+ name = 'MutingNotificationTypes1695605508898'
+
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum" RENAME TO "user_profile_mutingnotificationtypes_enum_old"`);
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum" AS ENUM('note', 'follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'achievementEarned', 'app', 'test', 'pollVote', 'groupInvited')`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum"[]`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum_old"`);
+ }
+
+ async down(queryRunner) {
+ await queryRunner.query(`CREATE TYPE "public"."user_profile_mutingnotificationtypes_enum_old" AS ENUM('follow', 'mention', 'reply', 'renote', 'quote', 'reaction', 'pollVote', 'pollEnded', 'receiveFollowRequest', 'followRequestAccepted', 'groupInvited', 'achievementEarned', 'app')`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" DROP DEFAULT`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" TYPE "public"."user_profile_mutingnotificationtypes_enum_old"[] USING "mutingNotificationTypes"::"text"::"public"."user_profile_mutingnotificationtypes_enum_old"[]`);
+ await queryRunner.query(`ALTER TABLE "user_profile" ALTER COLUMN "mutingNotificationTypes" SET DEFAULT '{}'`);
+ await queryRunner.query(`DROP TYPE "public"."user_profile_mutingnotificationtypes_enum"`);
+ await queryRunner.query(`ALTER TYPE "public"."user_profile_mutingnotificationtypes_enum_old" RENAME TO "user_profile_mutingnotificationtypes_enum"`);
+ }
+}
diff --git a/packages/backend/src/core/AnnouncementService.ts b/packages/backend/src/core/AnnouncementService.ts
index 2b4877788a..ddacc0936f 100644
--- a/packages/backend/src/core/AnnouncementService.ts
+++ b/packages/backend/src/core/AnnouncementService.ts
@@ -7,7 +7,7 @@ import { Inject, Injectable } from '@nestjs/common';
import { Brackets } from 'typeorm';
import { DI } from '@/di-symbols.js';
import type { MiUser } from '@/models/User.js';
-import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, MiAnnouncementRead } from '@/models/_.js';
+import type { AnnouncementReadsRepository, AnnouncementsRepository, MiAnnouncement, MiAnnouncementRead, UsersRepository } from '@/models/_.js';
import { bindThis } from '@/decorators.js';
import { Packed } from '@/misc/json-schema.js';
import { IdService } from '@/core/IdService.js';
@@ -23,6 +23,9 @@ export class AnnouncementService {
@Inject(DI.announcementReadsRepository)
private announcementReadsRepository: AnnouncementReadsRepository,
+ @Inject(DI.usersRepository)
+ private usersRepository: UsersRepository,
+
private idService: IdService,
private globalEventService: GlobalEventService,
private moderationLogService: ModerationLogService,
@@ -83,10 +86,13 @@ export class AnnouncementService {
});
if (moderator) {
+ const user = await this.usersRepository.findOneByOrFail({ id: values.userId });
this.moderationLogService.log(moderator, 'createUserAnnouncement', {
announcementId: announcement.id,
announcement: announcement,
userId: values.userId,
+ userUsername: user.username,
+ userHost: user.host,
});
}
} else {
@@ -127,10 +133,14 @@ export class AnnouncementService {
if (moderator) {
if (announcement.userId) {
+ const user = await this.usersRepository.findOneByOrFail({ id: announcement.userId });
this.moderationLogService.log(moderator, 'updateUserAnnouncement', {
announcementId: announcement.id,
before: announcement,
after: after,
+ userId: announcement.userId,
+ userUsername: user.username,
+ userHost: user.host,
});
} else {
this.moderationLogService.log(moderator, 'updateGlobalAnnouncement', {
diff --git a/packages/backend/src/core/CustomEmojiService.ts b/packages/backend/src/core/CustomEmojiService.ts
index b14a8666e6..1b545a124e 100644
--- a/packages/backend/src/core/CustomEmojiService.ts
+++ b/packages/backend/src/core/CustomEmojiService.ts
@@ -134,11 +134,11 @@ export class CustomEmojiService implements OnApplicationShutdown {
this.localEmojisCache.refresh();
- const updated = await this.emojiEntityService.packDetailed(emoji.id);
+ const packed = await this.emojiEntityService.packDetailed(emoji.id);
if (emoji.name === data.name) {
this.globalEventService.publishBroadcastStream('emojiUpdated', {
- emojis: [updated],
+ emojis: [packed],
});
} else {
this.globalEventService.publishBroadcastStream('emojiDeleted', {
@@ -146,11 +146,12 @@ export class CustomEmojiService implements OnApplicationShutdown {
});
this.globalEventService.publishBroadcastStream('emojiAdded', {
- emoji: updated,
+ emoji: packed,
});
}
if (moderator) {
+ const updated = await this.emojisRepository.findOneByOrFail({ id: id });
this.moderationLogService.log(moderator, 'updateCustomEmoji', {
emojiId: emoji.id,
before: emoji,
diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts
index 366205f586..cecbec9638 100644
--- a/packages/backend/src/core/DriveService.ts
+++ b/packages/backend/src/core/DriveService.ts
@@ -686,15 +686,20 @@ export class DriveService {
if (await this.roleService.isModerator(updater) && (file.userId !== updater.id)) {
if (values.isSensitive !== undefined && values.isSensitive !== file.isSensitive) {
+ const user = file.userId ? await this.usersRepository.findOneByOrFail({ id: file.userId }) : null;
if (values.isSensitive) {
this.moderationLogService.log(updater, 'markSensitiveDriveFile', {
fileId: file.id,
fileUserId: file.userId,
+ fileUserUsername: user?.username ?? null,
+ fileUserHost: user?.host ?? null,
});
} else {
this.moderationLogService.log(updater, 'unmarkSensitiveDriveFile', {
fileId: file.id,
fileUserId: file.userId,
+ fileUserUsername: user?.username ?? null,
+ fileUserHost: user?.host ?? null,
});
}
}
@@ -795,9 +800,12 @@ export class DriveService {
}
if (deleter && await this.roleService.isModerator(deleter) && (file.userId !== deleter.id)) {
+ const user = file.userId ? await this.usersRepository.findOneByOrFail({ id: file.userId }) : null;
this.moderationLogService.log(deleter, 'deleteDriveFile', {
fileId: file.id,
fileUserId: file.userId,
+ fileUserUsername: user?.username ?? null,
+ fileUserHost: user?.host ?? null,
});
}
}
diff --git a/packages/backend/src/core/NoteDeleteService.ts b/packages/backend/src/core/NoteDeleteService.ts
index c99f92b9cb..87979f22ac 100644
--- a/packages/backend/src/core/NoteDeleteService.ts
+++ b/packages/backend/src/core/NoteDeleteService.ts
@@ -135,9 +135,12 @@ export class NoteDeleteService {
});
if (deleter && (note.userId !== deleter.id)) {
+ const user = await this.usersRepository.findOneByOrFail({ id: note.userId });
this.moderationLogService.log(deleter, 'deleteNote', {
noteId: note.id,
noteUserId: note.userId,
+ noteUserUsername: user.username,
+ noteUserHost: user.host,
note: note,
});
}
diff --git a/packages/backend/src/core/RoleService.ts b/packages/backend/src/core/RoleService.ts
index dea6dc68cd..934b7d676b 100644
--- a/packages/backend/src/core/RoleService.ts
+++ b/packages/backend/src/core/RoleService.ts
@@ -412,10 +412,13 @@ export class RoleService implements OnApplicationShutdown {
this.globalEventService.publishInternalEvent('userRoleAssigned', created);
if (moderator) {
+ const user = await this.usersRepository.findOneByOrFail({ id: userId });
this.moderationLogService.log(moderator, 'assignRole', {
roleId: roleId,
roleName: role.name,
userId: userId,
+ userUsername: user.username,
+ userHost: user.host,
expiresAt: expiresAt ? expiresAt.toISOString() : null,
});
}
@@ -445,11 +448,16 @@ export class RoleService implements OnApplicationShutdown {
this.globalEventService.publishInternalEvent('userRoleUnassigned', existing);
if (moderator) {
- const role = await this.rolesRepository.findOneByOrFail({ id: roleId });
+ const [user, role] = await Promise.all([
+ this.usersRepository.findOneByOrFail({ id: userId }),
+ this.rolesRepository.findOneByOrFail({ id: roleId }),
+ ]);
this.moderationLogService.log(moderator, 'unassignRole', {
roleId: roleId,
roleName: role.name,
userId: userId,
+ userUsername: user.username,
+ userHost: user.host,
});
}
}
@@ -474,6 +482,42 @@ export class RoleService implements OnApplicationShutdown {
}
@bindThis
+ public async create(values: Partial<MiRole>, moderator?: MiUser): Promise<MiRole> {
+ const date = new Date();
+ const created = await this.rolesRepository.insert({
+ id: this.idService.genId(),
+ createdAt: date,
+ updatedAt: date,
+ lastUsedAt: date,
+ name: values.name,
+ description: values.description,
+ color: values.color,
+ iconUrl: values.iconUrl,
+ target: values.target,
+ condFormula: values.condFormula,
+ isPublic: values.isPublic,
+ isAdministrator: values.isAdministrator,
+ isModerator: values.isModerator,
+ isExplorable: values.isExplorable,
+ asBadge: values.asBadge,
+ canEditMembersByModerator: values.canEditMembersByModerator,
+ displayOrder: values.displayOrder,
+ policies: values.policies,
+ }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0]));
+
+ this.globalEventService.publishInternalEvent('roleCreated', created);
+
+ if (moderator) {
+ this.moderationLogService.log(moderator, 'createRole', {
+ roleId: created.id,
+ role: created,
+ });
+ }
+
+ return created;
+ }
+
+ @bindThis
public async update(role: MiRole, params: Partial<MiRole>, moderator?: MiUser): Promise<void> {
const date = new Date();
await this.rolesRepository.update(role.id, {
diff --git a/packages/backend/src/server/api/endpoints/admin/reset-password.ts b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
index 6ce7583276..13e9c30ed8 100644
--- a/packages/backend/src/server/api/endpoints/admin/reset-password.ts
+++ b/packages/backend/src/server/api/endpoints/admin/reset-password.ts
@@ -73,7 +73,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
this.moderationLogService.log(me, 'resetPassword', {
- targetId: user.id,
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
});
return {
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 8667640a67..fb5ac7a335 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
@@ -10,6 +10,7 @@ import { InstanceActorService } from '@/core/InstanceActorService.js';
import { QueueService } from '@/core/QueueService.js';
import { ApRendererService } from '@/core/activitypub/ApRendererService.js';
import { DI } from '@/di-symbols.js';
+import { ModerationLogService } from '@/core/ModerationLogService.js';
export const meta = {
tags: ['admin'],
@@ -41,6 +42,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
private queueService: QueueService,
private instanceActorService: InstanceActorService,
private apRendererService: ApRendererService,
+ private moderationLogService: ModerationLogService,
) {
super(meta, paramDef, async (ps, me) => {
const report = await this.abuseUserReportsRepository.findOneBy({ id: ps.reportId });
@@ -61,6 +63,12 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
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,
+ });
});
}
}
diff --git a/packages/backend/src/server/api/endpoints/admin/roles/create.ts b/packages/backend/src/server/api/endpoints/admin/roles/create.ts
index f567b0d387..8451b1955f 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/create.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/create.ts
@@ -5,11 +5,8 @@
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 { IdService } from '@/core/IdService.js';
import { RoleEntityService } from '@/core/entities/RoleEntityService.js';
+import { RoleService } from '@/core/RoleService.js';
export const meta = {
tags: ['admin', 'role'],
@@ -58,37 +55,11 @@ export const paramDef = {
@Injectable()
export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-disable-line import/no-default-export
constructor(
- @Inject(DI.rolesRepository)
- private rolesRepository: RolesRepository,
-
- private globalEventService: GlobalEventService,
- private idService: IdService,
private roleEntityService: RoleEntityService,
+ private roleService: RoleService,
) {
super(meta, paramDef, async (ps, me) => {
- const date = new Date();
- const created = await this.rolesRepository.insert({
- id: this.idService.genId(),
- createdAt: date,
- updatedAt: date,
- lastUsedAt: date,
- name: ps.name,
- description: ps.description,
- color: ps.color,
- iconUrl: ps.iconUrl,
- target: ps.target,
- condFormula: ps.condFormula,
- isPublic: ps.isPublic,
- isAdministrator: ps.isAdministrator,
- isModerator: ps.isModerator,
- isExplorable: ps.isExplorable,
- asBadge: ps.asBadge,
- canEditMembersByModerator: ps.canEditMembersByModerator,
- displayOrder: ps.displayOrder,
- policies: ps.policies,
- }).then(x => this.rolesRepository.findOneByOrFail(x.identifiers[0]));
-
- this.globalEventService.publishInternalEvent('roleCreated', created);
+ const created = await this.roleService.create(ps, me);
return await this.roleEntityService.pack(created, 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 e4e59e487c..6031e2363e 100644
--- a/packages/backend/src/server/api/endpoints/admin/roles/update.ts
+++ b/packages/backend/src/server/api/endpoints/admin/roles/update.ts
@@ -79,9 +79,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
throw new ApiError(meta.errors.noSuchRole);
}
- const date = new Date();
await this.roleService.update(role, {
- updatedAt: date,
name: ps.name,
description: ps.description,
color: ps.color,
diff --git a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
index 89199f8bff..9464f4b677 100644
--- a/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/suspend-user.ts
@@ -61,7 +61,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
this.moderationLogService.log(me, 'suspend', {
- targetId: user.id,
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
});
(async () => {
diff --git a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
index a2779148ed..5e523bbc31 100644
--- a/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
+++ b/packages/backend/src/server/api/endpoints/admin/unsuspend-user.ts
@@ -46,7 +46,9 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
});
this.moderationLogService.log(me, 'unsuspend', {
- targetId: user.id,
+ userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
});
this.userSuspendService.doPostUnsuspend(user);
diff --git a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
index 2e9fd5ad29..bfccc2a2a5 100644
--- a/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
+++ b/packages/backend/src/server/api/endpoints/admin/update-user-note.ts
@@ -51,6 +51,8 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
this.moderationLogService.log(me, 'updateUserNote', {
userId: user.id,
+ userUsername: user.username,
+ userHost: user.host,
before: currentProfile.moderationNote,
after: ps.text,
});
diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts
index 498afe3448..7c242dbcd5 100644
--- a/packages/backend/src/server/api/endpoints/announcements.ts
+++ b/packages/backend/src/server/api/endpoints/announcements.ts
@@ -52,7 +52,7 @@ 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)
- .where('announcement.isActive = :isActive', { isActive: ps.isActive })
+ .andWhere('announcement.isActive = :isActive', { isActive: ps.isActive })
.andWhere(new Brackets(qb => {
if (me) qb.orWhere('announcement.userId = :meId', { meId: me.id });
qb.orWhere('announcement.userId IS NULL');
diff --git a/packages/backend/src/types.ts b/packages/backend/src/types.ts
index 16654edd88..35ea710f9e 100644
--- a/packages/backend/src/types.ts
+++ b/packages/backend/src/types.ts
@@ -37,6 +37,7 @@ export const moderationLogTypes = [
'deleteCustomEmoji',
'assignRole',
'unassignRole',
+ 'createRole',
'updateRole',
'deleteRole',
'clearQueue',
@@ -54,6 +55,7 @@ export const moderationLogTypes = [
'unsuspendRemoteInstance',
'markSensitiveDriveFile',
'unmarkSensitiveDriveFile',
+ 'resolveAbuseReport',
] as const;
export type ModerationLogPayloads = {
@@ -62,13 +64,19 @@ export type ModerationLogPayloads = {
after: any | null;
};
suspend: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
unsuspend: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
updateUserNote: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
before: string | null;
after: string | null;
};
@@ -87,15 +95,23 @@ export type ModerationLogPayloads = {
};
assignRole: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
roleId: string;
roleName: string;
expiresAt: string | null;
};
unassignRole: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
roleId: string;
roleName: string;
};
+ createRole: {
+ roleId: string;
+ role: any;
+ };
updateRole: {
roleId: string;
before: any;
@@ -110,10 +126,14 @@ export type ModerationLogPayloads = {
deleteDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
};
deleteNote: {
noteId: string;
noteUserId: string;
+ noteUserUsername: string;
+ noteUserHost: string | null;
note: any;
};
createGlobalAnnouncement: {
@@ -124,6 +144,8 @@ export type ModerationLogPayloads = {
announcementId: string;
announcement: any;
userId: string;
+ userUsername: string;
+ userHost: string | null;
};
updateGlobalAnnouncement: {
announcementId: string;
@@ -134,6 +156,9 @@ export type ModerationLogPayloads = {
announcementId: string;
before: any;
after: any;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
deleteGlobalAnnouncement: {
announcementId: string;
@@ -144,7 +169,9 @@ export type ModerationLogPayloads = {
announcement: any;
};
resetPassword: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
suspendRemoteInstance: {
id: string;
@@ -157,9 +184,18 @@ export type ModerationLogPayloads = {
markSensitiveDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
};
unmarkSensitiveDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
+ };
+ resolveAbuseReport: {
+ reportId: string;
+ report: any;
+ forwarded: boolean;
};
};
diff --git a/packages/frontend/src/pages/admin/modlog.ModLog.vue b/packages/frontend/src/pages/admin/modlog.ModLog.vue
index ce7b89f8f7..14f94479f1 100644
--- a/packages/frontend/src/pages/admin/modlog.ModLog.vue
+++ b/packages/frontend/src/pages/admin/modlog.ModLog.vue
@@ -5,33 +5,61 @@ SPDX-License-Identifier: AGPL-3.0-only
<template>
<MkFolder>
- <template #label>{{ i18n.ts._moderationLogTypes[log.type] }}</template>
+ <template #label>
+ <b>{{ i18n.ts._moderationLogTypes[log.type] }}</b>
+ <span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'unsuspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'resetPassword'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'assignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'unassignRole'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'createRole'">: {{ log.info.role.name }}</span>
+ <span v-else-if="log.type === 'updateRole'">: {{ log.info.before.name }}</span>
+ <span v-else-if="log.type === 'deleteRole'">: {{ log.info.role.name }}</span>
+ <span v-else-if="log.type === 'updateCustomEmoji'">: {{ log.info.before.name }}</span>
+ <span v-else-if="log.type === 'markSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span>
+ <span v-else-if="log.type === 'unmarkSensitiveDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span>
+ <span v-else-if="log.type === 'suspendRemoteInstance'">: {{ log.info.host }}</span>
+ <span v-else-if="log.type === 'unsuspendRemoteInstance'">: {{ log.info.host }}</span>
+ <span v-else-if="log.type === 'createUserAnnouncement'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'updateUserAnnouncement'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
+ <span v-else-if="log.type === 'deleteNote'">: @{{ log.info.noteUserUsername }}{{ log.info.noteUserHost ? '@' + log.info.noteUserHost : '' }}</span>
+ <span v-else-if="log.type === 'deleteDriveFile'">: @{{ log.info.fileUserUsername }}{{ log.info.fileUserHost ? '@' + log.info.fileUserHost : '' }}</span>
+ </template>
<template #icon>
<MkAvatar :user="log.user" :class="$style.avatar"/>
</template>
<template #suffix>
- <MkTime :time="log.createdAt" mode="detail"/>
+ <MkTime :time="log.createdAt"/>
</template>
<div :class="$style.root">
- <div>{{ i18n.ts.moderator }}: {{ log.userId }}</div>
+ <div style="display: flex; gap: var(--margin); flex-wrap: wrap;">
+ <div style="flex: 1;">{{ i18n.ts.moderator }}: <MkA :to="`/admin/user/${log.userId}`" class="_link">@{{ log.user?.username }}</MkA></div>
+ <div style="flex: 1;">{{ i18n.ts.dateAndTime }}: <MkTime :time="log.createdAt" mode="detail"/></div>
+ </div>
<template v-if="log.type === 'updateServerSettings'">
<div :class="$style.diff">
- <CodeDiff :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
+ <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
</div>
</template>
<template v-else-if="log.type === 'updateUserNote'">
<div>{{ i18n.ts.user }}: {{ log.info.userId }}</div>
<div :class="$style.diff">
- <CodeDiff :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
+ <CodeDiff :context="5" :hideHeader="true" :oldString="log.info.before ?? ''" :newString="log.info.after ?? ''" maxHeight="300px"/>
</div>
</template>
<template v-else-if="log.type === 'suspend'">
- <div>{{ i18n.ts.user }}: {{ log.info.targetId }}</div>
+ <div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
</template>
<template v-else-if="log.type === 'unsuspend'">
- <div>{{ i18n.ts.user }}: {{ log.info.targetId }}</div>
+ <div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
+ </template>
+ <template v-else-if="log.type === 'updateRole'">
+ <div :class="$style.diff">
+ <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
+ </div>
</template>
<template v-else-if="log.type === 'assignRole'">
<div>{{ i18n.ts.user }}: {{ log.info.userId }}</div>
@@ -41,6 +69,17 @@ SPDX-License-Identifier: AGPL-3.0-only
<div>{{ i18n.ts.user }}: {{ log.info.userId }}</div>
<div>{{ i18n.ts.role }}: {{ log.info.roleName }} [{{ log.info.roleId }}]</div>
</template>
+ <template v-else-if="log.type === 'updateCustomEmoji'">
+ <div>{{ i18n.ts.emoji }}: {{ log.info.emojiId }}</div>
+ <div :class="$style.diff">
+ <CodeDiff :context="5" :hideHeader="true" :oldString="JSON5.stringify(log.info.before, null, '\t')" :newString="JSON5.stringify(log.info.after, null, '\t')" language="javascript" maxHeight="300px"/>
+ </div>
+ </template>
+
+ <details>
+ <summary>raw</summary>
+ <pre>{{ JSON5.stringify(log, null, '\t') }}</pre>
+ </details>
</div>
</MkFolder>
</template>
diff --git a/packages/frontend/src/scripts/get-note-menu.ts b/packages/frontend/src/scripts/get-note-menu.ts
index 734a632039..0948741fc5 100644
--- a/packages/frontend/src/scripts/get-note-menu.ts
+++ b/packages/frontend/src/scripts/get-note-menu.ts
@@ -368,8 +368,8 @@ export function getNoteMenu(props: {
.filter(x => x !== undefined);
} else {
menu = [{
- icon: 'ti ti-external-link',
- text: i18n.ts.detailed,
+ icon: 'ti ti-info-circle',
+ text: i18n.ts.details,
action: openDetail,
}, {
icon: 'ti ti-copy',
diff --git a/packages/misskey-js/etc/misskey-js.api.md b/packages/misskey-js/etc/misskey-js.api.md
index b3806754a8..0686354ff4 100644
--- a/packages/misskey-js/etc/misskey-js.api.md
+++ b/packages/misskey-js/etc/misskey-js.api.md
@@ -2551,6 +2551,9 @@ type ModerationLog = {
type: 'unassignRole';
info: ModerationLogPayloads['unassignRole'];
} | {
+ type: 'createRole';
+ info: ModerationLogPayloads['createRole'];
+} | {
type: 'updateRole';
info: ModerationLogPayloads['updateRole'];
} | {
@@ -2604,7 +2607,7 @@ type ModerationLog = {
});
// @public (undocumented)
-export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile"];
+export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "suspendRemoteInstance", "unsuspendRemoteInstance", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport"];
// @public (undocumented)
export const mutedNoteReasons: readonly ["word", "manual", "spam", "other"];
diff --git a/packages/misskey-js/src/consts.ts b/packages/misskey-js/src/consts.ts
index 63137dcc83..aedfb5570e 100644
--- a/packages/misskey-js/src/consts.ts
+++ b/packages/misskey-js/src/consts.ts
@@ -55,6 +55,7 @@ export const moderationLogTypes = [
'deleteCustomEmoji',
'assignRole',
'unassignRole',
+ 'createRole',
'updateRole',
'deleteRole',
'clearQueue',
@@ -72,6 +73,7 @@ export const moderationLogTypes = [
'unsuspendRemoteInstance',
'markSensitiveDriveFile',
'unmarkSensitiveDriveFile',
+ 'resolveAbuseReport',
] as const;
export type ModerationLogPayloads = {
@@ -80,13 +82,19 @@ export type ModerationLogPayloads = {
after: any | null;
};
suspend: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
unsuspend: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
updateUserNote: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
before: string | null;
after: string | null;
};
@@ -105,15 +113,23 @@ export type ModerationLogPayloads = {
};
assignRole: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
roleId: string;
roleName: string;
expiresAt: string | null;
};
unassignRole: {
userId: string;
+ userUsername: string;
+ userHost: string | null;
roleId: string;
roleName: string;
};
+ createRole: {
+ roleId: string;
+ role: any;
+ };
updateRole: {
roleId: string;
before: any;
@@ -128,10 +144,14 @@ export type ModerationLogPayloads = {
deleteDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
};
deleteNote: {
noteId: string;
noteUserId: string;
+ noteUserUsername: string;
+ noteUserHost: string | null;
note: any;
};
createGlobalAnnouncement: {
@@ -142,6 +162,8 @@ export type ModerationLogPayloads = {
announcementId: string;
announcement: any;
userId: string;
+ userUsername: string;
+ userHost: string | null;
};
updateGlobalAnnouncement: {
announcementId: string;
@@ -152,6 +174,9 @@ export type ModerationLogPayloads = {
announcementId: string;
before: any;
after: any;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
deleteGlobalAnnouncement: {
announcementId: string;
@@ -162,7 +187,9 @@ export type ModerationLogPayloads = {
announcement: any;
};
resetPassword: {
- targetId: string;
+ userId: string;
+ userUsername: string;
+ userHost: string | null;
};
suspendRemoteInstance: {
id: string;
@@ -175,9 +202,18 @@ export type ModerationLogPayloads = {
markSensitiveDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
};
unmarkSensitiveDriveFile: {
fileId: string;
fileUserId: string | null;
+ fileUserUsername: string | null;
+ fileUserHost: string | null;
+ };
+ resolveAbuseReport: {
+ reportId: string;
+ report: any;
+ forwarded: boolean;
};
};
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index f377f1a5ed..41c9bdef6e 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -602,6 +602,9 @@ export type ModerationLog = {
type: 'unassignRole';
info: ModerationLogPayloads['unassignRole'];
} | {
+ type: 'createRole';
+ info: ModerationLogPayloads['createRole'];
+} | {
type: 'updateRole';
info: ModerationLogPayloads['updateRole'];
} | {