parent
b3fc4dc00f
commit
00b134ce1e
7 changed files with 154 additions and 3 deletions
|
@ -1274,6 +1274,8 @@ admin/views/users.vue:
|
||||||
unsuspend: "凍結の解除"
|
unsuspend: "凍結の解除"
|
||||||
unsuspend-confirm: "凍結を解除しますか?"
|
unsuspend-confirm: "凍結を解除しますか?"
|
||||||
unsuspended: "凍結を解除しました"
|
unsuspended: "凍結を解除しました"
|
||||||
|
make-silence: "サイレンス"
|
||||||
|
unmake-silence: "サイレンスの解除"
|
||||||
verify: "公式アカウントにする"
|
verify: "公式アカウントにする"
|
||||||
verify-confirm: "公式アカウントにしますか?"
|
verify-confirm: "公式アカウントにしますか?"
|
||||||
verified: "公式アカウントにしました"
|
verified: "公式アカウントにしました"
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
<span class="is-admin" v-if="user.isAdmin">admin</span>
|
<span class="is-admin" v-if="user.isAdmin">admin</span>
|
||||||
<span class="is-moderator" v-if="user.isModerator">moderator</span>
|
<span class="is-moderator" v-if="user.isModerator">moderator</span>
|
||||||
<span class="is-verified" v-if="user.isVerified" :title="$t('@.verified-user')"><fa icon="star"/></span>
|
<span class="is-verified" v-if="user.isVerified" :title="$t('@.verified-user')"><fa icon="star"/></span>
|
||||||
|
<span class="is-silenced" v-if="user.isSilenced" :title="$t('@.silenced-user')"><fa :icon="faMicrophoneSlash"/></span>
|
||||||
<span class="is-suspended" v-if="user.isSuspended" :title="$t('@.suspended-user')"><fa :icon="faSnowflake"/></span>
|
<span class="is-suspended" v-if="user.isSuspended" :title="$t('@.suspended-user')"><fa :icon="faSnowflake"/></span>
|
||||||
</header>
|
</header>
|
||||||
<div>
|
<div>
|
||||||
|
@ -27,6 +28,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
|
import { faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faSnowflake } from '@fortawesome/free-regular-svg-icons';
|
import { faSnowflake } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
|
||||||
export default Vue.extend({
|
export default Vue.extend({
|
||||||
|
@ -34,7 +36,7 @@ export default Vue.extend({
|
||||||
props: ['user'],
|
props: ['user'],
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
faSnowflake
|
faSnowflake, faMicrophoneSlash
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
@ -76,6 +78,7 @@ export default Vue.extend({
|
||||||
color var(--noteHeaderAdminFg)
|
color var(--noteHeaderAdminFg)
|
||||||
|
|
||||||
> .is-verified
|
> .is-verified
|
||||||
|
> .is-silenced
|
||||||
> .is-suspended
|
> .is-suspended
|
||||||
margin 0 0 0 .5em
|
margin 0 0 0 .5em
|
||||||
color #4dabf7
|
color #4dabf7
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
<ui-button @click="verifyUser" :disabled="verifying"><fa :icon="faCertificate"/> {{ $t('verify') }}</ui-button>
|
<ui-button @click="verifyUser" :disabled="verifying"><fa :icon="faCertificate"/> {{ $t('verify') }}</ui-button>
|
||||||
<ui-button @click="unverifyUser" :disabled="unverifying">{{ $t('unverify') }}</ui-button>
|
<ui-button @click="unverifyUser" :disabled="unverifying">{{ $t('unverify') }}</ui-button>
|
||||||
</ui-horizon-group>
|
</ui-horizon-group>
|
||||||
|
<ui-horizon-group>
|
||||||
|
<ui-button @click="silenceUser"><fa :icon="faMicrophoneSlash"/> {{ $t('make-silence') }}</ui-button>
|
||||||
|
<ui-button @click="unsilenceUser">{{ $t('unmake-silence') }}</ui-button>
|
||||||
|
</ui-horizon-group>
|
||||||
<ui-horizon-group>
|
<ui-horizon-group>
|
||||||
<ui-button @click="suspendUser" :disabled="suspending"><fa :icon="faSnowflake"/> {{ $t('suspend') }}</ui-button>
|
<ui-button @click="suspendUser" :disabled="suspending"><fa :icon="faSnowflake"/> {{ $t('suspend') }}</ui-button>
|
||||||
<ui-button @click="unsuspendUser" :disabled="unsuspending">{{ $t('unsuspend') }}</ui-button>
|
<ui-button @click="unsuspendUser" :disabled="unsuspending">{{ $t('unsuspend') }}</ui-button>
|
||||||
|
@ -66,7 +70,7 @@
|
||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import i18n from '../../i18n';
|
import i18n from '../../i18n';
|
||||||
import parseAcct from "../../../../misc/acct/parse";
|
import parseAcct from "../../../../misc/acct/parse";
|
||||||
import { faCertificate, faUsers, faTerminal, faSearch, faKey, faSync } from '@fortawesome/free-solid-svg-icons';
|
import { faCertificate, faUsers, faTerminal, faSearch, faKey, faSync, faMicrophoneSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faSnowflake } from '@fortawesome/free-regular-svg-icons';
|
import { faSnowflake } from '@fortawesome/free-regular-svg-icons';
|
||||||
import XUser from './users.user.vue';
|
import XUser from './users.user.vue';
|
||||||
|
|
||||||
|
@ -90,7 +94,7 @@ export default Vue.extend({
|
||||||
offset: 0,
|
offset: 0,
|
||||||
users: [],
|
users: [],
|
||||||
existMore: false,
|
existMore: false,
|
||||||
faTerminal, faCertificate, faUsers, faSnowflake, faSearch, faKey, faSync
|
faTerminal, faCertificate, faUsers, faSnowflake, faSearch, faKey, faSync, faMicrophoneSlash
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -216,6 +220,44 @@ export default Vue.extend({
|
||||||
this.refreshUser();
|
this.refreshUser();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
async silenceUser() {
|
||||||
|
const process = async () => {
|
||||||
|
await this.$root.api('admin/silence-user', { userId: this.user._id });
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
splash: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
await process().catch(e => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refreshUser();
|
||||||
|
},
|
||||||
|
|
||||||
|
async unsilenceUser() {
|
||||||
|
const process = async () => {
|
||||||
|
await this.$root.api('admin/unsilence-user', { userId: this.user._id });
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'success',
|
||||||
|
splash: true
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
await process().catch(e => {
|
||||||
|
this.$root.dialog({
|
||||||
|
type: 'error',
|
||||||
|
text: e.toString()
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.refreshUser();
|
||||||
|
},
|
||||||
|
|
||||||
async suspendUser() {
|
async suspendUser() {
|
||||||
if (!await this.getConfirmed(this.$t('suspend-confirm'))) return;
|
if (!await this.getConfirmed(this.$t('suspend-confirm'))) return;
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,11 @@ type IUserBase = {
|
||||||
*/
|
*/
|
||||||
isSuspended: boolean;
|
isSuspended: boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* サイレンスされているか否か
|
||||||
|
*/
|
||||||
|
isSilenced: boolean;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 鍵アカウントか否か
|
* 鍵アカウントか否か
|
||||||
*/
|
*/
|
||||||
|
|
49
src/server/api/endpoints/admin/silence-user.ts
Normal file
49
src/server/api/endpoints/admin/silence-user.ts
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
|
import define from '../../define';
|
||||||
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定したユーザーをサイレンスにします。',
|
||||||
|
'en-US': 'Make silence a user.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: true,
|
||||||
|
requireModerator: true,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '対象のユーザーID',
|
||||||
|
'en-US': 'The user ID which you want to make silence'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default define(meta, (ps) => new Promise(async (res, rej) => {
|
||||||
|
const user = await User.findOne({
|
||||||
|
_id: ps.userId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return rej('user not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (user.isAdmin) {
|
||||||
|
return rej('cannot silence admin');
|
||||||
|
}
|
||||||
|
|
||||||
|
await User.findOneAndUpdate({
|
||||||
|
_id: user._id
|
||||||
|
}, {
|
||||||
|
$set: {
|
||||||
|
isSilenced: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res();
|
||||||
|
}));
|
45
src/server/api/endpoints/admin/unsilence-user.ts
Normal file
45
src/server/api/endpoints/admin/unsilence-user.ts
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
import $ from 'cafy';
|
||||||
|
import ID, { transform } from '../../../../misc/cafy-id';
|
||||||
|
import define from '../../define';
|
||||||
|
import User from '../../../../models/user';
|
||||||
|
|
||||||
|
export const meta = {
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '指定したユーザーのサイレンスを解除します。',
|
||||||
|
'en-US': 'Unsilence a user.'
|
||||||
|
},
|
||||||
|
|
||||||
|
requireCredential: true,
|
||||||
|
requireModerator: true,
|
||||||
|
|
||||||
|
params: {
|
||||||
|
userId: {
|
||||||
|
validator: $.type(ID),
|
||||||
|
transform: transform,
|
||||||
|
desc: {
|
||||||
|
'ja-JP': '対象のユーザーID',
|
||||||
|
'en-US': 'The user ID which you want to unsilence'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default define(meta, (ps) => new Promise(async (res, rej) => {
|
||||||
|
const user = await User.findOne({
|
||||||
|
_id: ps.userId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (user == null) {
|
||||||
|
return rej('user not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await User.findOneAndUpdate({
|
||||||
|
_id: user._id
|
||||||
|
}, {
|
||||||
|
$set: {
|
||||||
|
isSilenced: false
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
res();
|
||||||
|
}));
|
|
@ -116,6 +116,11 @@ export default async (user: IUser, data: Option, silent = false) => new Promise<
|
||||||
if (data.viaMobile == null) data.viaMobile = false;
|
if (data.viaMobile == null) data.viaMobile = false;
|
||||||
if (data.localOnly == null) data.localOnly = false;
|
if (data.localOnly == null) data.localOnly = false;
|
||||||
|
|
||||||
|
// サイレンス
|
||||||
|
if (user.isSilenced && data.visibility == 'public') {
|
||||||
|
data.visibility = 'home';
|
||||||
|
}
|
||||||
|
|
||||||
if (data.visibleUsers) {
|
if (data.visibleUsers) {
|
||||||
data.visibleUsers = erase(null, data.visibleUsers);
|
data.visibleUsers = erase(null, data.visibleUsers);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue