From f2b93eb3e16628df47da693a785b25482cff1d3b Mon Sep 17 00:00:00 2001 From: mattyatea Date: Fri, 31 Jan 2025 21:43:45 +0900 Subject: [PATCH 1/8] WIP --- packages/backend/src/core/DriveService.ts | 8 +++++++- .../src/core/entities/DriveFileEntityService.ts | 2 ++ packages/backend/src/models/DriveFile.ts | 6 ++++++ packages/backend/src/models/json-schema/drive-file.ts | 4 ++++ packages/backend/src/postgres.ts | 2 +- .../src/server/api/endpoints/drive/files/update.ts | 10 ++++++++++ packages/frontend/src/pages/drive.file.info.vue | 1 + 7 files changed, 31 insertions(+), 2 deletions(-) diff --git a/packages/backend/src/core/DriveService.ts b/packages/backend/src/core/DriveService.ts index a68fc25ab2e8..5a366cc26b78 100644 --- a/packages/backend/src/core/DriveService.ts +++ b/packages/backend/src/core/DriveService.ts @@ -590,6 +590,7 @@ export class DriveService { if (info.sensitive && profile!.autoSensitive) file.isSensitive = true; if (info.sensitive && instance.setSensitiveFlagAutomatically) file.isSensitive = true; if (userRoleNSFW) file.isSensitive = true; + if (file.isSensitiveByModerator) file.isSensitive = true; if (url !== null) { file.src = url; @@ -660,6 +661,7 @@ export class DriveService { @bindThis public async updateFile(file: MiDriveFile, values: Partial, updater: MiUser) { const alwaysMarkNsfw = (await this.roleService.getUserPolicies(file.userId)).alwaysMarkNsfw; + const isModerator = await this.roleService.isModerator(updater); if (values.name != null && !this.driveFileEntityService.validateFileName(values.name)) { throw new DriveService.InvalidFileNameError(); @@ -680,6 +682,10 @@ export class DriveService { } } + if (isModerator && file.userId !== updater.id) { + values.isSensitiveByModerator = values.isSensitive; + } + await this.driveFilesRepository.update(file.id, values); const fileObj = await this.driveFileEntityService.pack(file.id, updater, { self: true }); @@ -689,7 +695,7 @@ export class DriveService { this.globalEventService.publishDriveStream(file.userId, 'fileUpdated', fileObj); } - if (await this.roleService.isModerator(updater) && (file.userId !== updater.id)) { + if (isModerator && (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) { diff --git a/packages/backend/src/core/entities/DriveFileEntityService.ts b/packages/backend/src/core/entities/DriveFileEntityService.ts index 289f267c4b3a..4422573eb621 100644 --- a/packages/backend/src/core/entities/DriveFileEntityService.ts +++ b/packages/backend/src/core/entities/DriveFileEntityService.ts @@ -217,6 +217,7 @@ export class DriveFileEntityService { thumbnailUrl: this.getThumbnailUrl(file), comment: file.comment, folderId: file.folderId, + isSensitiveByModerator: opts.detail ? file.isSensitiveByModerator : null, folder: opts.detail && file.folderId ? this.driveFolderEntityService.pack(file.folderId, { detail: true, }) : null, @@ -247,6 +248,7 @@ export class DriveFileEntityService { md5: file.md5, size: file.size, isSensitive: file.isSensitive, + isSensitiveByModerator: opts.detail ? file.isSensitiveByModerator : null, blurhash: file.blurhash, properties: opts.self ? file.properties : this.getPublicProperties(file), url: opts.self ? file.url : this.getPublicUrl(file), diff --git a/packages/backend/src/models/DriveFile.ts b/packages/backend/src/models/DriveFile.ts index 079e9cd9dc1a..6973e4d9d46a 100644 --- a/packages/backend/src/models/DriveFile.ts +++ b/packages/backend/src/models/DriveFile.ts @@ -162,6 +162,12 @@ export class MiDriveFile { }) public isSensitive: boolean; + @Index() + @Column('boolean', { + default: false, + }) + public isSensitiveByModerator: boolean; + @Index() @Column('boolean', { default: false, diff --git a/packages/backend/src/models/json-schema/drive-file.ts b/packages/backend/src/models/json-schema/drive-file.ts index ca88cc0e3975..0f8ad44f33d5 100644 --- a/packages/backend/src/models/json-schema/drive-file.ts +++ b/packages/backend/src/models/json-schema/drive-file.ts @@ -42,6 +42,10 @@ export const packedDriveFileSchema = { type: 'boolean', optional: false, nullable: false, }, + isSensitiveByModerator: { + type: 'boolean', + optional: false, nullable: true, + }, blurhash: { type: 'string', optional: false, nullable: true, diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index b272f7d6523e..05c2748be4f9 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -212,7 +212,7 @@ export const entities = [ ...charts, ]; -const log = process.env.NODE_ENV !== 'production'; +const log = false; const timeoutFinalizationRegistry = new FinalizationRegistry((reference: { name: string; timeout: NodeJS.Timeout }) => { dbLogger.info(`Finalizing timeout: ${reference.name}`); clearInterval(reference.timeout); diff --git a/packages/backend/src/server/api/endpoints/drive/files/update.ts b/packages/backend/src/server/api/endpoints/drive/files/update.ts index 42c03204a420..88afdba642d6 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/update.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/update.ts @@ -51,6 +51,12 @@ export const meta = { code: 'RESTRICTED_BY_ROLE', id: '7f59dccb-f465-75ab-5cf4-3ce44e3282f7', }, + + restrictedByModerator: { + message: 'The isSensitive specified by the moderator cannot be deleted.', + code: 'RESTRICTED_BY_MODERATOR', + id: '20e6c501-e579-400d-97e4-1c7efc286f35', + }, }, res: { type: 'object', @@ -90,6 +96,10 @@ export default class extends Endpoint { // eslint- throw new ApiError(meta.errors.accessDenied); } + if (!await this.roleService.isModerator(me) && !ps.isSensitive && file.isSensitiveByModerator) { + throw new ApiError(meta.errors.restrictedByModerator); + } + let packedFile; try { diff --git a/packages/frontend/src/pages/drive.file.info.vue b/packages/frontend/src/pages/drive.file.info.vue index 8077edff5f44..74cbd82d720b 100644 --- a/packages/frontend/src/pages/drive.file.info.vue +++ b/packages/frontend/src/pages/drive.file.info.vue @@ -6,6 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only