Add secure mode settings to Security tab

This commit is contained in:
nullobsi 2021-07-20 13:08:21 -07:00 committed by Francis Dinh
parent 840227a901
commit 61b7c8ca53
Signed by untrusted user: norm
GPG key ID: 7123E30E441E80DE
5 changed files with 82 additions and 0 deletions

View file

@ -829,6 +829,13 @@ middle: "Medium"
low: "Low" low: "Low"
emailNotConfiguredWarning: "Email address not set." emailNotConfiguredWarning: "Email address not set."
ratio: "Ratio" ratio: "Ratio"
secureMode: "Secure Mode (Authorized Fetch)"
instanceSecurity: "Instance Security"
secureModeInfo: "Requests from other instances must be signed, otherwise notes won't be returned."
privateMode: "Private Mode"
privateModeInfo: "When enabled, only authorized instances may fetch notes. Hides all notes from public."
allowedInstances: "Allowed Instances"
allowedInstancesDescription: "Set the hosts of the instances you want to allow, separated by line. Valid in private mode only."
previewNoteText: "Show preview" previewNoteText: "Show preview"
customCss: "Custom CSS" customCss: "Custom CSS"
customCssWarn: "This setting should only be used if you know what it does. Entering\ customCssWarn: "This setting should only be used if you know what it does. Entering\

View file

@ -771,6 +771,13 @@ middle: "中"
low: "低" low: "低"
emailNotConfiguredWarning: "メールアドレスの設定がされていません。" emailNotConfiguredWarning: "メールアドレスの設定がされていません。"
ratio: "比率" ratio: "比率"
secureMode: "セキュアモード (Authorized Fetch)"
instanceSecurity: "インスタンスのセキュリティー"
secureModeInfo: "他のインスタンスからリクエストするときに、証明を付けなければ返送しません。"
privateMode: "非公開モード"
privateModeInfo: "有効にして、許可されているインスタンスのみがリクエストできます。すべてのノートが公開に非表示にします。"
allowedInstances: "許可されたインスタンス"
allowedInstancesDescription: "許可したいインスタンスのホストを改行で区切って設定します。非公開モードだけで有効です。"
previewNoteText: "本文をプレビュー" previewNoteText: "本文をプレビュー"
customCss: "カスタムCSS" customCss: "カスタムCSS"
customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。" customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。"

View file

