feat: make instance private
This commit is contained in:
parent
0c4972c12a
commit
ea0c96d5b4
|
@ -1216,7 +1216,10 @@ beSureToReadThisAsItIsImportant: "Please read this important information."
|
|||
iHaveReadXCarefullyAndAgree: "I have read the text \"{x}\" and agree."
|
||||
doNotSendNotificationEmailsForAbuseReport: "Do not send out notification emails for reporting"
|
||||
disableTimelinePreview: "Hide timeline preview in landing page"
|
||||
disableTimelinePreviewWarning: "By turning on, '{explore}' in landing page will be replaced to '{letsLookAtTimeline}'"
|
||||
disableTimelinePreviewDescription: "By turning on, '{explore}' in landing page will be replaced to '{letsLookAtTimeline}'"
|
||||
signupIsNotAvailable: "For now, you can't sign up on this instance."
|
||||
makeInstancePrivate: "Make instance private"
|
||||
makeInstancePrivateDescription: "By turning on, all visitors can't sign up (even if they invited) on this instance and can't view timeline, trends, highlights, etc."
|
||||
emailToReceiveAbuseReport: "Email address to receive notification of the report"
|
||||
emailToReceiveAbuseReportCaption: "Specify the email address to receive notification of the report. If this field is left blank, the mail server's email address will be used."
|
||||
dialog: "Dialog"
|
||||
|
|
|
@ -1222,7 +1222,10 @@ beSureToReadThisAsItIsImportant: "重要ですので必ずお読みください
|
|||
iHaveReadXCarefullyAndAgree: "「{x}」の内容をよく読み、同意します。"
|
||||
doNotSendNotificationEmailsForAbuseReport: "通報の通知メールを発送しないようにする"
|
||||
disableTimelinePreview: "非ログインのメインページにTLを表示しない"
|
||||
disableTimelinePreviewWarning: "このオプションを使用すると、「{explore}」ボタンが「{letsLookAtTimeline}」に変わります。"
|
||||
disableTimelinePreviewDescription: "このオプションを使用すると、「{explore}」ボタンが「{letsLookAtTimeline}」に変わります。"
|
||||
signupIsNotAvailable: "현재 이 인스턴스는 신규 사용자를 받고 있지 않습니다."
|
||||
makeInstancePrivate: "인스턴스를 비공개로 만들기"
|
||||
makeInstancePrivateDescription: "이 옵션을 사용할 경우, 초대를 통한 신규 가입을 포함해 모든 가입이 제한되며, 비로그인 사용자는 발견하기, 타임라인 등을 일체 볼 수 없게 됩니다."
|
||||
emailToReceiveAbuseReport: "通報通知を受け取るためのメールアドレス"
|
||||
emailToReceiveAbuseReportCaption: "通報通知を受け取るためのメールアドレスを指定します。ここの入力欄を空にするとメールサーバーのメールアドレスが使用されます。"
|
||||
dialog: "ダイアログ"
|
||||
|
|
|
@ -1214,7 +1214,10 @@ beSureToReadThisAsItIsImportant: "중요하므로 반드시 읽어주세요."
|
|||
iHaveReadXCarefullyAndAgree: "\"{x}\"의 내용을 읽고 동의할게요."
|
||||
doNotSendNotificationEmailsForAbuseReport: "신고 알림 메일을 발송하지 않기"
|
||||
disableTimelinePreview: "비로그인 페이지에 타임라인 미리보기를 표시하지 않기"
|
||||
disableTimelinePreviewWarning: "이 옵션을 사용하면 '{explore}' 버튼이 '{letsLookAtTimeline}' 버튼으로 변경됩니다."
|
||||
disableTimelinePreviewDescription: "이 옵션을 사용하면 '{explore}' 버튼이 '{letsLookAtTimeline}' 버튼으로 변경됩니다."
|
||||
signupIsNotAvailable: "현재 이 인스턴스는 신규 사용자를 받고 있지 않습니다."
|
||||
makeInstancePrivate: "인스턴스를 비공개로 만들기"
|
||||
makeInstancePrivateDescription: "이 옵션을 사용할 경우, 초대를 통한 신규 가입을 포함해 모든 가입이 제한되며, 비로그인 사용자는 발견하기, 타임라인 등을 일체 볼 수 없게 됩니다."
|
||||
emailToReceiveAbuseReport: "신고 알림을 받을 수 있는 이메일 주소"
|
||||
emailToReceiveAbuseReportCaption: "신고 알림을 받을 이메일 주소를 지정해 주세요. 이곳의 입력란을 비워두면 메일 서버의 이메일 주소가 사용돼요."
|
||||
dialog: "다이얼로그"
|
||||
|
|
16
packages/backend/migration/1701407688151-privateInstance.js
Normal file
16
packages/backend/migration/1701407688151-privateInstance.js
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and other misskey, cherrypick contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class privateInstance1701407688151 {
|
||||
name = 'privateInstance1701407688151'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "privateInstance" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "privateInstance"`);
|
||||
}
|
||||
}
|
|
@ -673,4 +673,9 @@ export class MiMeta {
|
|||
default: false,
|
||||
})
|
||||
public disableTimelinePreview: boolean;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public privateInstance: boolean;
|
||||
}
|
||||
|
|
|
@ -549,6 +549,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
skipVersion: instance.skipVersion,
|
||||
skipCherryPickVersion: instance.skipCherryPickVersion,
|
||||
disableTimelinePreview: instance.disableTimelinePreview,
|
||||
privateInstance: instance.privateInstance,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ export const paramDef = {
|
|||
skipVersion: { type: 'boolean' },
|
||||
skipCherryPickVersion: { type: 'string', nullable: true },
|
||||
disableTimelinePreview: { type: 'boolean' },
|
||||
privateInstance: { type: 'boolean' },
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
|
|
|
@ -219,6 +219,10 @@ export const meta = {
|
|||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
privateInstance: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
features: {
|
||||
type: 'object',
|
||||
optional: true, nullable: false,
|
||||
|
@ -358,6 +362,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
|||
|
||||
mediaProxy: this.config.mediaProxy,
|
||||
disableTimelinePreview: instance.disableTimelinePreview,
|
||||
privateInstance: instance.privateInstance,
|
||||
|
||||
...(ps.detail ? {
|
||||
cacheRemoteFiles: instance.cacheRemoteFiles,
|
||||
|
|
|
@ -394,6 +394,8 @@ export type LiteInstanceMetadata = {
|
|||
notesPerOneAd: number;
|
||||
translatorAvailable: boolean;
|
||||
serverRules: string[];
|
||||
disableTimelinePreview: boolean;
|
||||
privateInstance: boolean;
|
||||
};
|
||||
|
||||
export type DetailedInstanceMetadata = LiteInstanceMetadata & {
|
||||
|
|
|
@ -21,11 +21,14 @@ 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.privateInstance" :class="$style.mainWarn">
|
||||
<MkInfo warn>{{ i18n.ts.signupIsNotAvailable }}</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 v-if="!instance.privateInstance" :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> -->
|
||||
<MkButton v-if="!instance.disableTimelinePreview" :class="$style.mainAction" full rounded @click="mainRouter.push('/explore')">{{ i18n.ts.explore }}</MkButton>
|
||||
<MkButton v-if="instance.disableTimelinePreview" :class="$style.mainAction" full rounded @click="mainRouter.push('/timeline')">{{ i18n.ts.letsLookAtTimeline }}</MkButton>
|
||||
<MkButton v-if="!instance.disableTimelinePreview && !instance.privateInstance" :class="$style.mainAction" full rounded @click="mainRouter.push('/explore')">{{ i18n.ts.explore }}</MkButton>
|
||||
<MkButton v-if="instance.disableTimelinePreview && !instance.privateInstance" :class="$style.mainAction" full rounded @click="mainRouter.push('/timeline')">{{ i18n.ts.letsLookAtTimeline }}</MkButton>
|
||||
<MkButton :class="$style.mainAction" full rounded data-cy-signin @click="signin()">{{ i18n.ts.login }}</MkButton>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -40,7 +43,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div :class="$style.statsItemCount"><MkNumber :value="stats.originalNotesCount"/></div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="!instance.disableTimelinePreview" :class="[$style.tl, $style.panel]">
|
||||
<div v-if="!instance.disableTimelinePreview && !instance.privateInstance" :class="[$style.tl, $style.panel]">
|
||||
<div :class="$style.tlHeader">{{ i18n.ts.letsLookAtTimeline }}</div>
|
||||
<div :class="$style.tlBody">
|
||||
<MkTimeline src="local"/>
|
||||
|
|
|
@ -14,6 +14,11 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template #label>{{ i18n.ts.enableRegistration }}</template>
|
||||
</MkSwitch>
|
||||
|
||||
<MkSwitch v-model="privateInstance">
|
||||
<template #label>{{ i18n.ts.makeInstancePrivate }}</template>
|
||||
<template #caption>{{ i18n.ts.makeInstancePrivateDescription }}</template>
|
||||
</MkSwitch>
|
||||
|
||||
<MkSwitch v-model="emailRequiredForSignup">
|
||||
<template #label>{{ i18n.ts.emailRequiredForSignup }}</template>
|
||||
</MkSwitch>
|
||||
|
@ -75,6 +80,7 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import FormLink from '@/components/form/link.vue';
|
||||
|
||||
let enableRegistration: boolean = $ref(false);
|
||||
let privateInstance: boolean = $ref(false);
|
||||
let emailRequiredForSignup: boolean = $ref(false);
|
||||
let sensitiveWords: string = $ref('');
|
||||
let hiddenTags: string = $ref('');
|
||||
|
@ -85,6 +91,7 @@ let privacyPolicyUrl: string | null = $ref(null);
|
|||
async function init() {
|
||||
const meta = await os.api('admin/meta');
|
||||
enableRegistration = !meta.disableRegistration;
|
||||
privateInstance = meta.privateInstance;
|
||||
emailRequiredForSignup = meta.emailRequiredForSignup;
|
||||
sensitiveWords = meta.sensitiveWords.join('\n');
|
||||
hiddenTags = meta.hiddenTags.join('\n');
|
||||
|
@ -96,6 +103,7 @@ async function init() {
|
|||
function save() {
|
||||
os.apiWithDialog('admin/update-meta', {
|
||||
disableRegistration: !enableRegistration,
|
||||
privateInstance: privateInstance,
|
||||
emailRequiredForSignup,
|
||||
tosUrl,
|
||||
privacyPolicyUrl,
|
||||
|
|
|
@ -48,7 +48,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<div class="_panel" style="padding: 16px;">
|
||||
<MkSwitch v-model="disableTimelinePreview">
|
||||
<template #label>{{ i18n.ts.disableTimelinePreview }}</template>
|
||||
<template #caption>{{ i18n.t('disableTimelinePreviewWarning', { explore: i18n.ts.explore, letsLookAtTimeline: i18n.ts.letsLookAtTimeline }) }}</template>
|
||||
<template #caption>{{ i18n.t('disableTimelinePreviewDescription', { explore: i18n.ts.explore, letsLookAtTimeline: i18n.ts.letsLookAtTimeline }) }}</template>
|
||||
</MkSwitch>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -62,6 +62,7 @@ import MkButton from '@/components/MkButton.vue';
|
|||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
|
@ -72,6 +73,8 @@ const props = defineProps<{
|
|||
type?: string;
|
||||
}>();
|
||||
|
||||
if (instance.privateInstance && $i == null) router.push('/');
|
||||
|
||||
let key = $ref('');
|
||||
let tab = $ref('featured');
|
||||
let searchQuery = $ref('');
|
||||
|
|
|
@ -26,6 +26,9 @@ import XFeatured from './explore.featured.vue';
|
|||
import XUsers from './explore.users.vue';
|
||||
import XRoles from './explore.roles.vue';
|
||||
import MkFoldableSection from '@/components/MkFoldableSection.vue';
|
||||
import { instance } from '@/instance.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { i18n } from '@/i18n.js';
|
||||
|
||||
|
@ -36,6 +39,10 @@ const props = withDefaults(defineProps<{
|
|||
initialTab: 'featured',
|
||||
});
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
if (instance.privateInstance && $i == null) router.push('/');
|
||||
|
||||
let tab = $ref(props.initialTab);
|
||||
let tagsEl = $shallowRef<InstanceType<typeof MkFoldableSection>>();
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ import { defaultStore } from '@/store.js';
|
|||
import { i18n } from '@/i18n.js';
|
||||
import { instance } from '@/instance.js';
|
||||
import { $i } from '@/account.js';
|
||||
import { useRouter } from '@/router.js';
|
||||
import { definePageMetadata } from '@/scripts/page-metadata.js';
|
||||
import { miLocalStorage } from '@/local-storage.js';
|
||||
import { antennasCache, userListsCache } from '@/cache.js';
|
||||
|
@ -91,6 +92,8 @@ import { unisonReload } from '@/scripts/unison-reload.js';
|
|||
let showEl = $ref(false);
|
||||
const isFriendly = ref(miLocalStorage.getItem('ui') === 'friendly');
|
||||
|
||||
const router = useRouter();
|
||||
|
||||
const MOBILE_THRESHOLD = 500;
|
||||
|
||||
const isMobile = ref(deviceKind === 'smartphone' || window.innerWidth <= MOBILE_THRESHOLD);
|
||||
|
@ -100,6 +103,8 @@ window.addEventListener('resize', () => {
|
|||
|
||||
if (!isFriendly.value) provide('shouldOmitHeaderTitle', true);
|
||||
|
||||
if (instance.privateInstance && $i == null) router.push('/');
|
||||
|
||||
const isLocalTimelineAvailable = ($i == null && instance.policies.ltlAvailable) || ($i != null && $i.policies.ltlAvailable);
|
||||
const isGlobalTimelineAvailable = ($i == null && instance.policies.gtlAvailable) || ($i != null && $i.policies.gtlAvailable);
|
||||
const keymap = {
|
||||
|
|
|
@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
<template>
|
||||
<div v-if="meta" class="rsqzvsbo">
|
||||
<MkFeaturedPhotos class="bg"/>
|
||||
<XTimeline class="tl"/>
|
||||
<XTimeline v-if="!instance.disableTimelinePreview && !instance.privateInstance" class="tl"/>
|
||||
<div class="shape1"></div>
|
||||
<div class="shape2"></div>
|
||||
<img src="/client-assets/cherrypick.svg" class="cherrypick"/>
|
||||
|
@ -22,10 +22,10 @@ SPDX-License-Identifier: AGPL-3.0-only
|
|||
</div>
|
||||
<div v-if="instances && instances.length > 0" class="federation">
|
||||
<MarqueeText :duration="40">
|
||||
<MkA v-for="instance in instances" :key="instance.id" :class="$style.federationInstance" :to="`/instance-info/${instance.host}`" behavior="window">
|
||||
<!--<MkInstanceCardMini :instance="instance"/>-->
|
||||
<img v-if="instance.iconUrl" class="icon" :src="getInstanceIcon(instance)" alt=""/>
|
||||
<span class="name _monospace">{{ instance.host }}</span>
|
||||
<MkA v-for="ins in instances" :key="ins.id" :class="$style.federationInstance" :to="`/instance-info/${ins.host}`" behavior="window">
|
||||
<!--<MkInstanceCardMini :instance="ins"/>-->
|
||||
<img v-if="ins.iconUrl" class="icon" :src="getInstanceIcon(ins)" alt=""/>
|
||||
<span class="name _monospace">{{ ins.host }}</span>
|
||||
</MkA>
|
||||
</MarqueeText>
|
||||
</div>
|
||||
|
|
Loading…
Reference in a new issue