feat: Requiring credential to view local timeline
Some checks failed
/ test-build (push) Has been cancelled

This commit is contained in:
ltlapy 2024-12-27 13:09:57 +09:00
parent 486e4279af
commit 708a8d28a6
20 changed files with 69 additions and 5 deletions

View file

@ -2181,3 +2181,4 @@ _wellness:
newPostsButton: "Enable new posts alert button"
newPostsGlowOpacity: "New posts glow opacity"
immediacy: "Immediacy"
localTimelineRequiresCredential: Disable local timeline for non-logged in users

View file

@ -1972,3 +1972,4 @@ _cwStyle:
alternative: 代替(Firefish-like)
cwStyle: 閲覧注意投稿の表示スタイル
searchNotLoggedIn_2: しかし、ハッシュタグ検索とユーザー検索は利用できます。
localTimelineRequiresCredential: 非ログインユーザーにローカルタイムラインを非公開

View file

@ -1899,3 +1899,4 @@ removeMember: 멤버 삭제하기
searchEmptyQuery: 검색할 내용을 입력해주세요.
searchNotLoggedIn_1: 전체 텍스트 검색을 하려면 먼저 로그인해야 합니다.
searchNotLoggedIn_2: 대신, 해시태그나 유저를 검색할 수 있습니다.
localTimelineRequiresCredential: 비로그인 상태의 로컬 타임라인 열람 제한

View file

@ -1887,3 +1887,4 @@ removeMember: 멤버 삭제하기
searchEmptyQuery: 검색할 내용을 입력해달라냥.
searchNotLoggedIn_1: 전체 텍스트 검색을 하려면 먼저 로그인해야 한다냥.
searchNotLoggedIn_2: 대신, 해시태그나 유저를 검색할 수 있다냥.
localTimelineRequiresCredential: 비로그인 상태의 로컬 타임라인 열람 제한

View file

@ -0,0 +1,13 @@
import { MigrationInterface, QueryRunner } from "typeorm";
export class AddLocalTimelineRequiresCredential1735271639334 implements MigrationInterface {
name = 'AddLocalTimelineRequiresCredential1735271639334'
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" ADD "localTimelineRequiresCredential" boolean;`);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "localTimelineRequiresCredential"`);
}
}

View file

