Seemed to fix old stuff but breaks initilizing an instance? Idk whats going on
Some checks are pending
API report (misskey.js) / report (push) Waiting to run
Some checks are pending
API report (misskey.js) / report (push) Waiting to run
This commit is contained in:
parent
49650a1382
commit
1224033142
18 changed files with 325 additions and 49 deletions
|
@ -148,6 +148,7 @@ unsuspend: "Unsuspend"
|
|||
blockConfirm: "Are you sure that you want to block this account?"
|
||||
unblockConfirm: "Are you sure that you want to unblock this account?"
|
||||
suspendConfirm: "Are you sure that you want to suspend this account?"
|
||||
approveConfirm: "Are you sure that you want to approve this account?"
|
||||
unsuspendConfirm: "Are you sure that you want to unsuspend this account?"
|
||||
selectList: "Select a list"
|
||||
editList: "Edit list"
|
||||
|
@ -904,6 +905,7 @@ itsOff: "Disabled"
|
|||
on: "On"
|
||||
off: "Off"
|
||||
emailRequiredForSignup: "Require email address for sign-up"
|
||||
approvalRequiredForSignup: "Require approval for new users"
|
||||
unread: "Unread"
|
||||
filter: "Filter"
|
||||
controlPanel: "Control Panel"
|
||||
|
@ -964,6 +966,11 @@ requireAdminForView: "You must log in with an administrator account to view this
|
|||
isSystemAccount: "An account created and automatically operated by the system."
|
||||
typeToConfirm: "Please enter {x} to confirm"
|
||||
deleteAccount: "Delete account"
|
||||
approveAccount: "Approve"
|
||||
denyAccount: "Deny & Delete"
|
||||
approved: "Approved"
|
||||
notApproved: "Not Approved"
|
||||
approvalStatus: "Approval Status"
|
||||
document: "Documentation"
|
||||
numberOfPageCache: "Number of cached pages"
|
||||
numberOfPageCacheDescription: "Increasing this number will improve convenience for but cause more load as more memory usage on the user's device."
|
||||
|
@ -1056,6 +1063,7 @@ disableFederationConfirm: "Really disable federation?"
|
|||
disableFederationConfirmWarn: "Even if defederated, posts will continue to be public unless set otherwise. You usually do not need to do this."
|
||||
disableFederationOk: "Disable"
|
||||
invitationRequiredToRegister: "This instance is invite-only. You must enter a valid invite code sign up."
|
||||
approvalRequiredToRegister: "This instance is only accepting users who specify a reason for registration."
|
||||
emailNotSupported: "This instance does not support sending emails"
|
||||
postToTheChannel: "Post to channel"
|
||||
cannotBeChangedLater: "This cannot be changed later."
|
||||
|
@ -1864,6 +1872,8 @@ _signup:
|
|||
almostThere: "Almost there"
|
||||
emailAddressInfo: "Please enter your email address. It will not be made public."
|
||||
emailSent: "A confirmation email has been sent to your email address ({email}). Please click the included link to complete account creation."
|
||||
approvalPending: "Your account has been created and is awaiting approval."
|
||||
reasonInfo: "Please enter a reason as to why you want to join the instance."
|
||||
_accountDelete:
|
||||
accountDelete: "Delete account"
|
||||
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."
|
||||
|
|
40
locales/index.d.ts
vendored
40
locales/index.d.ts
vendored
|
@ -620,6 +620,10 @@ export interface Locale extends ILocale {
|
|||
* 凍結しますか?
|
||||
*/
|
||||
"suspendConfirm": string;
|
||||
/**
|
||||
* このアカウントを承認してもよろしいですか?
|
||||
*/
|
||||
"approveConfirm": string;
|
||||
/**
|
||||
* 解凍しますか?
|
||||
*/
|
||||
|
@ -3640,6 +3644,10 @@ export interface Locale extends ILocale {
|
|||
* アカウント登録にメールアドレスを必須にする
|
||||
*/
|
||||
"emailRequiredForSignup": string;
|
||||
/**
|
||||
* 新規ユーザーの承認が必要
|
||||
*/
|
||||
"approvalRequiredForSignup": string;
|
||||
/**
|
||||
* 未読
|
||||
*/
|
||||
|
@ -3883,6 +3891,26 @@ export interface Locale extends ILocale {
|
|||
* アカウント削除
|
||||
*/
|
||||
"deleteAccount": string;
|
||||
/**
|
||||
* 承認する
|
||||
*/
|
||||
"approveAccount": string;
|
||||
/**
|
||||
* 拒否と削除
|
||||
*/
|
||||
"denyAccount": string;
|
||||
/**
|
||||
* 承認済み
|
||||
*/
|
||||
"approved": string;
|
||||
/**
|
||||
* 承認されていない
|
||||
*/
|
||||
"notApproved": string;
|
||||
/**
|
||||
* 承認状況
|
||||
*/
|
||||
"approvalStatus": string;
|
||||
/**
|
||||
* ドキュメント
|
||||
*/
|
||||
|
@ -4251,6 +4279,10 @@ export interface Locale extends ILocale {
|
|||
* 現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。
|
||||
*/
|
||||
"invitationRequiredToRegister": string;
|
||||
/**
|
||||
* このインスタンスは、登録理由を指定したユーザーのみを受け入れています。
|
||||
*/
|
||||
"approvalRequiredToRegister": string;
|
||||
/**
|
||||
* このサーバーではメール配信はサポートされていません
|
||||
*/
|
||||
|
@ -7290,6 +7322,14 @@ export interface Locale extends ILocale {
|
|||
* 入力されたメールアドレス({email})宛に確認のメールが送信されました。メールに記載されたリンクにアクセスすると、アカウントの作成が完了します。メールに記載されているリンクの有効期限は30分です。
|
||||
*/
|
||||
"emailSent": ParameterizedString<"email">;
|
||||
/**
|
||||
* アカウントが作成され、承認待ちの状態です。
|
||||
*/
|
||||
"approvalPending": string;
|
||||
/**
|
||||
* インスタンスに参加したい理由を入力してください。
|
||||
*/
|
||||
"reasonInfo": string;
|
||||
};
|
||||
"_accountDelete": {
|
||||
/**
|
||||
|
|
|
@ -151,6 +151,7 @@ unsuspend: "解凍"
|
|||
blockConfirm: "ブロックしますか?"
|
||||
unblockConfirm: "ブロック解除しますか?"
|
||||
suspendConfirm: "凍結しますか?"
|
||||
approveConfirm: "このアカウントを承認してもよろしいですか?"
|
||||
unsuspendConfirm: "解凍しますか?"
|
||||
selectList: "リストを選択"
|
||||
editList: "リストを編集"
|
||||
|
@ -906,6 +907,7 @@ itsOff: "オフになっています"
|
|||
on: "オン"
|
||||
off: "オフ"
|
||||
emailRequiredForSignup: "アカウント登録にメールアドレスを必須にする"
|
||||
approvalRequiredForSignup: "新規ユーザーの承認が必要"
|
||||
unread: "未読"
|
||||
filter: "フィルタ"
|
||||
controlPanel: "コントロールパネル"
|
||||
|
@ -966,6 +968,11 @@ requireAdminForView: "閲覧するには管理者アカウントでログイン
|
|||
isSystemAccount: "システムにより自動で作成・管理されているアカウントです。"
|
||||
typeToConfirm: "この操作を行うには {x} と入力してください"
|
||||
deleteAccount: "アカウント削除"
|
||||
approveAccount: "承認する"
|
||||
denyAccount: "拒否と削除"
|
||||
approved: "承認済み"
|
||||
notApproved: "承認されていない"
|
||||
approvalStatus: "承認状況"
|
||||
document: "ドキュメント"
|
||||
numberOfPageCache: "ページキャッシュ数"
|
||||
numberOfPageCacheDescription: "多くすると利便性が向上しますが、負荷とメモリ使用量が増えます。"
|
||||
|
@ -1058,6 +1065,7 @@ disableFederationConfirm: "連合なしにしますか?"
|
|||
disableFederationConfirmWarn: "連合なしにしても投稿は非公開になりません。ほとんどの場合、連合なしにする必要はありません。"
|
||||
disableFederationOk: "連合なしにする"
|
||||
invitationRequiredToRegister: "現在このサーバーは招待制です。招待コードをお持ちの方のみ登録できます。"
|
||||
approvalRequiredToRegister: "このインスタンスは、登録理由を指定したユーザーのみを受け入れています。"
|
||||
emailNotSupported: "このサーバーではメール配信はサポートされていません"
|
||||
postToTheChannel: "チャンネルに投稿"
|
||||
cannotBeChangedLater: "後から変更できません。"
|
||||
|
@ -1882,6 +1890,8 @@ _signup:
|
|||
almostThere: "ほとんど完了です"
|
||||
emailAddressInfo: "あなたが使っているメールアドレスを入力してください。メールアドレスが公開されることはありません。"
|
||||
emailSent: "入力されたメールアドレス({email})宛に確認のメールが送信されました。メールに記載されたリンクにアクセスすると、アカウントの作成が完了します。メールに記載されているリンクの有効期限は30分です。"
|
||||
approvalPending: "アカウントが作成され、承認待ちの状態です。"
|
||||
reasonInfo: "インスタンスに参加したい理由を入力してください。"
|
||||
|
||||
_accountDelete:
|
||||
accountDelete: "アカウントの削除"
|
||||
|
|
|
@ -706,8 +706,6 @@ export class UserEntityService implements OnModuleInit {
|
|||
}
|
||||
}
|
||||
|
||||
return (await Promise.allSettled(_users.map(u => this.pack(u, me, { ...options, userProfile: profilesMap.get(u.id), userRelations: userRelations, userMemos: userMemos, pinNotes: pinNotes }))))
|
||||
.filter(result => result.status === 'fulfilled')
|
||||
.map(result => (result as PromiseFulfilledResult<Packed<S>>).value);
|
||||
return (await Promise.allSettled(_users.map(u => this.pack(u, me, { ...options, userProfile: profilesMap?.get(u.id), userRelations: userRelations, userMemos: userMemos, pinNotes: pinNotes }))))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,22 +242,19 @@ export class SignupApiService {
|
|||
reply.code(204);
|
||||
return;
|
||||
} else {
|
||||
if (instance.approvalRequiredForSignup) {
|
||||
await this.signupService.signup({
|
||||
username, password, host, reason,
|
||||
});
|
||||
|
||||
if (emailAddress) {
|
||||
this.emailService.sendEmail(emailAddress, 'Approval pending',
|
||||
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.',
|
||||
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.');
|
||||
}
|
||||
}
|
||||
try {
|
||||
const { account, secret } = await this.signupService.signup({
|
||||
username, password, host,
|
||||
username, password, host, reason
|
||||
});
|
||||
|
||||
if (instance.approvalRequiredForSignup) {
|
||||
if (emailAddress) {
|
||||
this.emailService.sendEmail(emailAddress, 'Approval pending',
|
||||
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.',
|
||||
'Congratulations! Your account is now pending approval. You will get notified when you have been accepted.');
|
||||
}
|
||||
}
|
||||
|
||||
const res = await this.userEntityService.pack(account, account, {
|
||||
schema: 'MeDetailed',
|
||||
includeSecrets: true,
|
||||
|
|
|
@ -45,6 +45,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-else-if="emailState === 'error'" style="color: var(--error)"><i class="ti ti-alert-triangle ti-fw"></i> {{ i18n.ts.error }}</span>
|
||||
</template>
|
||||
</MkInput>
|
||||
<MkInput v-if="instance.approvalRequiredForSignup" v-model="reason" type="text" :spellcheck="false" required data-cy-signup-reason>
|
||||
<template #label>Reason <div v-tooltip:dialog="i18n.ts._signup.reasonInfo" class="_button _help"><i class="ph-question ph-bold ph-lg"></i></div></template>
|
||||
<template #prefix><i class="ti ti-comment-alt"></i></template>
|
||||
</MkInput>
|
||||
<MkNewPassword ref="password" :label="i18n.ts.password"/>
|
||||
<MkCaptcha v-if="instance.enableHcaptcha" ref="hcaptcha" v-model="hCaptchaResponse" :class="$style.captcha" provider="hcaptcha" :sitekey="instance.hcaptchaSiteKey"/>
|
||||
<MkCaptcha v-if="instance.enableMcaptcha" ref="mcaptcha" v-model="mCaptchaResponse" :class="$style.captcha" provider="mcaptcha" :sitekey="instance.mcaptchaSiteKey" :instanceUrl="instance.mcaptchaInstanceUrl"/>
|
||||
|
@ -85,6 +89,7 @@ const props = withDefaults(defineProps<{
|
|||
const emit = defineEmits<{
|
||||
(ev: 'signup', user: Misskey.entities.SigninResponse): void;
|
||||
(ev: 'signupEmailPending'): void;
|
||||
(ev: 'approvalPending'): void;
|
||||
}>();
|
||||
|
||||
const host = toUnicode(config.host);
|
||||
|
@ -97,6 +102,7 @@ const turnstile = ref<Captcha | undefined>();
|
|||
const username = ref<string>('');
|
||||
const password = shallowRef<InstanceType<typeof MkNewPassword> | null>(null);
|
||||
const invitationCode = ref<string>('');
|
||||
let reason = ref<string>('');
|
||||
const email = ref('');
|
||||
const usernameState = ref<null | 'wait' | 'ok' | 'unavailable' | 'error' | 'invalid-format' | 'min-range' | 'max-range'>(null);
|
||||
const emailState = ref<null | 'wait' | 'ok' | 'unavailable:used' | 'unavailable:format' | 'unavailable:disposable' | 'unavailable:banned' | 'unavailable:mx' | 'unavailable:smtp' | 'unavailable' | 'error'>(null);
|
||||
|
@ -195,6 +201,7 @@ async function onSubmit(): Promise<void> {
|
|||
password: password.value.password,
|
||||
emailAddress: email.value,
|
||||
invitationCode: invitationCode.value,
|
||||
reason: reason.value,
|
||||
'hcaptcha-response': hCaptchaResponse.value,
|
||||
'm-captcha-response': mCaptchaResponse.value,
|
||||
'g-recaptcha-response': reCaptchaResponse.value,
|
||||
|
@ -207,6 +214,13 @@ async function onSubmit(): Promise<void> {
|
|||
text: i18n.tsx._signup.emailSent({ email: email.value }),
|
||||
});
|
||||
emit('signupEmailPending');
|
||||
} else if (instance.approvalRequiredForSignup) {
|
||||
os.alert({
|
||||
type: 'success',
|
||||
title: i18n.ts._signup.almostThere,
|
||||
text: i18n.ts._signup.approvalPending,
|
||||
});
|
||||
emit('approvalPending');
|
||||
} else {
|
||||
emit('signup', { id: res.id, i: res.token });
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<XServerRules @done="isAcceptedServerRule = true" @cancel="onClose"/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<XSignup :autoSet="autoSet" @signup="onSignup" @signupEmailPending="onSignupEmailPending"/>
|
||||
<XSignup :autoSet="autoSet" @signup="onSignup" @signupEmailPending="onSignupEmailPending" @approvalPending="onApprovalPending"/>
|
||||
</template>
|
||||
</Transition>
|
||||
</div>
|
||||
|
@ -69,6 +69,10 @@ function onSignup(res: Misskey.entities.SignupResponse) {
|
|||
function onSignupEmailPending() {
|
||||
dialog.value?.close();
|
||||
}
|
||||
|
||||
function onApprovalPending() {
|
||||
dialog.value?.close();
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" module>
|
||||
|
|
|
@ -22,6 +22,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div v-if="instance.disableRegistration" :class="$style.mainWarn">
|
||||
<MkInfo warn>{{ i18n.ts.invitationRequiredToRegister }}</MkInfo>
|
||||
</div>
|
||||
<div v-if="instance.approvalRequiredForSignup" :class="$style.mainWarn">
|
||||
<MkInfo warn>{{ i18n.ts.approvalRequiredToRegister }}</MkInfo>
|
||||
</div>
|
||||
<div class="_gaps_s" :class="$style.mainActions">
|
||||
<MkButton :class="$style.mainAction" full rounded gradate data-cy-signup style="margin-right: 12px;" @click="signup()">{{ i18n.ts.joinThisServer }}</MkButton>
|
||||
<MkButton :class="$style.mainAction" full rounded @click="exploreOtherServers()">{{ i18n.ts.exploreOtherServers }}</MkButton>
|
||||
|
|
|
@ -15,6 +15,8 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span class="name"><MkUserName class="name" :user="user"/></span>
|
||||
<span class="sub"><span class="acct _monospace">@{{ acct(user) }}</span></span>
|
||||
<span class="state">
|
||||
<span v-if="!approved" class="silenced">{{ i18n.ts.notApproved }}</span>
|
||||
<span v-if="approved" class="moderator">{{ i18n.ts.approved }}</span>
|
||||
<span v-if="admin" class="admin">Admin</span>
|
||||
<span v-if="moderator" class="moderator">Moderator</span>
|
||||
<span v-if="silenced" class="silenced">Silenced</span>
|
||||
|
@ -219,6 +221,20 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<MkObjectView tall :value="user">
|
||||
</MkObjectView>
|
||||
</div>
|
||||
|
||||
<div v-else-if="tab === 'approval'" class="_gaps_m">
|
||||
<MkKeyValue oneline>
|
||||
<template #key>{{ i18n.ts.approvalStatus }}</template>
|
||||
<template #value><span class="_monospace">{{ approved ? i18n.ts.approved : i18n.ts.notApproved }}</span></template>
|
||||
</MkKeyValue>
|
||||
|
||||
<MkTextarea v-model="signupReason" readonly>
|
||||
<template #label>Reason</template>
|
||||
</MkTextarea>
|
||||
|
||||
<MkButton v-if="$i.isAdmin" inline success @click="approveAccount">{{ i18n.ts.approveAccount }}</MkButton>
|
||||
<MkButton v-if="$i.isAdmin" inline danger @click="deleteAccount">{{ i18n.ts.denyAccount }}</MkButton>
|
||||
</div>
|
||||
</FormSuspense>
|
||||
</MkSpacer>
|
||||
</MkStickyContainer>
|
||||
|
@ -267,10 +283,13 @@ const ap = ref<any>(null);
|
|||
const admin = ref(false);
|
||||
const moderator = ref(false);
|
||||
const silenced = ref(false);
|
||||
const approved = ref(false);
|
||||
const limited = ref(false);
|
||||
const suspended = ref(false);
|
||||
const deleted = ref(false);
|
||||
const moderationNote = ref('');
|
||||
const signupReason = ref('');
|
||||
|
||||
const filesPagination = {
|
||||
endpoint: 'admin/drive/files' as const,
|
||||
limit: 10,
|
||||
|
@ -303,10 +322,12 @@ function createFetcher() {
|
|||
admin.value = info.value.isAdmin;
|
||||
moderator.value = info.value.isModerator;
|
||||
silenced.value = info.value.isSilenced;
|
||||
approved.value = info.value.approved;
|
||||
limited.value = info.value.isLimited;
|
||||
suspended.value = info.value.isSuspended;
|
||||
deleted.value = info.value.isDeleted;
|
||||
moderationNote.value = info.value.moderationNote;
|
||||
signupReason.value = info.value.signupReason;
|
||||
|
||||
watch(moderationNote, async () => {
|
||||
await misskeyApi('admin/update-user-note', {
|
||||
|
@ -470,6 +491,21 @@ async function deleteAccount(soft: boolean) {
|
|||
}
|
||||
}
|
||||
|
||||
async function approveAccount() {
|
||||
const confirm = await os.confirm({
|
||||
type: 'warning',
|
||||
text: i18n.ts.approveConfirm,
|
||||
});
|
||||
if (confirm.canceled) return;
|
||||
|
||||
await os.apiWithDialog('admin/approve-user', {
|
||||
type: 'warning',
|
||||
text: i18n.ts.approveConfirm,
|
||||
userId: user.value.id,
|
||||
});
|
||||
await refreshUser();
|
||||
}
|
||||
|
||||
async function assignRole() {
|
||||
const roles = await misskeyApi('admin/roles/list');
|
||||
|
||||
|
@ -573,35 +609,79 @@ watch(user, () => {
|
|||
|
||||
const headerActions = computed(() => []);
|
||||
|
||||
const headerTabs = computed(() => [{
|
||||
key: 'overview',
|
||||
title: i18n.ts.overview,
|
||||
icon: 'ti ti-info-circle',
|
||||
}, {
|
||||
key: 'roles',
|
||||
title: i18n.ts.roles,
|
||||
icon: 'ti ti-badges',
|
||||
}, {
|
||||
key: 'announcements',
|
||||
title: i18n.ts.announcements,
|
||||
icon: 'ti ti-speakerphone',
|
||||
}, {
|
||||
key: 'drive',
|
||||
title: i18n.ts.drive,
|
||||
icon: 'ti ti-cloud',
|
||||
}, {
|
||||
key: 'chart',
|
||||
title: i18n.ts.charts,
|
||||
icon: 'ti ti-chart-line',
|
||||
}, {
|
||||
key: 'activitypub',
|
||||
title: 'ActivityPub',
|
||||
icon: 'ti ti-share',
|
||||
}, {
|
||||
key: 'raw',
|
||||
title: 'Raw',
|
||||
icon: 'ti ti-code',
|
||||
}]);
|
||||
const headerTabs = computed(() => iAmAdmin && !approved.value ?
|
||||
[
|
||||
{
|
||||
key: 'overview',
|
||||
title: i18n.ts.overview,
|
||||
icon: 'ti ti-info-circle',
|
||||
},
|
||||
{
|
||||
key: 'roles',
|
||||
title: i18n.ts.roles,
|
||||
icon: 'ti ti-badges',
|
||||
},
|
||||
{
|
||||
key: 'announcements',
|
||||
title: i18n.ts.announcements,
|
||||
icon: 'ti ti-speakerphone',
|
||||
},
|
||||
{
|
||||
key: 'drive',
|
||||
title: i18n.ts.drive,
|
||||
icon: 'ti ti-cloud',
|
||||
},
|
||||
{
|
||||
key: 'chart',
|
||||
title: i18n.ts.charts,
|
||||
icon: 'ti ti-chart-line',
|
||||
},
|
||||
{
|
||||
key: 'activitypub',
|
||||
title: 'ActivityPub',
|
||||
icon: 'ti ti-share',
|
||||
},
|
||||
{
|
||||
key: 'raw',
|
||||
title: 'Raw',
|
||||
icon: 'ti ti-code',
|
||||
},
|
||||
{
|
||||
key: 'approval',
|
||||
title: 'Approval',
|
||||
icon: 'ph-eye ph-bold pg-lg',
|
||||
}
|
||||
] : [
|
||||
{
|
||||
key: 'overview',
|
||||
title: i18n.ts.overview,
|
||||
icon: 'ti ti-info-circle',
|
||||
}, {
|
||||
key: 'roles',
|
||||
title: i18n.ts.roles,
|
||||
icon: 'ti ti-badges',
|
||||
}, {
|
||||
key: 'announcements',
|
||||
title: i18n.ts.announcements,
|
||||
icon: 'ti ti-speakerphone',
|
||||
}, {
|
||||
key: 'drive',
|
||||
title: i18n.ts.drive,
|
||||
icon: 'ti ti-cloud',
|
||||
}, {
|
||||
key: 'chart',
|
||||
title: i18n.ts.charts,
|
||||
icon: 'ti ti-chart-line',
|
||||
}, {
|
||||
key: 'activitypub',
|
||||
title: 'ActivityPub',
|
||||
icon: 'ti ti-share',
|
||||
}, {
|
||||
key: 'raw',
|
||||
title: 'Raw',
|
||||
icon: 'ti ti-code',
|
||||
},
|
||||
]);
|
||||
|
||||
definePageMetadata(() => ({
|
||||
title: user.value ? acct(user.value) : i18n.ts.userInfo,
|
||||
|
@ -769,4 +849,16 @@ definePageMetadata(() => ({
|
|||
border-bottom: none;
|
||||
}
|
||||
}
|
||||
|
||||
.casdwq {
|
||||
.silenced {
|
||||
color: var(--warn);
|
||||
border-color: var(--warn);
|
||||
}
|
||||
|
||||
.moderator {
|
||||
color: var(--success);
|
||||
border-color: var(--success);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -18,6 +18,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts.emailRequiredForSignup }}</template>
|
||||
</MkSwitch>
|
||||
|
||||
<MkSwitch v-model="approvalRequiredForSignup">
|
||||
<template #label>{{ i18n.ts.approvalRequiredForSignup }}</template>
|
||||
</MkSwitch>
|
||||
|
||||
<FormLink to="/admin/server-rules">{{ i18n.ts.serverRules }}</FormLink>
|
||||
|
||||
<MkInput v-model="tosUrl" type="url">
|
||||
|
@ -90,6 +94,7 @@ import FormLink from '@/components/form/link.vue';
|
|||
|
||||
const enableRegistration = ref<boolean>(false);
|
||||
const emailRequiredForSignup = ref<boolean>(false);
|
||||
const approvalRequiredForSignup: boolean = ref<boolean>(false);
|
||||
const sensitiveWords = ref<string>('');
|
||||
const prohibitedWords = ref<string>('');
|
||||
const hiddenTags = ref<string>('');
|
||||
|
@ -103,6 +108,7 @@ async function init() {
|
|||
const meta = await misskeyApi('admin/meta');
|
||||
enableRegistration.value = !meta.disableRegistration;
|
||||
emailRequiredForSignup.value = meta.emailRequiredForSignup;
|
||||
approvalRequiredForSignup.value = meta.approvalRequiredForSignup;
|
||||
sensitiveWords.value = meta.sensitiveWords.join('\n');
|
||||
prohibitedWords.value = meta.prohibitedWords.join('\n');
|
||||
hiddenTags.value = meta.hiddenTags.join('\n');
|
||||
|
@ -117,6 +123,7 @@ function save() {
|
|||
os.apiWithDialog('admin/update-meta', {
|
||||
disableRegistration: !enableRegistration.value,
|
||||
emailRequiredForSignup: emailRequiredForSignup.value,
|
||||
approvalRequiredForSignup: approvalRequiredForSignup.value,
|
||||
tosUrl: tosUrl.value,
|
||||
privacyPolicyUrl: privacyPolicyUrl.value,
|
||||
sensitiveWords: sensitiveWords.value.split('\n'),
|
||||
|
|
|
@ -10,7 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
:class="{
|
||||
[$style.logGreen]: ['createRole', 'addCustomEmoji', 'createGlobalAnnouncement', 'createUserAnnouncement', 'createAd', 'createInvitation', 'createAvatarDecoration'].includes(log.type),
|
||||
[$style.logYellow]: ['markSensitiveDriveFile', 'resetPassword', 'regenerateUserToken', 'updateUserName', 'unsetUserAvatar', 'unsetUserBanner', 'unsetUserMutualLink'].includes(log.type),
|
||||
[$style.logRed]: ['suspend', 'deleteRole', 'suspendRemoteInstance', 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'deleteCustomEmoji', 'deleteNote', 'deleteDriveFile', 'deleteAd', 'deleteAvatarDecoration'].includes(log.type)
|
||||
[$style.logRed]: ['suspend', 'approve', 'deleteRole', 'suspendRemoteInstance', 'deleteGlobalAnnouncement', 'deleteUserAnnouncement', 'deleteCustomEmoji', 'deleteNote', 'deleteDriveFile', 'deleteAd', 'deleteAvatarDecoration'].includes(log.type)
|
||||
}"
|
||||
>{{ i18n.ts._moderationLogTypes[log.type] }}</b>
|
||||
<span v-if="log.type === 'updateUserNote'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
|
@ -19,6 +19,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<span v-else-if="log.type === 'unsetUserBanner'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'unsetUserMutualLink'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'suspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'approve'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'unsuspend'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'resetPassword'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
<span v-else-if="log.type === 'regenerateUserToken'">: @{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</span>
|
||||
|
@ -79,6 +80,9 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template v-else-if="log.type === 'suspend'">
|
||||
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||
</template>
|
||||
<template v-else-if="log.type === 'approve'">
|
||||
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||
</template>
|
||||
<template v-else-if="log.type === 'unsuspend'">
|
||||
<div>{{ i18n.ts.user }}: <MkA :to="`/admin/user/${log.info.userId}`" class="_link">@{{ log.info.userUsername }}{{ log.info.userHost ? '@' + log.info.userHost : '' }}</MkA></div>
|
||||
</template>
|
||||
|
|
|
@ -46,6 +46,13 @@ function submit() {
|
|||
misskeyApi('signup-pending', {
|
||||
code: props.code,
|
||||
}).then(res => {
|
||||
if (res.pendingApproval) {
|
||||
return os.alert({
|
||||
type: 'success',
|
||||
title: i18n.ts._signup.almostThere,
|
||||
text: i18n.ts._signup.approvalPending,
|
||||
});
|
||||
}
|
||||
return login(res.i, '/');
|
||||
}).catch(() => {
|
||||
submitting.value = false;
|
||||
|
|
|
@ -116,6 +116,9 @@ type AdminAnnouncementsListResponse = operations['admin___announcements___list']
|
|||
// @public (undocumented)
|
||||
type AdminAnnouncementsUpdateRequest = operations['admin___announcements___update']['requestBody']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type AdminApproveUserRequest = operations['admin___approve-user']['requestBody']['content']['application/json'];
|
||||
|
||||
// @public (undocumented)
|
||||
type AdminAvatarDecorationsCreateRequest = operations['admin___avatar-decorations___create']['requestBody']['content']['application/json'];
|
||||
|
||||
|
@ -1325,6 +1328,7 @@ declare namespace entities {
|
|||
AdminShowUsersRequest,
|
||||
AdminShowUsersResponse,
|
||||
AdminSuspendUserRequest,
|
||||
AdminApproveUserRequest,
|
||||
AdminUnsuspendUserRequest,
|
||||
AdminUpdateMetaRequest,
|
||||
AdminUpdateUserNameRequest,
|
||||
|
@ -2544,7 +2548,7 @@ type ModerationLog = {
|
|||
});
|
||||
|
||||
// @public (undocumented)
|
||||
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "unsuspend", "updateUserName", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "regenerateUserToken", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createIndieAuthClient", "updateIndieAuthClient", "deleteIndieAuthClient", "createSSOServiceProvider", "updateSSOServiceProvider", "deleteSSOServiceProvider", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "unsetUserMutualBanner"];
|
||||
export const moderationLogTypes: readonly ["updateServerSettings", "suspend", "approve", "unsuspend", "updateUserName", "updateUserNote", "addCustomEmoji", "updateCustomEmoji", "deleteCustomEmoji", "assignRole", "unassignRole", "createRole", "updateRole", "deleteRole", "clearQueue", "promoteQueue", "deleteDriveFile", "deleteNote", "createGlobalAnnouncement", "createUserAnnouncement", "updateGlobalAnnouncement", "updateUserAnnouncement", "deleteGlobalAnnouncement", "deleteUserAnnouncement", "resetPassword", "regenerateUserToken", "suspendRemoteInstance", "unsuspendRemoteInstance", "updateRemoteInstanceNote", "markSensitiveDriveFile", "unmarkSensitiveDriveFile", "resolveAbuseReport", "createInvitation", "createAd", "updateAd", "deleteAd", "createIndieAuthClient", "updateIndieAuthClient", "deleteIndieAuthClient", "createSSOServiceProvider", "updateSSOServiceProvider", "deleteSSOServiceProvider", "createAvatarDecoration", "updateAvatarDecoration", "deleteAvatarDecoration", "unsetUserAvatar", "unsetUserBanner", "unsetUserMutualBanner"];
|
||||
|
||||
// @public (undocumented)
|
||||
type MuteCreateRequest = operations['mute___create']['requestBody']['content']['application/json'];
|
||||
|
@ -2796,7 +2800,7 @@ type PagesUpdateRequest = operations['pages___update']['requestBody']['content']
|
|||
function parse(acct: string): Acct;
|
||||
|
||||
// @public (undocumented)
|
||||
export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "read:admin:abuse-report-resolvers", "write:admin:abuse-report-resolvers", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:regenerate-user-token", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-account-move-log", "read:admin:show-user", "read:admin:show-users", "write:admin:suspend-user", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-name", "write:admin:user-note", "write:admin:user-avatar", "write:admin:user-banner", "write:admin:user-mutual-link", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:indie-auth", "read:admin:indie-auth", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:sso", "read:admin:sso", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"];
|
||||
export const permissions: readonly ["read:account", "write:account", "read:blocks", "write:blocks", "read:drive", "write:drive", "read:favorites", "write:favorites", "read:following", "write:following", "read:messaging", "write:messaging", "read:mutes", "write:mutes", "write:notes", "read:notifications", "write:notifications", "read:reactions", "write:reactions", "write:votes", "read:pages", "write:pages", "write:page-likes", "read:page-likes", "read:user-groups", "write:user-groups", "read:channels", "write:channels", "read:gallery", "write:gallery", "read:gallery-likes", "write:gallery-likes", "read:flash", "write:flash", "read:flash-likes", "write:flash-likes", "read:admin:abuse-user-reports", "read:admin:abuse-report-resolvers", "write:admin:abuse-report-resolvers", "read:admin:index-stats", "read:admin:table-stats", "read:admin:user-ips", "read:admin:meta", "write:admin:reset-password", "write:admin:regenerate-user-token", "write:admin:resolve-abuse-user-report", "write:admin:send-email", "read:admin:server-info", "read:admin:show-moderation-log", "read:admin:show-account-move-log", "read:admin:show-user", "read:admin:show-users", "write:admin:suspend-user", "write:admin:approve-user", "write:admin:unsuspend-user", "write:admin:meta", "write:admin:user-name", "write:admin:user-note", "write:admin:user-avatar", "write:admin:user-banner", "write:admin:user-mutual-link", "write:admin:roles", "read:admin:roles", "write:admin:relays", "read:admin:relays", "write:admin:invite-codes", "read:admin:invite-codes", "write:admin:announcements", "read:admin:announcements", "write:admin:avatar-decorations", "read:admin:avatar-decorations", "write:admin:federation", "write:admin:indie-auth", "read:admin:indie-auth", "write:admin:account", "read:admin:account", "write:admin:emoji", "read:admin:emoji", "write:admin:queue", "read:admin:queue", "write:admin:promo", "write:admin:drive", "read:admin:drive", "write:admin:sso", "read:admin:sso", "write:admin:ad", "read:admin:ad", "write:invite-codes", "read:invite-codes", "write:clip-favorite", "read:clip-favorite", "read:federation", "write:report-abuse"];
|
||||
|
||||
// @public (undocumented)
|
||||
type PingResponse = operations['ping']['responses']['200']['content']['application/json'];
|
||||
|
|
|
@ -840,6 +840,17 @@ declare module '../api.js' {
|
|||
credential?: string | null,
|
||||
): Promise<SwitchCaseResponseType<E, P>>;
|
||||
|
||||
/**
|
||||
* No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:admin:approve-user*
|
||||
*/
|
||||
request<E extends 'admin/approve-user', P extends Endpoints[E]['req']>(
|
||||
endpoint: E,
|
||||
params: P,
|
||||
credential?: string | null,
|
||||
): Promise<SwitchCaseResponseType<E, P>>;
|
||||
|
||||
/**
|
||||
* No description provided.
|
||||
*
|
||||
|
|
|
@ -103,6 +103,7 @@ import type {
|
|||
AdminShowUsersRequest,
|
||||
AdminShowUsersResponse,
|
||||
AdminSuspendUserRequest,
|
||||
AdminApproveUserRequest,
|
||||
AdminUnsuspendUserRequest,
|
||||
AdminUpdateMetaRequest,
|
||||
AdminUpdateUserNameRequest,
|
||||
|
@ -667,6 +668,7 @@ export type Endpoints = {
|
|||
'admin/show-user': { req: AdminShowUserRequest; res: AdminShowUserResponse };
|
||||
'admin/show-users': { req: AdminShowUsersRequest; res: AdminShowUsersResponse };
|
||||
'admin/suspend-user': { req: AdminSuspendUserRequest; res: EmptyResponse };
|
||||
'admin/approve-user': { req: AdminApproveUserRequest; res: EmptyResponse };
|
||||
'admin/unsuspend-user': { req: AdminUnsuspendUserRequest; res: EmptyResponse };
|
||||
'admin/update-meta': { req: AdminUpdateMetaRequest; res: EmptyResponse };
|
||||
'admin/update-user-name': { req: AdminUpdateUserNameRequest; res: EmptyResponse };
|
||||
|
|
|
@ -106,6 +106,7 @@ export type AdminShowUserResponse = operations['admin___show-user']['responses']
|
|||
export type AdminShowUsersRequest = operations['admin___show-users']['requestBody']['content']['application/json'];
|
||||
export type AdminShowUsersResponse = operations['admin___show-users']['responses']['200']['content']['application/json'];
|
||||
export type AdminSuspendUserRequest = operations['admin___suspend-user']['requestBody']['content']['application/json'];
|
||||
export type AdminApproveUserRequest = operations['admin___approve-user']['requestBody']['content']['application/json'];
|
||||
export type AdminUnsuspendUserRequest = operations['admin___unsuspend-user']['requestBody']['content']['application/json'];
|
||||
export type AdminUpdateMetaRequest = operations['admin___update-meta']['requestBody']['content']['application/json'];
|
||||
export type AdminUpdateUserNameRequest = operations['admin___update-user-name']['requestBody']['content']['application/json'];
|
||||
|
|
|
@ -697,6 +697,15 @@ export type paths = {
|
|||
*/
|
||||
post: operations['admin___suspend-user'];
|
||||
};
|
||||
'/admin/approve-user': {
|
||||
/**
|
||||
* admin/approve-user
|
||||
* @description No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:admin:approve-user*
|
||||
*/
|
||||
post: operations['admin___approve-user'];
|
||||
};
|
||||
'/admin/unsuspend-user': {
|
||||
/**
|
||||
* admin/unsuspend-user
|
||||
|
@ -5111,6 +5120,7 @@ export type components = {
|
|||
defaultLightTheme: string | null;
|
||||
disableRegistration: boolean;
|
||||
emailRequiredForSignup: boolean;
|
||||
approvalRequiredForSignup: boolean;
|
||||
enableHcaptcha: boolean;
|
||||
hcaptchaSiteKey: string | null;
|
||||
enableMcaptcha: boolean;
|
||||
|
@ -5166,6 +5176,7 @@ export type components = {
|
|||
features?: {
|
||||
registration: boolean;
|
||||
emailRequiredForSignup: boolean;
|
||||
approvalRequiredForSignup: boolean;
|
||||
localTimeline: boolean;
|
||||
globalTimeline: boolean;
|
||||
hCaptcha: boolean;
|
||||
|
@ -5258,6 +5269,7 @@ export type operations = {
|
|||
cacheRemoteFiles: boolean;
|
||||
cacheRemoteSensitiveFiles: boolean;
|
||||
emailRequiredForSignup: boolean;
|
||||
approvalRequiredForSignup: boolean;
|
||||
enableHcaptcha: boolean;
|
||||
hcaptchaSiteKey: string | null;
|
||||
enableMcaptcha: boolean;
|
||||
|
@ -9887,7 +9899,7 @@ export type operations = {
|
|||
* @default all
|
||||
* @enum {string}
|
||||
*/
|
||||
state?: 'all' | 'alive' | 'available' | 'admin' | 'moderator' | 'adminOrModerator' | 'suspended';
|
||||
state?: 'all' | 'alive' | 'available' | 'admin' | 'moderator' | 'adminOrModerator' | 'suspended' | 'approved';
|
||||
/**
|
||||
* @default combined
|
||||
* @enum {string}
|
||||
|
@ -9994,6 +10006,58 @@ export type operations = {
|
|||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* admin/approve-user
|
||||
* @description No description provided.
|
||||
*
|
||||
* **Credential required**: *Yes* / **Permission**: *write:admin:approve-user*
|
||||
*/
|
||||
'admin___approve-user': {
|
||||
requestBody: {
|
||||
content: {
|
||||
'application/json': {
|
||||
/** Format: misskey:id */
|
||||
userId: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description OK (without any results) */
|
||||
204: {
|
||||
content: never;
|
||||
};
|
||||
/** @description Client error */
|
||||
400: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Authentication error */
|
||||
401: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Forbidden error */
|
||||
403: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description I'm Ai */
|
||||
418: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
/** @description Internal server error */
|
||||
500: {
|
||||
content: {
|
||||
'application/json': components['schemas']['Error'];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/**
|
||||
* admin/unsuspend-user
|
||||
* @description No description provided.
|
||||
|
@ -10081,6 +10145,7 @@ export type operations = {
|
|||
cacheRemoteFiles?: boolean;
|
||||
cacheRemoteSensitiveFiles?: boolean;
|
||||
emailRequiredForSignup?: boolean;
|
||||
approvalRequiredForSignup?: boolean;
|
||||
enableHcaptcha?: boolean;
|
||||
hcaptchaSiteKey?: string | null;
|
||||
hcaptchaSecretKey?: string | null;
|
||||
|
|
|
@ -62,6 +62,7 @@ export const permissions = [
|
|||
'read:admin:show-user',
|
||||
'read:admin:show-users',
|
||||
'write:admin:suspend-user',
|
||||
'write:admin:approve-user',
|
||||
'write:admin:unsuspend-user',
|
||||
'write:admin:meta',
|
||||
'write:admin:user-name',
|
||||
|
@ -106,6 +107,7 @@ export const permissions = [
|
|||
export const moderationLogTypes = [
|
||||
'updateServerSettings',
|
||||
'suspend',
|
||||
'approve',
|
||||
'unsuspend',
|
||||
'updateUserName',
|
||||
'updateUserNote',
|
||||
|
@ -163,6 +165,11 @@ export type ModerationLogPayloads = {
|
|||
userUsername: string;
|
||||
userHost: string | null;
|
||||
};
|
||||
approve: {
|
||||
userId: string;
|
||||
userUsername: string;
|
||||
userHost: string | null;
|
||||
};
|
||||
unsuspend: {
|
||||
userId: string;
|
||||
userUsername: string;
|
||||
|
|
Loading…
Reference in a new issue