@ -153,6 +153,22 @@ export const meta = {
optional: false, nullable: false, optional: false, nullable: false,
}, },
}, },
allowedHosts: {
type: 'array',
optional: true, nullable: false,
items: {
type: 'string',
optional: false, nullable: false,
},
},
privateMode: {
type: 'boolean',
optional: false, nullable: false,
},
secureMode: {
type: 'boolean',
optional: false, nullable: false,
},
hcaptchaSecretKey: { hcaptchaSecretKey: {
type: 'string', type: 'string',
optional: true, nullable: true, optional: true, nullable: true,
@ -327,6 +343,9 @@ export default define(meta, paramDef, async (ps, me) => {
pinnedUsers: instance.pinnedUsers, pinnedUsers: instance.pinnedUsers,
hiddenTags: instance.hiddenTags, hiddenTags: instance.hiddenTags,
blockedHosts: instance.blockedHosts, blockedHosts: instance.blockedHosts,
allowedHosts: instance.allowedHosts,
privateMode: instance.privateMode,
secureMode: instance.secureMode,
hcaptchaSecretKey: instance.hcaptchaSecretKey, hcaptchaSecretKey: instance.hcaptchaSecretKey,
recaptchaSecretKey: instance.recaptchaSecretKey, recaptchaSecretKey: instance.recaptchaSecretKey,
proxyAccountId: instance.proxyAccountId, proxyAccountId: instance.proxyAccountId,

View file

@ -26,6 +26,11 @@ export const paramDef = {
blockedHosts: { type: 'array', nullable: true, items: { blockedHosts: { type: 'array', nullable: true, items: {
type: 'string', type: 'string',
} }, } },
allowedHosts: { type: 'array', nullable: true, items: {
type: 'string',
} },
secureMode: { type: 'boolean', nullable: true },
privateMode: { type: 'boolean', nullable: true },
themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' }, themeColor: { type: 'string', nullable: true, pattern: '^#[0-9a-fA-F]{6}$' },
bannerUrl: { type: 'string', nullable: true }, bannerUrl: { type: 'string', nullable: true },
iconUrl: { type: 'string', nullable: true }, iconUrl: { type: 'string', nullable: true },
@ -131,6 +136,18 @@ export default define(meta, paramDef, async (ps, me) => {
set.themeColor = ps.themeColor; set.themeColor = ps.themeColor;
} }
if (Array.isArray(ps.allowedHosts)) {
set.allowedHosts = ps.allowedHosts.filter(Boolean);
}
if (typeof ps.privateMode === 'boolean') {
set.privateMode = ps.privateMode;
}
if (typeof ps.secureMode === 'boolean') {
set.secureMode = ps.secureMode;
}
if (ps.bannerUrl !== undefined) { if (ps.bannerUrl !== undefined) {
set.bannerUrl = ps.bannerUrl; set.bannerUrl = ps.bannerUrl;
} }

View file

@ -26,6 +26,26 @@
<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ i18n.ts.save }}</FormButton> <FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ i18n.ts.save }}</FormButton>
</div> </div>
</FormFolder> </FormFolder>
<FormFolder class="_formBlock">
<template #label>{{ i18n.ts.instanceSecurity }}</template>
<div class="_formRoot">
<FormSwitch v-if="!privateMode" v-model="secureMode">
<template #label>{{ i18n.ts.secureMode }}</template>
<template #caption>{{ i18n.ts.secureModeInfo }}</template>
</FormSwitch>
<FormSwitch v-model="privateMode">
<template #label>{{ i18n.ts.privateMode }}</template>
<template #caption>{{ i18n.ts.privateModeInfo }}</template>
</FormSwitch>
<FormTextarea v-if="privateMode" v-model="allowedHosts">
<template #label>{{ i18n.ts.allowedInstances }}</template>
<template #caption>{{ i18n.ts.allowedInstancesDescription }}</template>
</FormTextarea>
<FormButton primary class="_formBlock" @click="save"><i class="fas fa-save"></i> {{ i18n.ts.save }}</FormButton>
</div>
</FormFolder>
</div> </div>
</FormSuspense> </FormSuspense>
</MkSpacer> </MkSpacer>
@ -38,6 +58,7 @@ import FormFolder from '@/components/form/folder.vue';
import FormSuspense from '@/components/form/suspense.vue'; import FormSuspense from '@/components/form/suspense.vue';
import FormInput from '@/components/form/input.vue'; import FormInput from '@/components/form/input.vue';
import FormButton from '@/components/ui/button.vue'; import FormButton from '@/components/ui/button.vue';
import FormTextarea from '@/components/form/textarea.vue';
import * as os from '@/os'; import * as os from '@/os';
import { fetchInstance } from '@/instance'; import { fetchInstance } from '@/instance';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
@ -47,16 +68,27 @@ let summalyProxy: string = $ref('');
let enableHcaptcha: boolean = $ref(false); let enableHcaptcha: boolean = $ref(false);
let enableRecaptcha: boolean = $ref(false); let enableRecaptcha: boolean = $ref(false);
let secureMode: boolean = $ref(false);
let privateMode: boolean = $ref(false);
let allowedHosts: string = $ref('');
async function init(): Promise<void> { async function init(): Promise<void> {
const meta = await os.api('admin/meta'); const meta = await os.api('admin/meta');
summalyProxy = meta.summalyProxy; summalyProxy = meta.summalyProxy;
enableHcaptcha = meta.enableHcaptcha; enableHcaptcha = meta.enableHcaptcha;
enableRecaptcha = meta.enableRecaptcha; enableRecaptcha = meta.enableRecaptcha;
secureMode = meta.secureMode;
privateMode = meta.privateMode;
allowedHosts = meta.allowedHosts.join('\n');
} }
function save(): void { function save(): void {
os.apiWithDialog('admin/update-meta', { os.apiWithDialog('admin/update-meta', {
summalyProxy, summalyProxy,
secureMode,
privateMode,
allowedHosts: allowedHosts.split('\n'),
}).then(() => { }).then(() => {
fetchInstance(); fetchInstance();
}); });