diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts index 6062e464ba..9e8bb8b4fd 100644 --- a/packages/backend/src/core/NoteEditService.ts +++ b/packages/backend/src/core/NoteEditService.ts @@ -118,7 +118,7 @@ type MinimumUser = { uri: MiUser['uri']; }; -type Option = { +export type Option = { createdAt?: Date | null; name?: string | null; text?: string | null; diff --git a/packages/backend/src/server/api/endpoints/admin/cw-note.ts b/packages/backend/src/server/api/endpoints/admin/cw-note.ts index a549f57fb3..ba2240b8b2 100644 --- a/packages/backend/src/server/api/endpoints/admin/cw-note.ts +++ b/packages/backend/src/server/api/endpoints/admin/cw-note.ts @@ -4,11 +4,14 @@ */ import { Inject, Injectable } from '@nestjs/common'; +import { In } from 'typeorm'; import { Endpoint } from '@/server/api/endpoint-base.js'; -import type { MiNote, MiUser, NotesRepository } from '@/models/_.js'; +import type { ChannelsRepository, DriveFilesRepository, MiNote, NotesRepository } from '@/models/_.js'; import { DI } from '@/di-symbols.js'; import { ModerationLogService } from '@/core/ModerationLogService.js'; -import { NoteEditService } from '@/core/NoteEditService.js'; +import { NoteEditService, Option } from '@/core/NoteEditService.js'; +import { CacheService } from '@/core/CacheService.js'; +import { awaitAll } from '@/misc/prelude/await-all.js'; export const meta = { tags: ['admin'], @@ -35,14 +38,22 @@ export default class extends Endpoint { // eslint- @Inject(DI.notesRepository) private readonly notesRepository: NotesRepository, + @Inject(DI.driveFilesRepository) + private readonly driveFilesRepository: DriveFilesRepository, + + @Inject(DI.channelsRepository) + private readonly channelsRepository: ChannelsRepository, + private readonly noteEditService: NoteEditService, private readonly moderationLogService: ModerationLogService, + private readonly cacheService: CacheService, ) { super(meta, paramDef, async (ps, me) => { const note = await this.notesRepository.findOneOrFail({ where: { id: ps.noteId }, - relations: { user: true }, - }) as MiNote & { user: MiUser }; + relations: { reply: true, renote: true, channel: true }, + }); + const user = await this.cacheService.findUserById(note.userId); // Collapse empty strings to null const newCW = ps.cw?.trim() || null; @@ -51,16 +62,51 @@ export default class extends Endpoint { // eslint- // Skip if there's nothing to do if (oldCW === newCW) return; - await this.noteEditService.edit(note.user, note.id, { mandatoryCW: newCW }); + // TODO remove this after merging hazelnoot/fix-note-edit-logic. + // Until then, we have to ensure that everything is populated just like it would be from notes/edit.ts. + // Otherwise forcing a CW will erase everything else in the note. + // After merging remove all the "createUpdate" stuff and just pass "{ mandatoryCW: newCW }" into noteEditService.edit(). + const update = await this.createUpdate(note, newCW); + await this.noteEditService.edit(user, note.id, update); await this.moderationLogService.log(me, 'setMandatoryCWForNote', { newCW, oldCW, noteId: note.id, - noteUserId: note.user.id, - noteUserUsername: note.user.username, - noteUserHost: note.user.host, + noteUserId: user.id, + noteUserUsername: user.username, + noteUserHost: user.host, }); }); } + + // Note: user must be fetched with reply, renote, and channel relations populated + private async createUpdate(note: MiNote, newCW: string | null) { + // This is based on the call to NoteEditService.edit from notes/edit endpoint. + // noinspection ES6MissingAwait + return await awaitAll