diff --git a/CALCKEY.md b/CALCKEY.md
index dacaf77eea..e25034a463 100644
--- a/CALCKEY.md
+++ b/CALCKEY.md
@@ -68,6 +68,7 @@
- đ also triggers generic like/favorite
- [Add additional background for acrylic popups if backdrop-filter is unsupported](https://github.com/misskey-dev/misskey/pull/8671)
- [Timeline page for non-login users](https://github.com/misskey-dev/misskey/pull/8927)
+ - Made toggleable by instance admins, off by default
- [Add parameters to MFM rotate](https://github.com/misskey-dev/misskey/pull/8549)
- Many changes from [Foundkey](https://akkoma.dev/FoundKeyGang/Foundkey)
- 0ece67b04c3f0365057624c1068808276ccab981: refactor pages/auth.form.vue to composition API
diff --git a/locales/en-US.yml b/locales/en-US.yml
index f64a7c20d1..9ac13a7e90 100644
--- a/locales/en-US.yml
+++ b/locales/en-US.yml
@@ -324,6 +324,7 @@ disconnectService: "Disconnect"
enableLocalTimeline: "Enable local timeline"
enableGlobalTimeline: "Enable global timeline"
enableRecommendedTimeline: "Enable recommended timeline"
+enableGuestTimeline: "Enable timelines for non-logged in users"
disablingTimelinesInfo: "Adminstrators and Moderators will always have access to all timelines, even if they are not enabled."
registration: "Register"
enableRegistration: "Enable new user registration"
diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml
index ecd30b42d8..bb159aba37 100644
--- a/locales/ja-JP.yml
+++ b/locales/ja-JP.yml
@@ -324,6 +324,7 @@ disconnectService: "ćæăă"
enableLocalTimeline: "ăăŒă«ă«ăżă€ă ă©ă€ăłăæćčă«ăă"
enableGlobalTimeline: "ă°ăăŒăă«ăżă€ă ă©ă€ăłăæćčă«ăă"
enableRecommendedTimeline: "æšć„šăăăăżă€ă ă©ă€ăłăæćčă«ăă"
+enableGuestTimeline: "éăă°ă€ăłăŠăŒă¶ăŒăźăżă€ă ă©ă€ăłăæćčă«ăă"
disablingTimelinesInfo: "ăăăăźăżă€ă ă©ă€ăłăçĄćčćăăŠăăć©äŸżæ§ăźăă知çè
ăăăłăąăăŹăŒăżăŒăŻćŒăç¶ăć©çšăăăăšăă§ăăŸăă"
registration: "ç»éČ"
enableRegistration: "èȘ°ă§ăæ°èŠç»éČă§ăăăăă«ăă"
diff --git a/packages/backend/migration/1660068273737GuestTimeline.js b/packages/backend/migration/1660068273737GuestTimeline.js
new file mode 100644
index 0000000000..cabea72012
--- /dev/null
+++ b/packages/backend/migration/1660068273737GuestTimeline.js
@@ -0,0 +1,9 @@
+export class GuestTimeline1660068273737 {
+ name = 'GuestTimeline1660068273737'
+ async up(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" ADD "enableGuestTimeline" boolean NOT NULL DEFAULT true`);
+ }
+ async down(queryRunner) {
+ await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "enableGuestTimeline"`);
+ }
+ }
diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts
index 63a4193aaa..3c1612c36a 100644
--- a/packages/backend/src/models/entities/meta.ts
+++ b/packages/backend/src/models/entities/meta.ts
@@ -57,6 +57,11 @@ export class Meta {
})
public disableGlobalTimeline: boolean;
+ @Column('boolean', {
+ default: false,
+ })
+ public enableGuestTimeline: boolean;
+
@Column('boolean', {
default: false,
})
diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts
index ca7edc352d..43a3524c19 100644
--- a/packages/backend/src/server/api/endpoints/meta.ts
+++ b/packages/backend/src/server/api/endpoints/meta.ts
@@ -88,6 +88,10 @@ export const meta = {
type: 'boolean',
optional: false, nullable: false,
},
+ enableGuestTimeline: {
+ type: 'boolean',
+ optional: false, nullable: false,
+ },
driveCapacityPerLocalUserMb: {
type: 'number',
optional: false, nullable: false,
@@ -366,6 +370,7 @@ export default define(meta, paramDef, async (ps, me) => {
disableLocalTimeline: instance.disableLocalTimeline,
disableRecommendedTimeline: instance.disableRecommendedTimeline,
disableGlobalTimeline: instance.disableGlobalTimeline,
+ enableGuestTimeline: instance.enableGuestTimeline,
driveCapacityPerLocalUserMb: instance.localDriveCapacityMb,
driveCapacityPerRemoteUserMb: instance.remoteDriveCapacityMb,
emailRequiredForSignup: instance.emailRequiredForSignup,
@@ -423,6 +428,7 @@ export default define(meta, paramDef, async (ps, me) => {
localTimeLine: !instance.disableLocalTimeline,
recommendedTimeline: !instance.disableRecommendedTimeline,
globalTimeLine: !instance.disableGlobalTimeline,
+ guestTimeline: instance.enableGuestTimeline,
emailRequiredForSignup: instance.emailRequiredForSignup,
elasticsearch: config.elasticsearch ? true : false,
hcaptcha: instance.enableHcaptcha,
diff --git a/packages/backend/src/server/nodeinfo.ts b/packages/backend/src/server/nodeinfo.ts
index b4216d9d92..4e3cb63882 100644
--- a/packages/backend/src/server/nodeinfo.ts
+++ b/packages/backend/src/server/nodeinfo.ts
@@ -69,6 +69,7 @@ const nodeinfo2 = async () => {
disableLocalTimeline: meta.disableLocalTimeline,
disableRecommendedTimeline: meta.disableRecommendedTimeline,
disableGlobalTimeline: meta.disableGlobalTimeline,
+ enableGuestTimeline: meta.enableGuestTimeline,
emailRequiredForSignup: meta.emailRequiredForSignup,
enableHcaptcha: meta.enableHcaptcha,
enableRecaptcha: meta.enableRecaptcha,
diff --git a/packages/client/src/pages/admin/settings.vue b/packages/client/src/pages/admin/settings.vue
index 2871abab25..d5cf776f80 100644
--- a/packages/client/src/pages/admin/settings.vue
+++ b/packages/client/src/pages/admin/settings.vue
@@ -55,6 +55,7 @@
{{ i18n.ts.enableLocalTimeline }}
{{ i18n.ts.enableGlobalTimeline }}
+ {{ i18n.ts.enableGuestTimeline }}
{{ i18n.ts.disablingTimelinesInfo }}
@@ -198,6 +199,7 @@ let defaultDarkTheme: any = $ref(null);
let enableLocalTimeline: boolean = $ref(false);
let enableGlobalTimeline: boolean = $ref(false);
let enableRecommendedTimeline: boolean = $ref(false);
+let enableGuestTimeline: boolean = $ref(false);
let pinnedUsers: string = $ref('');
let customMOTD: string = $ref('');
let recommendedInstances: string = $ref('');
@@ -229,6 +231,7 @@ async function init() {
enableLocalTimeline = !meta.disableLocalTimeline;
enableGlobalTimeline = !meta.disableGlobalTimeline;
enableRecommendedTimeline = !meta.disableRecommendedTimeline;
+ enableGuestTimeline = meta.enableGuestTimeline;
pinnedUsers = meta.pinnedUsers.join('\n');
customMOTD = meta.customMOTD.join('\n');
customSplashIcons = meta.customSplashIcons.join('\n');
@@ -261,6 +264,7 @@ function save() {
disableLocalTimeline: !enableLocalTimeline,
disableGlobalTimeline: !enableGlobalTimeline,
disableRecommendedTimeline: !enableRecommendedTimeline,
+ enableGuestTimeline: enableGuestTimeline,
pinnedUsers: pinnedUsers.split('\n'),
customMOTD: customMOTD.split('\n'),
customSplashIcons: customSplashIcons.split('\n'),
diff --git a/packages/client/src/router.ts b/packages/client/src/router.ts
index 29b2eb5909..322f9bc123 100644
--- a/packages/client/src/router.ts
+++ b/packages/client/src/router.ts
@@ -4,6 +4,10 @@ import { $i, iAmModerator } from '@/account';
import MkLoading from '@/pages/_loading_.vue';
import MkError from '@/pages/_error_.vue';
import { ui } from '@/config';
+import * as os from '@/os';
+
+const meta = await os.api('admin/meta');
+const guestTimeline = meta.enableGuestTimeline;
const page = (loader: AsyncComponentLoader) => defineAsyncComponent({
loader: loader,
@@ -456,6 +460,7 @@ export const routes = [{
}, {
path: '/timeline',
component: page(() => import('./pages/timeline.vue')),
+ loginRequired: guestTimeline,
}, {
name: 'index',
path: '/',
diff --git a/packages/client/src/ui/visitor/b.vue b/packages/client/src/ui/visitor/b.vue
index bb0c59e4ff..e2c70d7341 100644
--- a/packages/client/src/ui/visitor/b.vue
+++ b/packages/client/src/ui/visitor/b.vue
@@ -77,7 +77,7 @@ const announcements = {
endpoint: 'announcements',
limit: 10,
};
-const isTimelineAvailable = !instance.disableLocalTimeline || !instance.disableRecommendedTimeline || !instance.disableGlobalTimeline;
+const isTimelineAvailable = instance.enableGuestTimeline && (!instance.disableLocalTimeline || !instance.disableRecommendedTimeline || !instance.disableGlobalTimeline);
let showMenu = $ref(false);
let isDesktop = $ref(window.innerWidth >= DESKTOP_THRESHOLD);
let narrow = $ref(window.innerWidth < 1280);
diff --git a/packages/client/src/ui/visitor/header.vue b/packages/client/src/ui/visitor/header.vue
index 6b4dd1ded2..80a3a34914 100644
--- a/packages/client/src/ui/visitor/header.vue
+++ b/packages/client/src/ui/visitor/header.vue
@@ -60,7 +60,7 @@ export default defineComponent({
return {
narrow: null,
showMenu: false,
- isTimelineAvailable: !instance.disableLocalTimeline || !instance.disableRecommendedTimeline || !instance.disableGlobalTimeline,
+ isTimelineAvailable: instance.enableGuestTimeline && (!instance.disableLocalTimeline || !instance.disableRecommendedTimeline || !instance.disableGlobalTimeline),
};
},