@ -45,6 +45,11 @@ export class Meta {
default: false,
})
public disableRegistration: boolean;
@Column("boolean", {
default: false,
})
public localTimelineRequiresCredential: boolean;
@Column("boolean", {
default: false,

View file

@ -425,6 +425,7 @@ export default define(meta, paramDef, async (ps, me) => {
repositoryUrl: instance.repositoryUrl,
feedbackUrl: instance.feedbackUrl,
disableRegistration: instance.disableRegistration,
localTimelineRequiresCredential: instance.localTimelineRequiresCredential,
disableLocalTimeline: instance.disableLocalTimeline,
disableRecommendedTimeline: instance.disableRecommendedTimeline,
disableGlobalTimeline: instance.disableGlobalTimeline,

View file

@ -18,6 +18,7 @@ export const paramDef = {
type: "object",
properties: {
disableRegistration: { type: "boolean", nullable: true },
localTimelineRequiresCredential: { type: "boolean", nullable: true },
disableLocalTimeline: { type: "boolean", nullable: true },
disableRecommendedTimeline: { type: "boolean", nullable: true },
disableGlobalTimeline: { type: "boolean", nullable: true },
@ -178,6 +179,10 @@ export default define(meta, paramDef, async (ps, me) => {
set.disableRegistration = ps.disableRegistration;
}
if (typeof ps.localTimelineRequiresCredential === "boolean") {
set.localTimelineRequiresCredential = ps.localTimelineRequiresCredential;
}
if (typeof ps.disableLocalTimeline === "boolean") {
set.disableLocalTimeline = ps.disableLocalTimeline;
}

View file

@ -98,6 +98,11 @@ export const meta = {
optional: false,
nullable: false,
},
localTimelineRequiresCredential: {
type: "boolean",
optional: false,
nullable: false,
},
disableLocalTimeline: {
type: "boolean",
optional: false,
@ -409,6 +414,7 @@ export default define(meta, paramDef, async (ps, me) => {
privateMode: instance.privateMode,
disableRegistration: instance.disableRegistration,
localTimelineRequiresCredential: instance.localTimelineRequiresCredential,
disableLocalTimeline: instance.disableLocalTimeline,
disableRecommendedTimeline: instance.disableRecommendedTimeline,
disableGlobalTimeline: instance.disableGlobalTimeline,

View file

@ -1,5 +1,7 @@
import { fetchMeta } from "@/misc/fetch-meta.js";
import { Notes } from "@/models/index.js";
import define from "../../define.js";
import { ApiError } from "../../error.js";
import { generateMutedUserQuery } from "../../common/generate-muted-user-query.js";
import { generateBlockedUserQuery } from "../../common/generate-block-query.js";
@ -20,6 +22,14 @@ export const meta = {
ref: "Note",
},
},
errors: {
ltlDisabled: {
message: "Local timeline has been disabled.",
code: "LTL_DISABLED",
id: "45a6eb02-7695-4393-b023-dd3be9aaaefd",
},
}
} as const;
export const paramDef = {
@ -38,6 +48,13 @@ export const paramDef = {
} as const;
export default define(meta, paramDef, async (ps, user) => {
const m = await fetchMeta();
if (m.disableLocalTimeline || m.localTimelineRequiresCredential) {
if (user == null || !(user.isAdmin || user.isModerator)) {
throw new ApiError(meta.errors.ltlDisabled);
}
}
const max = 30;
const day = 1000 * 60 * 60 * 24 * ps.days;

View file

@ -72,7 +72,7 @@ export const paramDef = {
export default define(meta, paramDef, async (ps, user) => {
const m = await fetchMeta();
if (m.disableLocalTimeline) {
if (m.disableLocalTimeline || m.localTimelineRequiresCredential) {
if (user == null || !(user.isAdmin || user.isModerator)) {
throw new ApiError(meta.errors.ltlDisabled);
}

View file

@ -18,7 +18,7 @@ export default class extends Channel {
public async init(params: any) {
const meta = await fetchMeta();
if (meta.disableLocalTimeline) {
if (meta.disableLocalTimeline || meta.localTimelineRequiresCredential && this.user == null) {
if (this.user == null || !(this.user.isAdmin || this.user.isModerator))
return;
}

View file

@ -74,6 +74,7 @@ const nodeinfo2 = async () => {
repositoryUrl: meta.repositoryUrl,
feedbackUrl: meta.feedbackUrl,
disableRegistration: meta.disableRegistration,
localTimelineRequiresCredential: meta.localTimelineRequiresCredential,
disableLocalTimeline: meta.disableLocalTimeline,
disableRecommendedTimeline: meta.disableRecommendedTimeline,
disableGlobalTimeline: meta.disableGlobalTimeline,

View file

@ -221,7 +221,7 @@ import { $i } from "@/account";
import { instance } from "@/instance";
const isLocalTimelineAvailable =
!instance.disableLocalTimeline ||
(!instance.disableLocalTimeline && (!instance.localTimelineRequiresCredential || $i != null)) ||
($i != null && ($i.isModerator || $i.isAdmin));
const isRecommendedTimelineAvailable =
!instance.disableRecommendedTimeline ||

View file

@ -123,6 +123,12 @@
class="_formBlock"
>{{ i18n.ts.enableLocalTimeline }}</FormSwitch
>
<FormSwitch
v-if="enableLocalTimeline"
v-model="localTimelineRequiresCredential"
class="_formBlock"
>{{ i18n.ts.localTimelineRequiresCredential }}</FormSwitch
>
<FormSwitch
v-model="enableGlobalTimeline"
class="_formBlock"
@ -433,6 +439,7 @@ let backgroundImageUrl: string | null = $ref(null);
let themeColor: any = $ref(null);
let defaultLightTheme: any = $ref(null);
let defaultDarkTheme: any = $ref(null);
let localTimelineRequiresCredential: boolean = $ref(false);
let enableLocalTimeline: boolean = $ref(false);
let enableGlobalTimeline: boolean = $ref(false);
let enableRecommendedTimeline: boolean = $ref(false);
@ -471,6 +478,7 @@ async function init() {
maintainerName = meta.maintainerName;
maintainerEmail = meta.maintainerEmail;
donationLink = meta.donationLink;
localTimelineRequiresCredential = meta.localTimelineRequiresCredential;
enableLocalTimeline = !meta.disableLocalTimeline;
enableGlobalTimeline = !meta.disableGlobalTimeline;
enableRecommendedTimeline = !meta.disableRecommendedTimeline;
@ -516,6 +524,7 @@ function save() {
maintainerName,
maintainerEmail,
donationLink,
localTimelineRequiresCredential: localTimelineRequiresCredential,
disableLocalTimeline: !enableLocalTimeline,
disableGlobalTimeline: !enableGlobalTimeline,
disableRecommendedTimeline: !enableRecommendedTimeline,

View file

@ -85,7 +85,7 @@ if (defaultStore.reactiveState.tutorial.value !== -1) {
}
const isLocalTimelineAvailable =
!instance.disableLocalTimeline ||
(!instance.disableLocalTimeline && (!instance.localTimelineRequiresCredential || $i != null)) ||
($i != null && ($i.isModerator || $i.isAdmin));
const isRecommendedTimelineAvailable = !instance.disableRecommendedTimeline;
const isGlobalTimelineAvailable =

View file

@ -7687,7 +7687,7 @@
},
{
"kind": "Content",
"text": "{\n maintainerName: string | null;\n maintainerEmail: string | null;\n version: string;\n name: string | null;\n uri: string;\n description: string | null;\n tosUrl: string | null;\n disableRegistration: boolean;\n disableLocalTimeline: boolean;\n disableRecommendedTimeline: boolean;\n disableGlobalTimeline: boolean;\n driveCapacityPerLocalUserMb: number;\n driveCapacityPerRemoteUserMb: number;\n enableHcaptcha: boolean;\n hcaptchaSiteKey: string | null;\n enableRecaptcha: boolean;\n recaptchaSiteKey: string | null;\n swPublickey: string | null;\n maxNoteTextLength: number;\n enableEmail: boolean;\n enableGithubIntegration: boolean;\n enableDiscordIntegration: boolean;\n searchEngine: string;\n emojis: "
"text": "{\n maintainerName: string | null;\n maintainerEmail: string | null;\n version: string;\n name: string | null;\n uri: string;\n description: string | null;\n tosUrl: string | null;\n disableRegistration: boolean;\n localTimelineRequiresCredential: boolean;\n disableLocalTimeline: boolean;\n disableRecommendedTimeline: boolean;\n disableGlobalTimeline: boolean;\n driveCapacityPerLocalUserMb: number;\n driveCapacityPerRemoteUserMb: number;\n enableHcaptcha: boolean;\n hcaptchaSiteKey: string | null;\n enableRecaptcha: boolean;\n recaptchaSiteKey: string | null;\n swPublickey: string | null;\n maxNoteTextLength: number;\n enableEmail: boolean;\n enableGithubIntegration: boolean;\n enableDiscordIntegration: boolean;\n searchEngine: string;\n emojis: "
},
{
"kind": "Reference",

View file

@ -2291,6 +2291,7 @@ type LiteInstanceMetadata = {
description: string | null;
tosUrl: string | null;
disableRegistration: boolean;
localTimelineRequiresCredential: boolean;
disableLocalTimeline: boolean;
disableRecommendedTimeline: boolean;
disableGlobalTimeline: boolean;

View file

@ -16,6 +16,7 @@ export type LiteInstanceMetadata = {
description: string | null;
tosUrl: string | null;
disableRegistration: boolean;
localTimelineRequiresCredential: boolean;
disableLocalTimeline: boolean;
disableRecommendedTimeline: boolean;
disableGlobalTimeline: boolean;

View file

@ -285,6 +285,7 @@ export type LiteInstanceMetadata = {
description: string | null;
tosUrl: string | null;
disableRegistration: boolean;
localTimelineRequiresCredential: boolean;
disableLocalTimeline: boolean;
disableRecommendedTimeline: boolean;
disableGlobalTimeline: boolean;