diff --git a/locales/en-US.yml b/locales/en-US.yml index 437a201492..0e51870146 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1932,6 +1932,13 @@ _accountDelete: requestAccountDelete: "Request account deletion" started: "Deletion has been started." inProgress: "Deletion is currently in progress" +_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 c10ef4e0cc..0c5fe5c7dd 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -7537,6 +7537,10 @@ export interface Locale extends ILocale { * アカウントの整理 */ "accountDelete": string; + /** + * ドライブのファイルもすべて消去 + */ + "purgeDriveFiles": string; /** * アカウントの整理は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index a6802fc68d..b5089e7f22 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1962,6 +1962,7 @@ _accountDelete: _accountTruncate: accountDelete: "アカウントの整理" + purgeDriveFiles: "ドライブのファイルもすべて消去" mayTakeTime: "アカウントの整理は負荷のかかる処理であるため、作成したコンテンツの数やアップロードしたファイルの数が多いと完了までに時間がかかることがあります。" requestAccountTruncate: "アカウント整理をリクエスト" started: "整理処理が開始されました。" diff --git a/locales/ko-KR.yml b/locales/ko-KR.yml index 996119f550..6b86e0d1e7 100644 --- a/locales/ko-KR.yml +++ b/locales/ko-KR.yml @@ -995,7 +995,7 @@ followingVisibility: "팔로우 목록의 공개 범위" followersVisibility: "팔로워 목록의 공개 범위" continueThread: "대화 이어서 보기" deleteAccountConfirm: "계정이 삭제되고 복구할 수 없습니다. 그래도 계속하시겠습니까?" -truncateAccountConfirm: "다이렉트 및 프로필 상단에 고정된 노트를 제외한 모든 노트와 파일을 제거하고 복구할 수 없습니다. 그래도 계속하시겠습니까?" +truncateAccountConfirm: "다이렉트 및 프로필 상단에 고정된 노트를 제외한 모든 노트가 (드라이브 정리 옵션을 켠 경우 모든 파일도) 삭제되고 이는 복구할 수 없습니다. 그래도 계속하시겠습니까?" incorrectPassword: "올바르지 않은 계정 정보입니다." voteConfirm: "\"{choice}\"에 투표하시겠습니까?" hide: "숨기기" @@ -1944,17 +1944,18 @@ _signup: emailSent: "입력한 메일 주소({email})로 확인 메일을 보내드렸어요! 가입을 완료하려면 보내드린 메일에 있는 링크로 접속해 주세요.\n만약 메일이 오지 않는다면 스팸 메일함을 확인해 주세요!" _accountDelete: accountDelete: "계정 삭제" - mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있어요." - sendEmail: "계정 삭제가 완료되면 등록된 메일 주소로 알림을 보내드려요." - requestAccountDelete: "계정 삭제 요청" - started: "삭제 작업이 시작되었어요." - inProgress: "삭제 진행 중" + mayTakeTime: "계정 삭제는 서버에 부하를 가하기 때문에, 서버에서 시간을 들여 느리게 처리합니다. 만약 업로드한 컨텐츠가 많으면 시간이 오래 걸릴 수 있습니다." + sendEmail: "계정 삭제가 완료되면 등록되어 있는 이메일 주소로 완료 알림을 전송해드립니다." + requestAccountDelete: "계정 삭제를 요청하기" + started: "계정 삭제가 시작되었습니다. 안녕히 가세요!" + inProgress: "삭제 작업이 진행 중입니다..." _accountTruncate: accountTruncate: "계정 청소" - mayTakeTime: "계정 청소는 서버에 부하를 가하기 때문에, 작성한 콘텐츠나 업로드한 파일의 수가 많으면 완료까지 시간이 걸릴 수 있습니다." - requestAccountTruncate: "계정 청소 요청" + purgeDriveFiles: "드라이브의 파일도 정리하기" + mayTakeTime: "계정 청소는 서버에 부하를 가하기 때문에, 서버에서 시간을 들여 느리게 처리합니다. 만약 업로드한 컨텐츠가 많으면 시간이 오래 걸릴 수 있습니다." + requestAccountTruncate: "계정 청소를 요청하기" started: "청소 작업이 시작되었습니다." - inProgress: "청소 진행 중" + inProgress: "청소 작업이 진행 중입니다..." _ad: back: "뒤로" reduceFrequencyOfThisAd: "이 광고의 표시 빈도 낮추기" diff --git a/packages/backend/src/core/QueueService.ts b/packages/backend/src/core/QueueService.ts index 0f1a133ee9..f85b91da62 100644 --- a/packages/backend/src/core/QueueService.ts +++ b/packages/backend/src/core/QueueService.ts @@ -367,9 +367,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 ef042cf259..866275fd61 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/queue/processors/TruncateAccountProcessorService.ts b/packages/backend/src/queue/processors/TruncateAccountProcessorService.ts index 4b2f33b989..53d4ba2fd3 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, 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 5d4633d4e1..165f812ed6 100644 --- a/packages/backend/src/queue/types.ts +++ b/packages/backend/src/queue/types.ts @@ -83,6 +83,7 @@ export type DbUserDeleteJobData = { export type DbUserTruncateJobData = { user: ThinUser; + purgeDrive: boolean; }; export type DbUserImportJobData = { diff --git a/packages/backend/src/server/api/StreamingApiServerService.ts b/packages/backend/src/server/api/StreamingApiServerService.ts index 04bc2a8827..e4162bb6e0 100644 --- a/packages/backend/src/server/api/StreamingApiServerService.ts +++ b/packages/backend/src/server/api/StreamingApiServerService.ts @@ -79,7 +79,7 @@ export class StreamingApiServerService { if (e instanceof AuthenticationError) { socket.write([ 'HTTP/1.1 401 Unauthorized', - 'WWW-Authenticate: Bearer realm="CherryPick", error="invalid_token", error_description="Failed to authenticate"', + 'WWW-Authenticate: Bearer realm="LycheeBridge", error="invalid_token", error_description="Failed to authenticate"', ].join('\r\n') + '\r\n\r\n'); } else { socket.write('HTTP/1.1 500 Internal Server Error\r\n\r\n'); 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 8ff841789a..fbad69f43a 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/frontend/src/pages/settings/other.vue b/packages/frontend/src/pages/settings/other.vue index 92fd17480e..e963c62ff5 100644 --- a/packages/frontend/src/pages/settings/other.vue +++ b/packages/frontend/src/pages/settings/other.vue @@ -54,6 +54,9 @@ SPDX-License-Identifier: AGPL-3.0-only
{{ i18n.ts._accountTruncate.mayTakeTime }} + + + {{ i18n.ts._accountTruncate.requestAccountTruncate }} {{ i18n.ts._accountTruncate.inProgress }}
@@ -98,7 +101,7 @@ SPDX-License-Identifier: AGPL-3.0-only