enhance(moderation): 管理者がアカウントの物理削除・論理削除を選べるように (MisskeyIO#581)
This commit is contained in:
parent
acc10c0709
commit
b4420f895e
|
@ -37,6 +37,7 @@ export const paramDef = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
properties: {
|
||||||
userId: { type: 'string', format: 'misskey:id' },
|
userId: { type: 'string', format: 'misskey:id' },
|
||||||
|
soft: { type: 'boolean', default: true, description: 'Since deletion by an administrator is a moderation action, the default is to soft delete.' },
|
||||||
},
|
},
|
||||||
required: ['userId'],
|
required: ['userId'],
|
||||||
} as const;
|
} as const;
|
||||||
|
@ -56,8 +57,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||||
if (user == null) throw new ApiError(meta.errors.userNotFound);
|
if (user == null) throw new ApiError(meta.errors.userNotFound);
|
||||||
if (await this.roleService.isModerator(user)) throw new ApiError(meta.errors.cannotDeleteModerator);
|
if (await this.roleService.isModerator(user)) throw new ApiError(meta.errors.cannotDeleteModerator);
|
||||||
|
|
||||||
// 管理者からの削除ということはモデレーション行為なので、soft delete にする
|
await this.deleteAccountService.deleteAccount(user, ps.soft, me);
|
||||||
await this.deleteAccountService.deleteAccount(user, true, me);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,11 +58,16 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
|
||||||
<FormSection>
|
<FormSection>
|
||||||
<div class="_gaps">
|
<div class="_gaps">
|
||||||
<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.suspend }}</MkSwitch>
|
<MkFolder v-if="iAmModerator" defaultOpen>
|
||||||
|
<template #icon><i class="ti ti-shield"></i></template>
|
||||||
<div>
|
<template #label>{{ i18n.ts.moderation }}</template>
|
||||||
<MkButton v-if="user.host == null" inline style="margin-right: 8px;" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton>
|
<div class="_gaps">
|
||||||
</div>
|
<MkSwitch v-model="suspended" @update:modelValue="toggleSuspend">{{ i18n.ts.suspend }}</MkSwitch>
|
||||||
|
<MkButton v-if="user.host == null" @click="resetPassword"><i class="ti ti-key"></i> {{ i18n.ts.resetPassword }}</MkButton>
|
||||||
|
<MkButton inline danger @click="unsetUserAvatar"><i class="ti ti-user-circle"></i> {{ i18n.ts.unsetUserAvatar }}</MkButton>
|
||||||
|
<MkButton inline danger @click="unsetUserBanner"><i class="ti ti-photo"></i> {{ i18n.ts.unsetUserBanner }}</MkButton>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
|
|
||||||
<MkFolder>
|
<MkFolder>
|
||||||
<template #icon><i class="ti ti-license"></i></template>
|
<template #icon><i class="ti ti-license"></i></template>
|
||||||
|
@ -87,11 +92,14 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||||
</template>
|
</template>
|
||||||
</MkFolder>
|
</MkFolder>
|
||||||
|
|
||||||
<div class="_buttons">
|
<MkFolder v-if="$i.isAdmin">
|
||||||
<MkButton v-if="iAmModerator" inline danger @click="unsetUserAvatar"><i class="ti ti-user-circle"></i> {{ i18n.ts.unsetUserAvatar }}</MkButton>
|
<template #icon><i class="ti ti-user-x"></i></template>
|
||||||
<MkButton v-if="iAmModerator" inline danger @click="unsetUserBanner"><i class="ti ti-photo"></i> {{ i18n.ts.unsetUserBanner }}</MkButton>
|
<template #label>{{ i18n.ts.deleteAccount }}</template>
|
||||||
</div>
|
<div class="_gaps">
|
||||||
<MkButton v-if="$i.isAdmin" inline danger @click="deleteAccount">{{ i18n.ts.deleteAccount }}</MkButton>
|
<MkButton inline danger @click="deleteAccount(true)"><i class="ti ti-user-x"></i> {{ i18n.ts.deleteAccount }}</MkButton>
|
||||||
|
<MkButton inline danger @click="deleteAccount(false)"><i class="ti ti-file-shredder"></i> {{ i18n.ts.deleteAccount }} ({{ i18n.ts.all }})</MkButton>
|
||||||
|
</div>
|
||||||
|
</MkFolder>
|
||||||
</div>
|
</div>
|
||||||
</FormSection>
|
</FormSection>
|
||||||
</div>
|
</div>
|
||||||
|
@ -380,7 +388,7 @@ async function deleteAllFiles() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function deleteAccount() {
|
async function deleteAccount(soft: boolean) {
|
||||||
const confirm = await os.confirm({
|
const confirm = await os.confirm({
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
text: i18n.ts.deleteAccountConfirm,
|
text: i18n.ts.deleteAccountConfirm,
|
||||||
|
@ -395,6 +403,7 @@ async function deleteAccount() {
|
||||||
if (typed.result === user.value?.username) {
|
if (typed.result === user.value?.username) {
|
||||||
await os.apiWithDialog('admin/accounts/delete', {
|
await os.apiWithDialog('admin/accounts/delete', {
|
||||||
userId: user.value.id,
|
userId: user.value.id,
|
||||||
|
soft,
|
||||||
}).then(refreshUser);
|
}).then(refreshUser);
|
||||||
} else {
|
} else {
|
||||||
os.alert({
|
os.alert({
|
||||||
|
|
|
@ -5438,6 +5438,11 @@ export type operations = {
|
||||||
'application/json': {
|
'application/json': {
|
||||||
/** Format: misskey:id */
|
/** Format: misskey:id */
|
||||||
userId: string;
|
userId: string;
|
||||||
|
/**
|
||||||
|
* @description Since deletion by an administrator is a moderation action, the default is to soft delete.
|
||||||
|
* @default true
|
||||||
|
*/
|
||||||
|
soft?: boolean;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue