From 0793a9ba84467ceec5b304a28cd5b925efa1d72e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=95=84=EB=A5=B4=ED=8E=98?= Date: Thu, 15 Feb 2024 22:18:22 +0900 Subject: [PATCH] feat: purge notes without drive files --- locales/en-US.yml | 7 +++++++ locales/index.d.ts | 4 ++++ locales/ja-JP.yml | 1 + locales/ko-KR.yml | 13 +++++++------ packages/backend/src/core/QueueService.ts | 3 ++- packages/backend/src/core/TruncateAccountService.ts | 4 ++-- packages/backend/src/models/AutoRemovalCondition.ts | 2 +- .../models/json-schema/auto-removal-condition.ts | 2 +- .../processors/AutoNoteRemovalProcessorService.ts | 2 +- .../processors/TruncateAccountProcessorService.ts | 8 ++++---- packages/backend/src/queue/types.ts | 1 + .../src/server/api/endpoints/i/truncate-account.ts | 4 +++- .../api/endpoints/i/update-removal-condition.ts | 2 +- packages/frontend/src/pages/settings/other.vue | 9 +++++++-- packages/misskey-js/src/autogen/types.ts | 1 + 15 files changed, 43 insertions(+), 20 deletions(-) diff --git a/locales/en-US.yml b/locales/en-US.yml index 7783ccc4e..4be0c8a09 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1826,6 +1826,13 @@ _accountDelete: started: "Deletion has been started." inProgress: "Deletion is currently in progress" youCantUseThisTime: "You can't request account deletion for now." +_accountTruncate: + accountTruncate: "Truncate account" + purgeDriveFiles: "Also purge drive's files" + mayTakeTime: "As account deletion is a resource-heavy process, it may take some time to complete depending on how much content you have created and how many files you have uploaded." + requestAccountTruncate: "Request to truncate my account" + started: "Truncate task has been started." + inProgress: "Your account is currently being truncated" _ad: back: "Back" reduceFrequencyOfThisAd: "Show this ad less" diff --git a/locales/index.d.ts b/locales/index.d.ts index fa78c6bcb..623bd2c41 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7305,6 +7305,10 @@ export interface Locale extends ILocale { * アカウントの整理 */ "accountDelete": string; + /** + * ドライブのファイルもすべて消去 + */ + "purgeDriveFiles": string; /** * アカウントの整理は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index f432753c6..976205e0c 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1893,6 +1893,7 @@ _accountDelete: _accountTruncate: accountDelete: "アカウントの整理" + purgeDriveFiles: "ドライブのファイルもすべて消去" mayTakeTime: "アカウントの整理は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。" requestAccountTruncate: "アカウント整理をリクエスト" started: "整理処理が開始されました。" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index e8d0ffcbe..efb293bd6 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -909,7 +909,7 @@ followingVisibility: "팔로우 중인 유저를 볼 수 있는 사람" followersVisibility: "내 팔로워를 볼 수 있는 사람" continueThread: "글타래 더 보기" deleteAccountConfirm: "계정이 삭제되고 되돌릴 수 없게 됩니다. 계속하시겠습니까? " -truncateAccountConfirm: "다이렉트 및 프로필 상단에 고정된 노트를 제외한 모든 노트와 파일을 제거하고 복구할 수 없습니다. 그래도 계속하시겠습니까?" +truncateAccountConfirm: "다이렉트 및 프로필 상단에 고정된 노트를 제외한 모든 노트가 (드라이브 정리 옵션을 켠 경우 모든 파일도) 삭제되고 이는 복구할 수 없습니다. 그래도 계속하시겠습니까?" incorrectPassword: "비밀번호가 올바르지 않습니다." voteConfirm: "\"{choice}\"에 투표하시겠습니까?" hide: "숨기기" @@ -1853,16 +1853,17 @@ _signup: emailSent: "입력하신 메일 주소({email})로 확인 메일을 보내드렸습니다. 가입을 완료하시려면 보내드린 메일에 있는 링크로 접속해 주세요." _accountDelete: accountDelete: "계정 삭제" - mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다." - sendEmail: "계정 삭제가 완료되면 등록된 이메일 주소로 알림을 보냅니다." - requestAccountDelete: "계정 삭제 요청" + mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 서버에서 시간을 들여 느리게 처리합니다. 만약 업로드한 컨텐츠가 많으면 시간이 오래 걸릴 수 있습니다." + sendEmail: "계정 삭제가 완료되면 등록했던 이메일 주소로 알림을 보내드립니다." + requestAccountDelete: "계정 삭제를 요청하기" started: "삭제 작업이 시작되었습니다." inProgress: "삭제 진행 중" youCantUseThisTime: "지금은 계정 삭제를 진행할 수 없습니다." _accountTruncate: accountTruncate: "계정 청소" - mayTakeTime: "계정 청소는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다." - requestAccountTruncate: "계정 청소 요청" + purgeDriveFiles: "드라이브의 파일도 정리하기" + mayTakeTime: "계정 청소는 서버에 부하를 가하기 때문에, 서버에서 시간을 들여 느리게 처리합니다. 만약 업로드한 컨텐츠가 많으면 시간이 오래 걸릴 수 있습니다." + requestAccountTruncate: "계정 청소를 요청하기" started: "청소 작업이 시작되었습니다." inProgress: "청소 진행 중" _ad: diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index bbed9641a..bd7c0946f 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -390,9 +390,10 @@ export class QueueService { } @bindThis - public createTruncateAccountJob(user: ThinUser, opts = {}) { + public createTruncateAccountJob(user: ThinUser, purgeDrive: boolean, opts = {}) { return this.dbQueue.add('truncateAccount', { user: { id: user.id }, + purgeDrive: purgeDrive, }, { removeOnComplete: true, removeOnFail: true, diff --git a/packages/backend/src/core/TruncateAccountService.ts b/packages/backend/src/core/TruncateAccountService.ts index ef042cf25..866275fd6 100644 --- a/packages/backend/src/core/TruncateAccountService.ts +++ b/packages/backend/src/core/TruncateAccountService.ts @@ -23,10 +23,10 @@ export class TruncateAccountService { public async truncateAccount(user: { id: string; host: string | null; - }): Promise { + }, purgeDrive: boolean | false): Promise { const _user = await this.usersRepository.findOneByOrFail({ id: user.id }); - this.queueService.createTruncateAccountJob(user, { + this.queueService.createTruncateAccountJob(user, purgeDrive, { soft: false, }); } diff --git a/packages/backend/src/models/AutoRemovalCondition.ts b/packages/backend/src/models/AutoRemovalCondition.ts index ab273791d..6b120f83c 100644 --- a/packages/backend/src/models/AutoRemovalCondition.ts +++ b/packages/backend/src/models/AutoRemovalCondition.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: syuilo and noridev and other misskey, cherrypick contributors + * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ diff --git a/packages/backend/src/models/json-schema/auto-removal-condition.ts b/packages/backend/src/models/json-schema/auto-removal-condition.ts index 701dce0ad..7fd18d566 100644 --- a/packages/backend/src/models/json-schema/auto-removal-condition.ts +++ b/packages/backend/src/models/json-schema/auto-removal-condition.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors + * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ diff --git a/packages/backend/src/queue/processors/AutoNoteRemovalProcessorService.ts b/packages/backend/src/queue/processors/AutoNoteRemovalProcessorService.ts index 4ed845055..cb9bb56f0 100644 --- a/packages/backend/src/queue/processors/AutoNoteRemovalProcessorService.ts +++ b/packages/backend/src/queue/processors/AutoNoteRemovalProcessorService.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors + * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ diff --git a/packages/backend/src/queue/processors/TruncateAccountProcessorService.ts b/packages/backend/src/queue/processors/TruncateAccountProcessorService.ts index 4b2f33b98..64aa7e3e9 100644 --- a/packages/backend/src/queue/processors/TruncateAccountProcessorService.ts +++ b/packages/backend/src/queue/processors/TruncateAccountProcessorService.ts @@ -43,7 +43,7 @@ export class TruncateAccountProcessorService { @bindThis public async process(job: Bull.Job): Promise { - this.logger.info(`Truncate notes and drives account of ${job.data.user.id} ...`); + this.logger.info(`Truncate account of ${job.data.user.id} ...`); const user = await this.usersRepository.findOneBy({ id: job.data.user.id }); if (user == null) { @@ -98,7 +98,7 @@ export class TruncateAccountProcessorService { this.logger.succ('All of notes deleted'); } - { // Delete files + if (job.data.purgeDrive) { // Delete files let cursor: MiDriveFile['id'] | null = null; while (true) { @@ -124,13 +124,13 @@ export class TruncateAccountProcessorService { cursor = files.at(-1)?.id ?? null; for (const file of files) { - await this.driveService.deleteFileSync(file); + await this.driveService.deleteFileSync(file, false, user); } } this.logger.succ('All of files deleted'); } - return 'Account notes and drives are truncated'; + return 'Account truncate job completed'; } } diff --git a/packages/backend/src/queue/types.ts b/packages/backend/src/queue/types.ts index 0829d6180..0f167c62a 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -86,6 +86,7 @@ export type DbUserDeleteJobData = { export type DbUserTruncateJobData = { user: ThinUser; + purgeDrive: boolean; }; export type DbUserImportJobData = { diff --git a/packages/backend/src/server/api/endpoints/i/truncate-account.ts b/packages/backend/src/server/api/endpoints/i/truncate-account.ts index 8ff841789..fbad69f43 100644 --- a/packages/backend/src/server/api/endpoints/i/truncate-account.ts +++ b/packages/backend/src/server/api/endpoints/i/truncate-account.ts @@ -22,6 +22,7 @@ export const paramDef = { properties: { password: { type: 'string' }, token: { type: 'string', nullable: true }, + purgeDrive: { type: 'boolean', nullable: true }, }, required: ['password'], } as const; @@ -40,6 +41,7 @@ export default class extends Endpoint { // eslint- ) { super(meta, paramDef, async (ps, me) => { const token = ps.token; + const purgeDrive = ps.purgeDrive ? true : false; const profile = await this.userProfilesRepository.findOneByOrFail({ userId: me.id }); if (profile.twoFactorEnabled) { @@ -64,7 +66,7 @@ export default class extends Endpoint { // eslint- throw new Error('incorrect password'); } - await this.truncateAccountService.truncateAccount(me); + await this.truncateAccountService.truncateAccount(me, purgeDrive); }); } } diff --git a/packages/backend/src/server/api/endpoints/i/update-removal-condition.ts b/packages/backend/src/server/api/endpoints/i/update-removal-condition.ts index 357b17015..62c447776 100644 --- a/packages/backend/src/server/api/endpoints/i/update-removal-condition.ts +++ b/packages/backend/src/server/api/endpoints/i/update-removal-condition.ts @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors + * SPDX-FileCopyrightText: syuilo and misskey-project * SPDX-License-Identifier: AGPL-3.0-only */ diff --git a/packages/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index c5f1acac4..e64449ca0 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -82,7 +82,10 @@ SPDX-License-Identifier: AGPL-3.0-only
- {{ i18n.ts._accountTruncate.mayTakeTime }} + {{ i18n.ts._accountTruncate.mayTakeTime }} + + + {{ i18n.ts._accountTruncate.requestAccountTruncate }} {{ i18n.ts._accountTruncate.inProgress }}
@@ -132,8 +135,9 @@ import { signout, signinRequired } from '@/account.js'; import { i18n } from '@/i18n.js'; import { definePageMetadata } from '@/scripts/page-metadata.js'; -const $i = signinRequired(); // const reportError = computed(defaultStore.makeGetterSetter('reportError')); +const $i = signinRequired(); +const purgeDrive = ref(false); const devMode = computed(defaultStore.makeGetterSetter('devMode')); const defaultWithReplies = computed(defaultStore.makeGetterSetter('defaultWithReplies')); const autoRemoval = ref($i.autoRemovalCondition.active); @@ -189,6 +193,7 @@ async function truncateAccount() { await os.apiWithDialog('i/truncate-account', { password: auth.result.password, token: auth.result.token, + purgeDrive: purgeDrive.value, }); await os.alert({ diff --git a/packages/misskey-js/src/autogen/types.ts b/packages/misskey-js/src/autogen/types.ts index 132c7e9a8..aa9178fcc 100644 --- a/packages/misskey-js/src/autogen/types.ts +++ b/packages/misskey-js/src/autogen/types.ts @@ -18247,6 +18247,7 @@ export type operations = { 'application/json': { password: string; token?: string | null; + purgeDrive?: boolean | null; }; }; };