mirror of
https://github.com/MisskeyIO/misskey
synced 2024-11-27 06:18:40 +09:00
enhance(moderation): 凍結されたユーザー・削除されたユーザーを可視化できるように (MisskeyIO#676)
This commit is contained in:
parent
3db41c2d82
commit
787d00bec0
@ -66,6 +66,13 @@ export const meta = {
|
||||
id: '4362f8dc-731f-4ad8-a694-be5a88922a24',
|
||||
httpStatusCode: 404,
|
||||
},
|
||||
|
||||
userSuspended: {
|
||||
message: 'User is suspended.',
|
||||
code: 'USER_SUSPENDED',
|
||||
id: 'c1e1b0d6-2b7c-4c1d-9f1d-2d3d6e8d7e7f',
|
||||
httpStatusCode: 403,
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
|
||||
@ -147,10 +154,19 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
user = await this.usersRepository.findOneBy(q);
|
||||
}
|
||||
|
||||
if (user == null || (!isModerator && user.isSuspended)) {
|
||||
if (user == null) {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
|
||||
if (!isModerator) {
|
||||
if (user.isDeleted && user.isSuspended) {
|
||||
throw new ApiError(meta.errors.noSuchUser);
|
||||
}
|
||||
if (user.isSuspended) {
|
||||
throw new ApiError(meta.errors.userSuspended);
|
||||
}
|
||||
}
|
||||
|
||||
if (user.host == null) {
|
||||
if (me == null && ip != null) {
|
||||
this.perUserPvChart.commitByVisitor(user, ip);
|
||||
|
@ -8,7 +8,7 @@ process.env.NODE_ENV = 'test';
|
||||
import * as assert from 'assert';
|
||||
import { inspect } from 'node:util';
|
||||
import { DEFAULT_POLICIES } from '@/core/RoleService.js';
|
||||
import { api, post, role, signup, successfulApiCall, uploadFile } from '../utils.js';
|
||||
import { api, post, role, signup, successfulApiCall, uploadFile, failedApiCall } from '../utils.js';
|
||||
import type * as misskey from 'misskey-js';
|
||||
|
||||
describe('ユーザー', () => {
|
||||
@ -883,6 +883,22 @@ describe('ユーザー', () => {
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 凍結/削除ユーザー
|
||||
test('が凍結済みのユーザー情報を取得できない', async () => {
|
||||
const parameters = { userId: userSuspended.id };
|
||||
await failedApiCall({ endpoint: 'users/show', parameters, user: alice },
|
||||
{ status: 403, code: 'USER_SUSPENDED', id: 'c1e1b0d6-2b7c-4c1d-9f1d-2d3d6e8d7e7f' });
|
||||
});
|
||||
|
||||
test('(Admin)が凍結済みユーザー情報を取得できる', async () => {
|
||||
const parameters = { userId: userSuspended.id };
|
||||
await successfulApiCall({ endpoint: 'users/show', parameters, user: root });
|
||||
// Adminとユーザー情報は持っている情報が違うので、比較はできない
|
||||
// const expected = userSuspended;
|
||||
// assert.deepStrictEqual(response, expected);
|
||||
});
|
||||
//#endregion
|
||||
|
||||
test.todo('を管理人として確認することができる(admin/show-user)');
|
||||
test.todo('を管理人として確認することができる(admin/show-users)');
|
||||
test.todo('をサーバー向けに取得することができる(federation/users)');
|
||||
|
44
packages/frontend/src/components/MkUserNotFound.vue
Normal file
44
packages/frontend/src/components/MkUserNotFound.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear>
|
||||
<div :class="$style.root">
|
||||
<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
|
||||
<p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.noSuchUser }}</p>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { serverErrorImageUrl } from '@/instance.js';
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.img {
|
||||
vertical-align: bottom;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
</style>
|
44
packages/frontend/src/components/MkUserSuspended.vue
Normal file
44
packages/frontend/src/components/MkUserSuspended.vue
Normal file
@ -0,0 +1,44 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
SPDX-License-Identifier: AGPL-3.0-only
|
||||
-->
|
||||
|
||||
<template>
|
||||
<Transition :name="defaultStore.state.animation ? '_transition_zoom' : ''" appear>
|
||||
<div :class="$style.root">
|
||||
<img :class="$style.img" :src="serverErrorImageUrl" class="_ghost"/>
|
||||
<p :class="$style.text"><i class="ti ti-alert-triangle"></i> {{ i18n.ts.userSuspended }}</p>
|
||||
</div>
|
||||
</Transition>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { defaultStore } from '@/store.js';
|
||||
import { serverErrorImageUrl } from '@/instance.js';
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
.root {
|
||||
padding: 32px;
|
||||
text-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.text {
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.button {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.img {
|
||||
vertical-align: bottom;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
margin-bottom: 16px;
|
||||
border-radius: 16px;
|
||||
}
|
||||
</style>
|
@ -24,7 +24,13 @@ SPDX-License-Identifier: AGPL-3.0-only
|
||||
<XRaw v-else-if="tab === 'raw'" key="raw" :user="user"/>
|
||||
</MkHorizontalSwipe>
|
||||
</div>
|
||||
<MkError v-else-if="error" @retry="fetchUser()"/>
|
||||
<div v-else-if="error">
|
||||
<MkError @retry="fetchUser()"/>
|
||||
</div>
|
||||
<div v-else-if="userstatus">
|
||||
<MkUserNotFound v-if="userstatus === 'notfound'"/>
|
||||
<MkUserSuspended v-else-if="userstatus === 'suspended'"/>
|
||||
</div>
|
||||
<MkLoading v-else/>
|
||||
</div>
|
||||
</MkStickyContainer>
|
||||
@ -38,6 +44,8 @@ import { misskeyApi } from '@/scripts/misskey-api.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
import { $i } from '@/account.js';
|
||||
import MkUserNotFound from '@/components/MkUserNotFound.vue';
|
||||
import MkUserSuspended from '@/components/MkUserSuspended.vue';
|
||||
import MkHorizontalSwipe from '@/components/MkHorizontalSwipe.vue';
|
||||
|
||||
const XHome = defineAsyncComponent(() => import('./home.vue'));
|
||||
@ -62,7 +70,8 @@ const props = withDefaults(defineProps<{
|
||||
const tab = ref(props.page);
|
||||
|
||||
const user = ref<null | Misskey.entities.UserDetailed>(null);
|
||||
const error = ref<any>(null);
|
||||
const error = ref<null | any>(null);
|
||||
const userstatus = ref<null | any>(null);
|
||||
|
||||
function fetchUser(): void {
|
||||
if (props.acct == null) return;
|
||||
@ -70,7 +79,13 @@ function fetchUser(): void {
|
||||
misskeyApi('users/show', Misskey.acct.parse(props.acct)).then(u => {
|
||||
user.value = u;
|
||||
}).catch(err => {
|
||||
error.value = err;
|
||||
if (err.id && err.id === '4362f8dc-731f-4ad8-a694-be5a88922a24') { // User not found
|
||||
userstatus.value = 'notfound';
|
||||
} else if (err.id && err.id === 'c1e1b0d6-2b7c-4c1d-9f1d-2d3d6e8d7e7f') { // User suspended
|
||||
userstatus.value = 'suspended';
|
||||
} else {
|
||||
error.value = err;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user