From 203fba0216a9123cfe45dba1b3fbe5ecbb36fe03 Mon Sep 17 00:00:00 2001 From: MeiMei <30769358+mei23@users.noreply.github.com> Date: Fri, 11 Jan 2019 08:09:44 +0900 Subject: [PATCH] =?UTF-8?q?=E7=AE=A1=E7=90=86=E7=94=BB=E9=9D=A2=E3=81=A7?= =?UTF-8?q?=E3=83=A6=E3=83=BC=E3=82=B6=E3=83=BC=E3=82=92=E7=8A=B6=E6=85=8B?= =?UTF-8?q?=E3=81=A7=E3=83=95=E3=82=A3=E3=83=AB=E3=82=BF=E3=81=A7=E3=81=8D?= =?UTF-8?q?=E3=82=8B=E3=82=88=E3=81=86=E3=81=AB=20(#3873)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- locales/ja-JP.yml | 8 ++ src/client/app/admin/views/users.vue | 39 +++++- src/server/api/endpoints/admin/show-users.ts | 123 +++++++++++++++++++ 3 files changed, 168 insertions(+), 2 deletions(-) create mode 100644 src/server/api/endpoints/admin/show-users.ts diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 814b08827b..c91548d78a 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1255,6 +1255,14 @@ admin/views/users.vue: createdAtDesc: "登録日時が新しい順" updatedAtAsc: "更新日時が古い順" updatedAtDesc: "更新日時が新しい順" + state: + title: "状態" + all: "すべて" + admin: "管理者" + moderator: "モデレーター" + adminOrModerator: "管理者+モデレーター" + verified: "公式アカウント" + suspended: "凍結済み" origin: title: "オリジン" combined: "ローカル+リモート" diff --git a/src/client/app/admin/views/users.vue b/src/client/app/admin/views/users.vue index 21d41efba8..dcacdd5bad 100644 --- a/src/client/app/admin/views/users.vue +++ b/src/client/app/admin/views/users.vue @@ -31,6 +31,14 @@ + + {{ $t('users.state.title') }} + + + + + + {{ $t('users.origin.title') }} @@ -39,7 +47,7 @@ -
+
@@ -49,6 +57,10 @@
@{{ user | acct }} + admin + moderator + +
{{ $t('users.updatedAt') }}: @@ -84,6 +96,7 @@ export default Vue.extend({ suspending: false, unsuspending: false, sort: '+createdAt', + state: 'all', origin: 'combined', limit: 10, offset: 0, @@ -100,6 +113,12 @@ export default Vue.extend({ this.fetchUsers(); }, + state() { + this.users = []; + this.offset = 0; + this.fetchUsers(); + }, + origin() { this.users = []; this.offset = 0; @@ -236,7 +255,8 @@ export default Vue.extend({ }, fetchUsers() { - this.$root.api('users', { + this.$root.api('admin/show-users', { + state: this.state, origin: this.origin, sort: this.sort, offset: this.offset, @@ -284,4 +304,19 @@ export default Vue.extend({ margin-left 8px opacity 0.7 + > .is-admin + > .is-moderator + flex-shrink 0 + align-self center + margin 0 0 0 .5em + padding 1px 6px + font-size 80% + border-radius 3px + background var(--noteHeaderAdminBg) + color var(--noteHeaderAdminFg) + + > .is-verified + > .is-suspended + margin 0 0 0 .5em + color #4dabf7 diff --git a/src/server/api/endpoints/admin/show-users.ts b/src/server/api/endpoints/admin/show-users.ts new file mode 100644 index 0000000000..20ccfbd7f3 --- /dev/null +++ b/src/server/api/endpoints/admin/show-users.ts @@ -0,0 +1,123 @@ +import $ from 'cafy'; +import User, { pack } from '../../../../models/user'; +import define from '../../define'; + +export const meta = { + requireCredential: true, + requireModerator: true, + + params: { + limit: { + validator: $.num.optional.range(1, 100), + default: 10 + }, + + offset: { + validator: $.num.optional.min(0), + default: 0 + }, + + sort: { + validator: $.str.optional.or([ + '+follower', + '-follower', + '+createdAt', + '-createdAt', + '+updatedAt', + '-updatedAt', + ]), + }, + + state: { + validator: $.str.optional.or([ + 'all', + 'admin', + 'moderator', + 'adminOrModerator', + 'verified', + 'suspended', + ]), + default: 'all' + }, + + origin: { + validator: $.str.optional.or([ + 'combined', + 'local', + 'remote', + ]), + default: 'local' + } + } +}; + +export default define(meta, (ps, me) => new Promise(async (res, rej) => { + let _sort; + if (ps.sort) { + if (ps.sort == '+follower') { + _sort = { + followersCount: -1 + }; + } else if (ps.sort == '-follower') { + _sort = { + followersCount: 1 + }; + } else if (ps.sort == '+createdAt') { + _sort = { + createdAt: -1 + }; + } else if (ps.sort == '+updatedAt') { + _sort = { + updatedAt: -1 + }; + } else if (ps.sort == '-createdAt') { + _sort = { + createdAt: 1 + }; + } else if (ps.sort == '-updatedAt') { + _sort = { + updatedAt: 1 + }; + } + } else { + _sort = { + _id: -1 + }; + } + + const q = { + $and: [] + } as any; + + // state + q.$and.push( + ps.state == 'admin' ? { isAdmin: true } : + ps.state == 'moderator' ? { isModerator: true } : + ps.state == 'adminOrModerator' ? { + $or: [{ + isAdmin: true + }, { + isModerator: true + }] + } : + ps.state == 'verified' ? { isVerified: true } : + ps.state == 'suspended' ? { isSuspended: true } : + {} + ); + + // origin + q.$and.push( + ps.origin == 'local' ? { host: null } : + ps.origin == 'remote' ? { host: { $ne: null } } : + {} + ); + + const users = await User + .find(q, { + limit: ps.limit, + sort: _sort, + skip: ps.offset + }); + + res(await Promise.all(users.map(user => pack(user, me, { detail: true })))); +}));