From faa8f4ccf03fbe1f02df7c30bad5bacdbb4e0f6a Mon Sep 17 00:00:00 2001 From: nullobsi Date: Mon, 19 Jul 2021 15:41:23 -0700 Subject: [PATCH 01/14] Add migration for allowedHosts, secureMode, privateMode --- .../1626733991004-allowlist-secure-mode.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 packages/backend/migration/1626733991004-allowlist-secure-mode.js diff --git a/packages/backend/migration/1626733991004-allowlist-secure-mode.js b/packages/backend/migration/1626733991004-allowlist-secure-mode.js new file mode 100644 index 000000000..aa3fcf875 --- /dev/null +++ b/packages/backend/migration/1626733991004-allowlist-secure-mode.js @@ -0,0 +1,17 @@ + + +export class allowlistSecureMode1626733991004 { + name = 'allowlistSecureMode1626733991004'; + async up(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" ADD "allowedHosts" character varying(256) [] default '{}'`); + await queryRunner.query(`ALTER TABLE "meta" ADD "secureMode" bool default false`); + await queryRunner.query(`ALTER TABLE "meta" ADD "privateMode" bool default false`); + } + + async down(queryRunner) { + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "allowedHosts"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "secureMode"`); + await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "privateMode"`); + } +} + -- 2.43.0 From ecf96827478e472280a81dae17b33ab9fd585300 Mon Sep 17 00:00:00 2001 From: nullobsi Date: Tue, 20 Jul 2021 09:45:41 -0700 Subject: [PATCH 02/14] Add Secure Mode and Private Mode - Add instance actor - Add private mode, which uses an allowlist - Add Secure Mode, restricts access to blocked instances --- packages/backend/src/models/entities/meta.ts | 15 +++ .../backend/src/queue/processors/deliver.ts | 4 + .../backend/src/queue/processors/inbox.ts | 5 + .../src/remote/activitypub/check-fetch.ts | 73 ++++++++++ .../src/remote/activitypub/resolver.ts | 4 + packages/backend/src/server/activitypub.ts | 127 ++++++++++++++++-- .../src/server/activitypub/featured.ts | 16 ++- .../src/server/activitypub/followers.ts | 15 ++- .../src/server/activitypub/following.ts | 15 ++- .../backend/src/server/activitypub/outbox.ts | 16 ++- .../backend/src/server/api/endpoints/meta.ts | 10 ++ 11 files changed, 288 insertions(+), 12 deletions(-) create mode 100644 packages/backend/src/remote/activitypub/check-fetch.ts diff --git a/packages/backend/src/models/entities/meta.ts b/packages/backend/src/models/entities/meta.ts index c6a4c9f41..5ec3a3d50 100644 --- a/packages/backend/src/models/entities/meta.ts +++ b/packages/backend/src/models/entities/meta.ts @@ -77,6 +77,21 @@ export class Meta { }) public blockedHosts: string[]; + @Column('boolean', { + default: false + }) + public secureMode: boolean; + + @Column('boolean', { + default: false + }) + public privateMode: boolean; + + @Column('varchar', { + length: 256, array: true, default: '{}' + }) + public allowedHosts: string[]; + @Column('varchar', { length: 512, array: true, default: '{/featured,/channels,/explore,/pages,/about-misskey}', }) diff --git a/packages/backend/src/queue/processors/deliver.ts b/packages/backend/src/queue/processors/deliver.ts index 291c05766..01ba4381a 100644 --- a/packages/backend/src/queue/processors/deliver.ts +++ b/packages/backend/src/queue/processors/deliver.ts @@ -28,6 +28,10 @@ export default async (job: Bull.Job) => { return 'skip (blocked)'; } + if (meta.privateMode && !meta.allowedHosts.includes(toPuny(host))) { + return 'skip (not allowed)'; + } + // isSuspendedなら中断 let suspendedHosts = suspendedHostsCache.get(null); if (suspendedHosts == null) { diff --git a/packages/backend/src/queue/processors/inbox.ts b/packages/backend/src/queue/processors/inbox.ts index 198dde605..422632059 100644 --- a/packages/backend/src/queue/processors/inbox.ts +++ b/packages/backend/src/queue/processors/inbox.ts @@ -39,6 +39,11 @@ export default async (job: Bull.Job): Promise => { return `Blocked request: ${host}`; } + // 非公開モードなら許可なインスタンスのみ + if (meta.privateMode && !meta.allowedHosts.includes(host)) { + return `Blocked request: ${host}`; + } + const keyIdLower = signature.keyId.toLowerCase(); if (keyIdLower.startsWith('acct:')) { return `Old keyId is no longer supported. ${keyIdLower}`; diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts new file mode 100644 index 000000000..8a53396b6 --- /dev/null +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -0,0 +1,73 @@ +import config from '@/config/index.js'; +import { IncomingMessage } from 'http'; +import { fetchMeta } from '@/misc/fetch-meta.js'; +import httpSignature from '@peertube/http-signature'; +import { URL } from 'url'; +import { toPuny } from '@/misc/convert-host.js'; +import DbResolver from '@/remote/activitypub/db-resolver.js'; +import { getApId } from '@/remote/activitypub/type.js'; + + +export default async function checkFetch(req: IncomingMessage): Promise { + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + let signature; + + try { + signature = httpSignature.parseRequest(req, { 'headers': [] }); + } catch (e) { + return 401; + } + + const keyId = new URL(signature.keyId); + const host = toPuny(keyId.hostname); + + if (meta.blockedHosts.includes(host)) { + return 403; + } + + if (meta.privateMode && host !== config.host && !meta.allowedHosts.includes(host)) { + return 403; + } + + const keyIdLower = signature.keyId.toLowerCase(); + if (keyIdLower.startsWith('acct:')) { + // Old keyId is no longer supported. + return 401; + } + + const dbResolver = new DbResolver(); + + // HTTP-Signature keyIdを元にDBから取得 + let authUser = await dbResolver.getAuthUserFromKeyId(signature.keyId); + + // keyIdでわからなければ、resolveしてみる + if (authUser == null) { + try { + keyId.hash = ''; + authUser = await dbResolver.getAuthUserFromApId(getApId(keyId.toString())); + } catch (e) { + // できなければ駄目 + return 403; + } + } + + // publicKey がなくても終了 + if (authUser?.key == null) { + return 403; + } + + // もう一回チェック + if (authUser.user.host !== host) { + return 403; + } + + // HTTP-Signatureの検証 + const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem); + + if (!httpSignatureValidated) { + return 403; + } + } + return 200; +} diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 962408177..24fdbe277 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -72,6 +72,10 @@ export default class Resolver { throw new Error('Instance is blocked'); } + if (meta.privateMode && config.host !== host && !meta.allowedHosts.includes(host)) { + throw new Error('Instance is not allowed'); + } + if (config.signToActivityPubGet && !this.user) { this.user = await getInstanceActor(); } diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index cd5f917c4..250a39bf0 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -12,12 +12,15 @@ import Followers from './activitypub/followers.js'; import Following from './activitypub/following.js'; import Featured from './activitypub/featured.js'; import { inbox as processInbox } from '@/queue/index.js'; -import { isSelfHost } from '@/misc/convert-host.js'; +import { isSelfHost, toPuny } from '@/misc/convert-host.js'; import { Notes, Users, Emojis, NoteReactions } from '@/models/index.js'; import { ILocalUser, User } from '@/models/entities/user.js'; import { In, IsNull, Not } from 'typeorm'; import { renderLike } from '@/remote/activitypub/renderer/like.js'; import { getUserKeypair } from '@/misc/keypair-store.js'; +import checkFetch from '@/remote/activitypub/check-fetch.js'; +import { getInstanceActor } from '@/services/instance-actor.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; import renderFollow from '@/remote/activitypub/renderer/follow.js'; // Init router @@ -66,6 +69,12 @@ router.post('/users/:user/inbox', json(), inbox); router.get('/notes/:note', async (ctx, next) => { if (!isActivityPubReq(ctx)) return await next(); + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const note = await Notes.findOneBy({ id: ctx.params.note, visibility: In(['public' as const, 'home' as const]), @@ -88,12 +97,24 @@ router.get('/notes/:note', async (ctx, next) => { } ctx.body = renderActivity(await renderNote(note, false)); - ctx.set('Cache-Control', 'public, max-age=180'); + + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }); // note activity router.get('/notes/:note/activity', async ctx => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const note = await Notes.findOneBy({ id: ctx.params.note, userHost: IsNull(), @@ -107,7 +128,12 @@ router.get('/notes/:note/activity', async ctx => { } ctx.body = renderActivity(await packActivity(note)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }); @@ -125,6 +151,20 @@ router.get('/users/:user/collections/featured', Featured); // publickey router.get('/users/:user/publickey', async ctx => { + const instanceActor = await getInstanceActor(); + if (ctx.params.user === instanceActor.id) { + ctx.body = renderActivity(renderKey(instanceActor, await getUserKeypair(instanceActor.id))); + ctx.set('Cache-Control', 'public, max-age=180'); + setResponseType(ctx); + return; + } + + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const user = await Users.findOneBy({ @@ -141,7 +181,12 @@ router.get('/users/:user/publickey', async ctx => { if (Users.isLocalUser(user)) { ctx.body = renderActivity(renderKey(user, keypair)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); } else { ctx.status = 400; @@ -156,13 +201,30 @@ async function userInfo(ctx: Router.RouterContext, user: User | null) { } ctx.body = renderActivity(await renderPerson(user as ILocalUser)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); } router.get('/users/:user', async (ctx, next) => { if (!isActivityPubReq(ctx)) return await next(); + const instanceActor = await getInstanceActor(); + if (ctx.params.user === instanceActor.id) { + await userInfo(ctx, instanceActor); + return; + } + + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const user = await Users.findOneBy({ @@ -177,6 +239,18 @@ router.get('/users/:user', async (ctx, next) => { router.get('/@:user', async (ctx, next) => { if (!isActivityPubReq(ctx)) return await next(); + if (ctx.params.user === 'instance.actor') { + const instanceActor = await getInstanceActor(); + await userInfo(ctx, instanceActor); + return; + } + + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const user = await Users.findOneBy({ usernameLower: ctx.params.user.toLowerCase(), host: IsNull(), @@ -185,10 +259,21 @@ router.get('/@:user', async (ctx, next) => { await userInfo(ctx, user); }); + +router.get('/actor', async (ctx, next) => { + const instanceActor = await getInstanceActor(); + await userInfo(ctx, instanceActor); +}); //#endregion // emoji router.get('/emojis/:emoji', async ctx => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const emoji = await Emojis.findOneBy({ host: IsNull(), name: ctx.params.emoji, @@ -200,12 +285,23 @@ router.get('/emojis/:emoji', async ctx => { } ctx.body = renderActivity(await renderEmoji(emoji)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }); // like router.get('/likes/:like', async ctx => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const reaction = await NoteReactions.findOneBy({ id: ctx.params.like }); if (reaction == null) { @@ -221,12 +317,22 @@ router.get('/likes/:like', async ctx => { } ctx.body = renderActivity(await renderLike(reaction, note)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }); // follow router.get('/follows/:follower/:followee', async ctx => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } // This may be used before the follow is completed, so we do not // check if the following exists. @@ -247,7 +353,12 @@ router.get('/follows/:follower/:followee', async ctx => { } ctx.body = renderActivity(renderFollow(follower, followee)); - ctx.set('Cache-Control', 'public, max-age=180'); + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }); diff --git a/packages/backend/src/server/activitypub/featured.ts b/packages/backend/src/server/activitypub/featured.ts index c03fd1049..87e4f8320 100644 --- a/packages/backend/src/server/activitypub/featured.ts +++ b/packages/backend/src/server/activitypub/featured.ts @@ -6,8 +6,16 @@ import { setResponseType } from '../activitypub.js'; import renderNote from '@/remote/activitypub/renderer/note.js'; import { Users, Notes, UserNotePinings } from '@/models/index.js'; import { IsNull } from 'typeorm'; +import checkFetch from '@/remote/activitypub/check-fetch.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const user = await Users.findOneBy({ @@ -36,6 +44,12 @@ export default async (ctx: Router.RouterContext) => { ); ctx.body = renderActivity(rendered); - ctx.set('Cache-Control', 'public, max-age=180'); + + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } setResponseType(ctx); }; diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts index beb48713a..833f0e77f 100644 --- a/packages/backend/src/server/activitypub/followers.ts +++ b/packages/backend/src/server/activitypub/followers.ts @@ -9,8 +9,16 @@ import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; import { Users, Followings, UserProfiles } from '@/models/index.js'; import { Following } from '@/models/entities/following.js'; import { setResponseType } from '../activitypub.js'; +import checkFetch from '@/remote/activitypub/check-fetch.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const cursor = ctx.request.query.cursor; @@ -89,7 +97,12 @@ export default async (ctx: Router.RouterContext) => { // index page const rendered = renderOrderedCollection(partOf, user.followersCount, `${partOf}?page=true`); ctx.body = renderActivity(rendered); - ctx.set('Cache-Control', 'public, max-age=180'); setResponseType(ctx); } + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } }; diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts index 3a25a6316..f843d79f0 100644 --- a/packages/backend/src/server/activitypub/following.ts +++ b/packages/backend/src/server/activitypub/following.ts @@ -9,8 +9,16 @@ import renderFollowUser from '@/remote/activitypub/renderer/follow-user.js'; import { Users, Followings, UserProfiles } from '@/models/index.js'; import { Following } from '@/models/entities/following.js'; import { setResponseType } from '../activitypub.js'; +import checkFetch from '@/remote/activitypub/check-fetch.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const cursor = ctx.request.query.cursor; @@ -89,7 +97,12 @@ export default async (ctx: Router.RouterContext) => { // index page const rendered = renderOrderedCollection(partOf, user.followingCount, `${partOf}?page=true`); ctx.body = renderActivity(rendered); - ctx.set('Cache-Control', 'public, max-age=180'); setResponseType(ctx); } + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } }; diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index 7a2586998..4a6b5caff 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -13,8 +13,16 @@ import { Users, Notes } from '@/models/index.js'; import { Note } from '@/models/entities/note.js'; import { makePaginationQuery } from '../api/common/make-pagination-query.js'; import { setResponseType } from '../activitypub.js'; +import checkFetch from '@/remote/activitypub/check-fetch.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { + const verify = await checkFetch(ctx.req); + if (verify != 200) { + ctx.status = verify; + return; + } + const userId = ctx.params.user; const sinceId = ctx.request.query.since_id; @@ -89,9 +97,15 @@ export default async (ctx: Router.RouterContext) => { `${partOf}?page=true&since_id=000000000000000000000000`, ); ctx.body = renderActivity(rendered); - ctx.set('Cache-Control', 'public, max-age=180'); + setResponseType(ctx); } + const meta = await fetchMeta(); + if (meta.secureMode || meta.privateMode) { + ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + } else { + ctx.set('Cache-Control', 'public, max-age=180'); + } }; /** diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 2b6de3756..01c54503c 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -246,6 +246,16 @@ export const meta = { }, }, }, + secureMode: { + type: 'boolean', + optional: true, nullable: false, + default: false, + }, + privateMode: { + type: 'boolean', + optional: true, nullable: false, + default: false, + }, }, }, } as const; -- 2.43.0 From 7dc19b861d350ef26385020f7466c534ee4f0de2 Mon Sep 17 00:00:00 2001 From: nullobsi Date: Tue, 20 Jul 2021 11:51:59 -0700 Subject: [PATCH 03/14] In private mode, block access to many public APIs --- packages/backend/src/server/api/call.ts | 13 +++++++++++++ packages/backend/src/server/api/endpoints.ts | 6 ++++++ .../src/server/api/endpoints/announcements.ts | 1 + .../server/api/endpoints/channels/featured.ts | 1 + .../src/server/api/endpoints/channels/show.ts | 1 + .../server/api/endpoints/channels/timeline.ts | 1 + .../api/endpoints/charts/active-users.ts | 1 + .../server/api/endpoints/charts/ap-request.ts | 1 + .../src/server/api/endpoints/charts/drive.ts | 1 + .../server/api/endpoints/charts/federation.ts | 1 + .../src/server/api/endpoints/charts/hashtag.ts | 1 + .../server/api/endpoints/charts/instance.ts | 1 + .../src/server/api/endpoints/charts/notes.ts | 1 + .../server/api/endpoints/charts/user/drive.ts | 1 + .../api/endpoints/charts/user/following.ts | 1 + .../server/api/endpoints/charts/user/notes.ts | 1 + .../api/endpoints/charts/user/reactions.ts | 1 + .../src/server/api/endpoints/charts/users.ts | 1 + .../src/server/api/endpoints/clips/notes.ts | 1 + .../src/server/api/endpoints/clips/show.ts | 1 + .../api/endpoints/federation/followers.ts | 1 + .../api/endpoints/federation/following.ts | 1 + .../api/endpoints/federation/instances.ts | 1 + .../api/endpoints/federation/show-instance.ts | 1 + .../server/api/endpoints/federation/users.ts | 1 + .../server/api/endpoints/gallery/featured.ts | 1 + .../server/api/endpoints/gallery/popular.ts | 1 + .../src/server/api/endpoints/gallery/posts.ts | 1 + .../server/api/endpoints/gallery/posts/show.ts | 1 + .../api/endpoints/get-online-users-count.ts | 1 + .../src/server/api/endpoints/hashtags/list.ts | 1 + .../server/api/endpoints/hashtags/search.ts | 1 + .../src/server/api/endpoints/hashtags/show.ts | 1 + .../src/server/api/endpoints/hashtags/trend.ts | 1 + .../src/server/api/endpoints/hashtags/users.ts | 1 + .../backend/src/server/api/endpoints/meta.ts | 18 +++++++++++++----- .../backend/src/server/api/endpoints/notes.ts | 1 + .../src/server/api/endpoints/notes/children.ts | 3 ++- .../src/server/api/endpoints/notes/clips.ts | 1 + .../server/api/endpoints/notes/conversation.ts | 1 + .../src/server/api/endpoints/notes/featured.ts | 1 + .../api/endpoints/notes/global-timeline.ts | 1 + .../api/endpoints/notes/local-timeline.ts | 1 + .../server/api/endpoints/notes/reactions.ts | 1 + .../src/server/api/endpoints/notes/renotes.ts | 1 + .../src/server/api/endpoints/notes/replies.ts | 1 + .../api/endpoints/notes/search-by-tag.ts | 1 + .../src/server/api/endpoints/notes/search.ts | 1 + .../src/server/api/endpoints/notes/show.ts | 1 + .../server/api/endpoints/notes/translate.ts | 1 + .../src/server/api/endpoints/pages/featured.ts | 1 + .../src/server/api/endpoints/pages/show.ts | 1 + .../src/server/api/endpoints/pinned-users.ts | 1 + .../src/server/api/endpoints/server-info.ts | 1 + .../backend/src/server/api/endpoints/stats.ts | 1 + .../backend/src/server/api/endpoints/users.ts | 1 + .../src/server/api/endpoints/users/clips.ts | 1 + .../server/api/endpoints/users/followers.ts | 1 + .../server/api/endpoints/users/following.ts | 1 + .../api/endpoints/users/gallery/posts.ts | 1 + .../users/get-frequently-replied-users.ts | 1 + .../src/server/api/endpoints/users/notes.ts | 1 + .../src/server/api/endpoints/users/pages.ts | 1 + .../server/api/endpoints/users/reactions.ts | 1 + .../users/search-by-username-and-host.ts | 1 + .../src/server/api/endpoints/users/search.ts | 1 + .../src/server/api/endpoints/users/show.ts | 1 + .../src/server/api/endpoints/users/stats.ts | 1 + 68 files changed, 98 insertions(+), 6 deletions(-) diff --git a/packages/backend/src/server/api/call.ts b/packages/backend/src/server/api/call.ts index fe1698dbc..29769d602 100644 --- a/packages/backend/src/server/api/call.ts +++ b/packages/backend/src/server/api/call.ts @@ -7,6 +7,8 @@ import { limiter } from './limiter.js'; import endpoints, { IEndpointMeta } from './endpoints.js'; import { ApiError } from './error.js'; import { apiLogger } from './logger.js'; +import { AccessToken } from '@/models/entities/access-token.js'; +import { fetchMeta } from '@/misc/fetch-meta.js'; const accessDenied = { message: 'Access denied.', @@ -93,6 +95,17 @@ export default async (endpoint: string, user: CacheableLocalUser | null | undefi }); } + // private mode + const meta = await fetchMeta(); + if (meta.privateMode && ep.meta.requireCredentialPrivateMode && user == null) { + throw new ApiError({ + message: 'Credential required.', + code: 'CREDENTIAL_REQUIRED', + id: '1384574d-a912-4b81-8601-c7b1c4085df1', + httpStatusCode: 401 + }); + } + // Cast non JSON input if ((ep.meta.requireFile || ctx?.method === 'GET') && ep.params.properties) { for (const k of Object.keys(ep.params.properties)) { diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 9eedfd53c..6693a4bf6 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -692,6 +692,12 @@ export interface IEndpointMeta { */ readonly secure?: boolean; + /** + * プライベートモードでなら、このエンドポイントにリクエストするときにユーザー情報が必要か否か + * 省略した場合は false として解釈されます + */ + readonly requireCredentialPrivateMode?: boolean; + /** * エンドポイントの種類 * パーミッションの実現に利用されます。 diff --git a/packages/backend/src/server/api/endpoints/announcements.ts b/packages/backend/src/server/api/endpoints/announcements.ts index 23cb93c9a..189de042b 100644 --- a/packages/backend/src/server/api/endpoints/announcements.ts +++ b/packages/backend/src/server/api/endpoints/announcements.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['meta'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/channels/featured.ts b/packages/backend/src/server/api/endpoints/channels/featured.ts index 73980c0fa..13ad6ca7d 100644 --- a/packages/backend/src/server/api/endpoints/channels/featured.ts +++ b/packages/backend/src/server/api/endpoints/channels/featured.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['channels'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/channels/show.ts b/packages/backend/src/server/api/endpoints/channels/show.ts index 87665a986..1c8461af4 100644 --- a/packages/backend/src/server/api/endpoints/channels/show.ts +++ b/packages/backend/src/server/api/endpoints/channels/show.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['channels'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/channels/timeline.ts b/packages/backend/src/server/api/endpoints/channels/timeline.ts index deaa29901..18ba6b2e3 100644 --- a/packages/backend/src/server/api/endpoints/channels/timeline.ts +++ b/packages/backend/src/server/api/endpoints/channels/timeline.ts @@ -8,6 +8,7 @@ export const meta = { tags: ['notes', 'channels'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/charts/active-users.ts b/packages/backend/src/server/api/endpoints/charts/active-users.ts index ea2379429..216676020 100644 --- a/packages/backend/src/server/api/endpoints/charts/active-users.ts +++ b/packages/backend/src/server/api/endpoints/charts/active-users.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts', 'users'], + requireCredentialPrivateMode: true, res: getJsonSchema(activeUsersChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/ap-request.ts b/packages/backend/src/server/api/endpoints/charts/ap-request.ts index 06dee250e..a8f6e4564 100644 --- a/packages/backend/src/server/api/endpoints/charts/ap-request.ts +++ b/packages/backend/src/server/api/endpoints/charts/ap-request.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts'], + requireCredentialPrivateMode: true, res: getJsonSchema(apRequestChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/drive.ts b/packages/backend/src/server/api/endpoints/charts/drive.ts index dd2c2d683..14f82e39d 100644 --- a/packages/backend/src/server/api/endpoints/charts/drive.ts +++ b/packages/backend/src/server/api/endpoints/charts/drive.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts', 'drive'], + requireCredentialPrivateMode: true, res: getJsonSchema(driveChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/federation.ts b/packages/backend/src/server/api/endpoints/charts/federation.ts index 8c35b3c46..141e005ee 100644 --- a/packages/backend/src/server/api/endpoints/charts/federation.ts +++ b/packages/backend/src/server/api/endpoints/charts/federation.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts'], + requireCredentialPrivateMode: true, res: getJsonSchema(federationChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/hashtag.ts b/packages/backend/src/server/api/endpoints/charts/hashtag.ts index 77e24a62c..d34153bc1 100644 --- a/packages/backend/src/server/api/endpoints/charts/hashtag.ts +++ b/packages/backend/src/server/api/endpoints/charts/hashtag.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts', 'hashtags'], + requireCredentialPrivateMode: true, res: getJsonSchema(hashtagChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/instance.ts b/packages/backend/src/server/api/endpoints/charts/instance.ts index 817d51ad0..3d9619d24 100644 --- a/packages/backend/src/server/api/endpoints/charts/instance.ts +++ b/packages/backend/src/server/api/endpoints/charts/instance.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts'], + requireCredentialPrivateMode: true, res: getJsonSchema(instanceChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/notes.ts b/packages/backend/src/server/api/endpoints/charts/notes.ts index 951adf540..42befed27 100644 --- a/packages/backend/src/server/api/endpoints/charts/notes.ts +++ b/packages/backend/src/server/api/endpoints/charts/notes.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts', 'notes'], + requireCredentialPrivateMode: true, res: getJsonSchema(notesChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/user/drive.ts b/packages/backend/src/server/api/endpoints/charts/user/drive.ts index f165b4022..cb73b4ac9 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/drive.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/drive.ts @@ -4,6 +4,7 @@ import define from '../../../define.js'; export const meta = { tags: ['charts', 'drive', 'users'], + requireCredentialPrivateMode: true, res: getJsonSchema(perUserDriveChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/user/following.ts b/packages/backend/src/server/api/endpoints/charts/user/following.ts index f5d42e21c..697a5f37a 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/following.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/following.ts @@ -4,6 +4,7 @@ import { perUserFollowingChart } from '@/services/chart/index.js'; export const meta = { tags: ['charts', 'users', 'following'], + requireCredentialPrivateMode: true, res: getJsonSchema(perUserFollowingChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/user/notes.ts b/packages/backend/src/server/api/endpoints/charts/user/notes.ts index aefe550d4..5b576754d 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/notes.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/notes.ts @@ -4,6 +4,7 @@ import define from '../../../define.js'; export const meta = { tags: ['charts', 'users', 'notes'], + requireCredentialPrivateMode: true, res: getJsonSchema(perUserNotesChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts index 6bc6b56bf..61c4527b9 100644 --- a/packages/backend/src/server/api/endpoints/charts/user/reactions.ts +++ b/packages/backend/src/server/api/endpoints/charts/user/reactions.ts @@ -4,6 +4,7 @@ import define from '../../../define.js'; export const meta = { tags: ['charts', 'users', 'reactions'], + requireCredentialPrivateMode: true, res: getJsonSchema(perUserReactionsChart.schema), diff --git a/packages/backend/src/server/api/endpoints/charts/users.ts b/packages/backend/src/server/api/endpoints/charts/users.ts index 338e8fd33..0c799287c 100644 --- a/packages/backend/src/server/api/endpoints/charts/users.ts +++ b/packages/backend/src/server/api/endpoints/charts/users.ts @@ -4,6 +4,7 @@ import define from '../../define.js'; export const meta = { tags: ['charts', 'users'], + requireCredentialPrivateMode: true, res: getJsonSchema(usersChart.schema), diff --git a/packages/backend/src/server/api/endpoints/clips/notes.ts b/packages/backend/src/server/api/endpoints/clips/notes.ts index 4ace747ef..eea6f0a0d 100644 --- a/packages/backend/src/server/api/endpoints/clips/notes.ts +++ b/packages/backend/src/server/api/endpoints/clips/notes.ts @@ -10,6 +10,7 @@ export const meta = { tags: ['account', 'notes', 'clips'], requireCredential: false, + requireCredentialPrivateMode: true, kind: 'read:account', diff --git a/packages/backend/src/server/api/endpoints/clips/show.ts b/packages/backend/src/server/api/endpoints/clips/show.ts index c3d73c168..aec4c1253 100644 --- a/packages/backend/src/server/api/endpoints/clips/show.ts +++ b/packages/backend/src/server/api/endpoints/clips/show.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['clips', 'account'], requireCredential: false, + requireCredentialPrivateMode: true, kind: 'read:account', diff --git a/packages/backend/src/server/api/endpoints/federation/followers.ts b/packages/backend/src/server/api/endpoints/federation/followers.ts index 7b1197d1e..8a04df2d5 100644 --- a/packages/backend/src/server/api/endpoints/federation/followers.ts +++ b/packages/backend/src/server/api/endpoints/federation/followers.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['federation'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/federation/following.ts b/packages/backend/src/server/api/endpoints/federation/following.ts index ed1f142d8..fe41eefa4 100644 --- a/packages/backend/src/server/api/endpoints/federation/following.ts +++ b/packages/backend/src/server/api/endpoints/federation/following.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['federation'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index 39c49c266..9469d1871 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['federation'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/federation/show-instance.ts b/packages/backend/src/server/api/endpoints/federation/show-instance.ts index 2fbb8a15c..92298f672 100644 --- a/packages/backend/src/server/api/endpoints/federation/show-instance.ts +++ b/packages/backend/src/server/api/endpoints/federation/show-instance.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['federation'], requireCredential: false, + requireCredentialPrivateMode: true, res: { oneOf: [{ diff --git a/packages/backend/src/server/api/endpoints/federation/users.ts b/packages/backend/src/server/api/endpoints/federation/users.ts index 65ad9f88d..a9b3f3a8c 100644 --- a/packages/backend/src/server/api/endpoints/federation/users.ts +++ b/packages/backend/src/server/api/endpoints/federation/users.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['federation'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/gallery/featured.ts b/packages/backend/src/server/api/endpoints/gallery/featured.ts index e6acd3691..52232c5cc 100644 --- a/packages/backend/src/server/api/endpoints/gallery/featured.ts +++ b/packages/backend/src/server/api/endpoints/gallery/featured.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['gallery'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/gallery/popular.ts b/packages/backend/src/server/api/endpoints/gallery/popular.ts index c4c8982fc..5286dcd8b 100644 --- a/packages/backend/src/server/api/endpoints/gallery/popular.ts +++ b/packages/backend/src/server/api/endpoints/gallery/popular.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['gallery'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/gallery/posts.ts b/packages/backend/src/server/api/endpoints/gallery/posts.ts index 428ba9cc7..f556ec513 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts.ts @@ -4,6 +4,7 @@ import { GalleryPosts } from '@/models/index.js'; export const meta = { tags: ['gallery'], + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts index 4f6dafd7c..48468f410 100644 --- a/packages/backend/src/server/api/endpoints/gallery/posts/show.ts +++ b/packages/backend/src/server/api/endpoints/gallery/posts/show.ts @@ -6,6 +6,7 @@ export const meta = { tags: ['gallery'], requireCredential: false, + requireCredentialPrivateMode: true, errors: { noSuchPost: { diff --git a/packages/backend/src/server/api/endpoints/get-online-users-count.ts b/packages/backend/src/server/api/endpoints/get-online-users-count.ts index 56c550297..a8febe05b 100644 --- a/packages/backend/src/server/api/endpoints/get-online-users-count.ts +++ b/packages/backend/src/server/api/endpoints/get-online-users-count.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['meta'], requireCredential: false, + requireCredentialPrivateMode: true, } as const; export const paramDef = { diff --git a/packages/backend/src/server/api/endpoints/hashtags/list.ts b/packages/backend/src/server/api/endpoints/hashtags/list.ts index 50e36386c..4b18cb76a 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/list.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/list.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['hashtags'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/hashtags/search.ts b/packages/backend/src/server/api/endpoints/hashtags/search.ts index c28984477..ed1abf1a1 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/search.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/search.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['hashtags'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/hashtags/show.ts b/packages/backend/src/server/api/endpoints/hashtags/show.ts index 5b78f6ac7..409233c24 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/show.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/show.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['hashtags'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/hashtags/trend.ts b/packages/backend/src/server/api/endpoints/hashtags/trend.ts index 9cdbc8941..8795927e6 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/trend.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/trend.ts @@ -24,6 +24,7 @@ export const meta = { tags: ['hashtags'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/hashtags/users.ts b/packages/backend/src/server/api/endpoints/hashtags/users.ts index a5df21a7e..1d18a9ce7 100644 --- a/packages/backend/src/server/api/endpoints/hashtags/users.ts +++ b/packages/backend/src/server/api/endpoints/hashtags/users.ts @@ -4,6 +4,7 @@ import { normalizeForSearch } from '@/misc/normalize-for-search.js'; export const meta = { requireCredential: false, + requireCredentialPrivateMode: true, tags: ['hashtags', 'users'], diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 01c54503c..43babed9b 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -297,6 +297,12 @@ export default define(meta, paramDef, async (ps, me) => { description: instance.description, langs: instance.langs, tosUrl: instance.ToSUrl, + repositoryUrl: instance.repositoryUrl, + feedbackUrl: instance.feedbackUrl, + + secureMode: instance.secureMode, + privateMode: instance.privateMode, + disableRegistration: instance.disableRegistration, disableLocalTimeline: instance.disableLocalTimeline, disableGlobalTimeline: instance.disableGlobalTimeline, @@ -314,7 +320,7 @@ export default define(meta, paramDef, async (ps, me) => { backgroundImageUrl: instance.backgroundImageUrl, logoImageUrl: instance.logoImageUrl, maxNoteTextLength: MAX_NOTE_TEXT_LENGTH, // 後方互換性のため - emojis: await Emojis.packMany(emojis), + emojis: instance.privateMode && !me ? [] : await Emojis.packMany(emojis), defaultLightTheme: instance.defaultLightTheme, defaultDarkTheme: instance.defaultDarkTheme, enableEmail: instance.enableEmail, @@ -328,8 +334,8 @@ export default define(meta, paramDef, async (ps, me) => { translatorAvailable: instance.deeplAuthKey != null, ...(ps.detail ? { - pinnedPages: instance.pinnedPages, - pinnedClipId: instance.pinnedClipId, + pinnedPages: instance.privateMode && !me ? [] : instance.pinnedPages, + pinnedClipId: instance.privateMode && !me ? [] : instance.pinnedClipId, cacheRemoteFiles: instance.cacheRemoteFiles, requireSetup: (await Users.countBy({ host: IsNull(), @@ -338,9 +344,11 @@ export default define(meta, paramDef, async (ps, me) => { }; if (ps.detail) { - const proxyAccount = instance.proxyAccountId ? await Users.pack(instance.proxyAccountId).catch(() => null) : null; + if (!instance.privateMode || me) { + const proxyAccount = instance.proxyAccountId ? await Users.pack(instance.proxyAccountId).catch(() => null) : null; + response.proxyAccountName = proxyAccount ? proxyAccount.username : null; + } - response.proxyAccountName = proxyAccount ? proxyAccount.username : null; response.features = { registration: !instance.disableRegistration, localTimeLine: !instance.disableLocalTimeline, diff --git a/packages/backend/src/server/api/endpoints/notes.ts b/packages/backend/src/server/api/endpoints/notes.ts index 015b0338e..fc2bc3741 100644 --- a/packages/backend/src/server/api/endpoints/notes.ts +++ b/packages/backend/src/server/api/endpoints/notes.ts @@ -5,6 +5,7 @@ import { makePaginationQuery } from '../common/make-pagination-query.js'; export const meta = { tags: ['notes'], + requireCredentialPrivateMode: true, res: { type: 'array', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index 0fc2a5366..feaf94dcf 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -10,6 +10,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Get a list of children of a notes. Children includes replies as well as quote renotes that quote the respective post. A post will not be duplicated if it is a reply and a quote of a note in this thread. For depths larger than 1 the threading has to be computed by the client.', @@ -22,7 +23,7 @@ export const meta = { ref: 'Note', }, }, -} as const; +}; export const paramDef = { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/notes/clips.ts b/packages/backend/src/server/api/endpoints/notes/clips.ts index 976c11260..514386d73 100644 --- a/packages/backend/src/server/api/endpoints/notes/clips.ts +++ b/packages/backend/src/server/api/endpoints/notes/clips.ts @@ -8,6 +8,7 @@ export const meta = { tags: ['clips', 'notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/conversation.ts b/packages/backend/src/server/api/endpoints/notes/conversation.ts index 7ee052001..fa9b58848 100644 --- a/packages/backend/src/server/api/endpoints/notes/conversation.ts +++ b/packages/backend/src/server/api/endpoints/notes/conversation.ts @@ -8,6 +8,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/featured.ts b/packages/backend/src/server/api/endpoints/notes/featured.ts index dd9cc581a..0e4a454d7 100644 --- a/packages/backend/src/server/api/endpoints/notes/featured.ts +++ b/packages/backend/src/server/api/endpoints/notes/featured.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts index 925318f54..6a468f198 100644 --- a/packages/backend/src/server/api/endpoints/notes/global-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/global-timeline.ts @@ -12,6 +12,7 @@ import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], + requireCredentialPrivateMode: true, res: { type: 'array', optional: false, nullable: false, diff --git a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts index 5a495005c..e0cada191 100644 --- a/packages/backend/src/server/api/endpoints/notes/local-timeline.ts +++ b/packages/backend/src/server/api/endpoints/notes/local-timeline.ts @@ -14,6 +14,7 @@ import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes'], + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/reactions.ts b/packages/backend/src/server/api/endpoints/notes/reactions.ts index d9388b47f..f1a203c36 100644 --- a/packages/backend/src/server/api/endpoints/notes/reactions.ts +++ b/packages/backend/src/server/api/endpoints/notes/reactions.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['notes', 'reactions'], requireCredential: false, + requireCredentialPrivateMode: true, allowGet: true, cacheSec: 60, diff --git a/packages/backend/src/server/api/endpoints/notes/renotes.ts b/packages/backend/src/server/api/endpoints/notes/renotes.ts index 1fa9c5230..2f662f355 100644 --- a/packages/backend/src/server/api/endpoints/notes/renotes.ts +++ b/packages/backend/src/server/api/endpoints/notes/renotes.ts @@ -11,6 +11,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/replies.ts b/packages/backend/src/server/api/endpoints/notes/replies.ts index ab0018f58..b05ef5914 100644 --- a/packages/backend/src/server/api/endpoints/notes/replies.ts +++ b/packages/backend/src/server/api/endpoints/notes/replies.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts index 777de7221..231913223 100644 --- a/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts +++ b/packages/backend/src/server/api/endpoints/notes/search-by-tag.ts @@ -10,6 +10,7 @@ import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['notes', 'hashtags'], + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/search.ts b/packages/backend/src/server/api/endpoints/notes/search.ts index 4e2cdae80..cf3de47a3 100644 --- a/packages/backend/src/server/api/endpoints/notes/search.ts +++ b/packages/backend/src/server/api/endpoints/notes/search.ts @@ -12,6 +12,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/notes/show.ts b/packages/backend/src/server/api/endpoints/notes/show.ts index c9c148747..83a39a855 100644 --- a/packages/backend/src/server/api/endpoints/notes/show.ts +++ b/packages/backend/src/server/api/endpoints/notes/show.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/notes/translate.ts b/packages/backend/src/server/api/endpoints/notes/translate.ts index c42bf8c65..a01dcfa48 100644 --- a/packages/backend/src/server/api/endpoints/notes/translate.ts +++ b/packages/backend/src/server/api/endpoints/notes/translate.ts @@ -12,6 +12,7 @@ export const meta = { tags: ['notes'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/pages/featured.ts b/packages/backend/src/server/api/endpoints/pages/featured.ts index 5a149a626..75580778b 100644 --- a/packages/backend/src/server/api/endpoints/pages/featured.ts +++ b/packages/backend/src/server/api/endpoints/pages/featured.ts @@ -5,6 +5,7 @@ export const meta = { tags: ['pages'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/pages/show.ts b/packages/backend/src/server/api/endpoints/pages/show.ts index 5d37e86b9..54ae43deb 100644 --- a/packages/backend/src/server/api/endpoints/pages/show.ts +++ b/packages/backend/src/server/api/endpoints/pages/show.ts @@ -8,6 +8,7 @@ export const meta = { tags: ['pages'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'object', diff --git a/packages/backend/src/server/api/endpoints/pinned-users.ts b/packages/backend/src/server/api/endpoints/pinned-users.ts index 41595b47d..d2ded60a1 100644 --- a/packages/backend/src/server/api/endpoints/pinned-users.ts +++ b/packages/backend/src/server/api/endpoints/pinned-users.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/server-info.ts b/packages/backend/src/server/api/endpoints/server-info.ts index 99f3730e9..fdfbc8a6f 100644 --- a/packages/backend/src/server/api/endpoints/server-info.ts +++ b/packages/backend/src/server/api/endpoints/server-info.ts @@ -4,6 +4,7 @@ import define from '../define.js'; export const meta = { requireCredential: false, + requireCredentialPrivateMode: true, tags: ['meta'], } as const; diff --git a/packages/backend/src/server/api/endpoints/stats.ts b/packages/backend/src/server/api/endpoints/stats.ts index cc94f8bf2..0f2fb1f41 100644 --- a/packages/backend/src/server/api/endpoints/stats.ts +++ b/packages/backend/src/server/api/endpoints/stats.ts @@ -5,6 +5,7 @@ import { IsNull } from 'typeorm'; export const meta = { requireCredential: false, + requireCredentialPrivateMode: true, tags: ['meta'], diff --git a/packages/backend/src/server/api/endpoints/users.ts b/packages/backend/src/server/api/endpoints/users.ts index 3a8211374..d2f2ddcbf 100644 --- a/packages/backend/src/server/api/endpoints/users.ts +++ b/packages/backend/src/server/api/endpoints/users.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, res: { type: 'array', diff --git a/packages/backend/src/server/api/endpoints/users/clips.ts b/packages/backend/src/server/api/endpoints/users/clips.ts index 09fdf27c2..becfad52d 100644 --- a/packages/backend/src/server/api/endpoints/users/clips.ts +++ b/packages/backend/src/server/api/endpoints/users/clips.ts @@ -4,6 +4,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'clips'], + requireCredentialPrivateMode: true, description: 'Show all clips this user owns.', diff --git a/packages/backend/src/server/api/endpoints/users/followers.ts b/packages/backend/src/server/api/endpoints/users/followers.ts index 7f9f98076..4971d21b0 100644 --- a/packages/backend/src/server/api/endpoints/users/followers.ts +++ b/packages/backend/src/server/api/endpoints/users/followers.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Show everyone that follows this user.', diff --git a/packages/backend/src/server/api/endpoints/users/following.ts b/packages/backend/src/server/api/endpoints/users/following.ts index 0aaa810f7..043841aa4 100644 --- a/packages/backend/src/server/api/endpoints/users/following.ts +++ b/packages/backend/src/server/api/endpoints/users/following.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Show everyone that this user is following.', diff --git a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts index 35bf2df59..95ca77825 100644 --- a/packages/backend/src/server/api/endpoints/users/gallery/posts.ts +++ b/packages/backend/src/server/api/endpoints/users/gallery/posts.ts @@ -4,6 +4,7 @@ import { makePaginationQuery } from '../../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'gallery'], + requireCredentialPrivateMode: true, description: 'Show all gallery posts by the given user.', diff --git a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts index 56965d306..8cf3ea040 100644 --- a/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts +++ b/packages/backend/src/server/api/endpoints/users/get-frequently-replied-users.ts @@ -9,6 +9,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Get a list of other users that the specified user frequently replies to.', diff --git a/packages/backend/src/server/api/endpoints/users/notes.ts b/packages/backend/src/server/api/endpoints/users/notes.ts index 9fa56fe83..1e205eec3 100644 --- a/packages/backend/src/server/api/endpoints/users/notes.ts +++ b/packages/backend/src/server/api/endpoints/users/notes.ts @@ -11,6 +11,7 @@ import { generateBlockedUserQuery } from '../../common/generate-block-query.js'; export const meta = { tags: ['users', 'notes'], + requireCredentialPrivateMode: true, description: 'Show all notes that this user created.', res: { diff --git a/packages/backend/src/server/api/endpoints/users/pages.ts b/packages/backend/src/server/api/endpoints/users/pages.ts index b1d28af84..e1d876e6b 100644 --- a/packages/backend/src/server/api/endpoints/users/pages.ts +++ b/packages/backend/src/server/api/endpoints/users/pages.ts @@ -4,6 +4,7 @@ import { makePaginationQuery } from '../../common/make-pagination-query.js'; export const meta = { tags: ['users', 'pages'], + requireCredentialPrivateMode: true, description: 'Show all pages this user created.', diff --git a/packages/backend/src/server/api/endpoints/users/reactions.ts b/packages/backend/src/server/api/endpoints/users/reactions.ts index 4750dc4f9..144326958 100644 --- a/packages/backend/src/server/api/endpoints/users/reactions.ts +++ b/packages/backend/src/server/api/endpoints/users/reactions.ts @@ -8,6 +8,7 @@ export const meta = { tags: ['users', 'reactions'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Show all reactions this user made.', diff --git a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts index 12a45edfa..9091c32aa 100644 --- a/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts +++ b/packages/backend/src/server/api/endpoints/users/search-by-username-and-host.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Search for a user by username and/or host.', diff --git a/packages/backend/src/server/api/endpoints/users/search.ts b/packages/backend/src/server/api/endpoints/users/search.ts index 01729de66..70aaa4526 100644 --- a/packages/backend/src/server/api/endpoints/users/search.ts +++ b/packages/backend/src/server/api/endpoints/users/search.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Search for users.', diff --git a/packages/backend/src/server/api/endpoints/users/show.ts b/packages/backend/src/server/api/endpoints/users/show.ts index 846d83b49..892e37bdf 100644 --- a/packages/backend/src/server/api/endpoints/users/show.ts +++ b/packages/backend/src/server/api/endpoints/users/show.ts @@ -10,6 +10,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Show the properties of a user.', diff --git a/packages/backend/src/server/api/endpoints/users/stats.ts b/packages/backend/src/server/api/endpoints/users/stats.ts index 47f322ee9..a68b6ea40 100644 --- a/packages/backend/src/server/api/endpoints/users/stats.ts +++ b/packages/backend/src/server/api/endpoints/users/stats.ts @@ -7,6 +7,7 @@ export const meta = { tags: ['users'], requireCredential: false, + requireCredentialPrivateMode: true, description: 'Show statistics about a user.', -- 2.43.0 From 126b7f4ad786e41a6144a6a087e9399c044ed008 Mon Sep 17 00:00:00 2001 From: nullobsi Date: Tue, 20 Jul 2021 13:08:21 -0700 Subject: [PATCH 04/14] Add secure mode settings to Security tab --- locales/ja-JP.yml | 7 ++++ .../src/server/api/endpoints/admin/meta.ts | 19 +++++++++ .../server/api/endpoints/admin/update-meta.ts | 21 ++++++++++ packages/client/src/pages/admin/security.vue | 39 +++++++++++++++++++ 4 files changed, 86 insertions(+) diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 401f9ed35..e58787e57 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -776,6 +776,13 @@ middle: "中" low: "低" emailNotConfiguredWarning: "メールアドレスの設定がされていません。" ratio: "比率" +secureMode: "セキュアモード (Authorized Fetch)" +instanceSecurity: "インスタンスのセキュリティー" +secureModeInfo: "他のインスタンスからリクエストするときに、証明を付けなければ返送しません。他のインスタンスの設定ファイルでsignToActivityPubGetはtrueにしてください。" +privateMode: "非公開モード" +privateModeInfo: "有効にして、許可されているインスタンスのみがリクエストできます。すべてのノートが公開に非表示にします。" +allowedInstances: "許可されたインスタンス" +allowedInstancesDescription: "許可したいインスタンスのホストを改行で区切って設定します。非公開モードだけで有効です。" previewNoteText: "本文をプレビュー" customCss: "カスタムCSS" customCssWarn: "この設定は必ず知識のある方が行ってください。不適切な設定を行うとクライアントが正常に使用できなくなる恐れがあります。" diff --git a/packages/backend/src/server/api/endpoints/admin/meta.ts b/packages/backend/src/server/api/endpoints/admin/meta.ts index 5d7973669..f869a0f9f 100644 --- a/packages/backend/src/server/api/endpoints/admin/meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/meta.ts @@ -153,6 +153,22 @@ export const meta = { 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: { type: 'string', optional: true, nullable: true, @@ -327,6 +343,9 @@ export default define(meta, paramDef, async (ps, me) => { pinnedUsers: instance.pinnedUsers, hiddenTags: instance.hiddenTags, blockedHosts: instance.blockedHosts, + allowedHosts: instance.allowedHosts, + privateMode: instance.privateMode, + secureMode: instance.secureMode, hcaptchaSecretKey: instance.hcaptchaSecretKey, recaptchaSecretKey: instance.recaptchaSecretKey, proxyAccountId: instance.proxyAccountId, diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index bd75e0f93..3b42a62d2 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -26,6 +26,11 @@ export const paramDef = { blockedHosts: { type: 'array', nullable: true, items: { 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}$' }, bannerUrl: { type: 'string', nullable: true }, iconUrl: { type: 'string', nullable: true }, @@ -131,6 +136,22 @@ export default define(meta, paramDef, async (ps, me) => { 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.mascotImageUrl !== undefined) { + set.mascotImageUrl = ps.mascotImageUrl; + } + if (ps.bannerUrl !== undefined) { set.bannerUrl = ps.bannerUrl; } diff --git a/packages/client/src/pages/admin/security.vue b/packages/client/src/pages/admin/security.vue index ec11e42a7..c5fb842fe 100644 --- a/packages/client/src/pages/admin/security.vue +++ b/packages/client/src/pages/admin/security.vue @@ -26,6 +26,26 @@ {{ i18n.ts.save }} + + + + +
+ + + + + + + + + + + + + {{ i18n.ts.save }} +
+
@@ -43,6 +63,7 @@ import FormSuspense from '@/components/form/suspense.vue'; import FormSection from '@/components/form/section.vue'; import FormInput from '@/components/form/input.vue'; import FormButton from '@/components/ui/button.vue'; +import FormTextarea from '@/components/form/textarea.vue'; import * as os from '@/os'; import { fetchInstance } from '@/instance'; import { i18n } from '@/i18n'; @@ -52,11 +73,19 @@ let summalyProxy: string = $ref(''); let enableHcaptcha: 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() { const meta = await os.api('admin/meta'); summalyProxy = meta.summalyProxy; enableHcaptcha = meta.enableHcaptcha; enableRecaptcha = meta.enableRecaptcha; + + secureMode = meta.secureMode; + privateMode = meta.privateMode; + allowedHosts = meta.allowedHosts.join('\n'); } function save() { @@ -67,6 +96,16 @@ function save() { }); } +function saveInstance() { + os.apiWithDialog('admin/update-meta', { + secureMode, + privateMode, + allowedHosts: allowedHosts.split('\n'), + }).then(() => { + fetchInstance(); + }); +} + const headerActions = $computed(() => []); const headerTabs = $computed(() => []); -- 2.43.0 From cfd251d9dc8261482f9f55118bc30481aa5c9757 Mon Sep 17 00:00:00 2001 From: nullobsi Date: Wed, 25 Aug 2021 20:48:57 -0700 Subject: [PATCH 05/14] Hide private data in pug when private mode is enabled --- packages/backend/src/server/web/index.ts | 14 +++++ .../backend/src/server/web/views/base.pug | 2 + .../backend/src/server/web/views/channel.pug | 16 +++--- .../backend/src/server/web/views/clip.pug | 33 ++++++------ .../src/server/web/views/gallery-post.pug | 35 +++++++------ .../backend/src/server/web/views/note.pug | 51 ++++++++++--------- .../backend/src/server/web/views/page.pug | 33 ++++++------ .../backend/src/server/web/views/user.pug | 47 +++++++++-------- 8 files changed, 132 insertions(+), 99 deletions(-) diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 03ee8d5ba..bd5efcc31 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -218,6 +218,10 @@ router.get('/api.json', async ctx => { }); const getFeed = async (acct: string) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + return; + } const { username, host } = Acct.parse(acct); const user = await Users.findOneBy({ usernameLower: username.toLowerCase(), @@ -290,6 +294,7 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, + privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); } else { @@ -379,6 +384,7 @@ router.get('/@:user/pages/:page', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, + privateMode: meta.privateMode, }); if (['public'].includes(page.visibility)) { @@ -409,6 +415,7 @@ router.get('/clips/:clip', async (ctx, next) => { profile, avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: clip.userId })), instanceName: meta.name || 'Misskey', + privateMode: meta.privateMode, icon: meta.iconUrl, themeColor: meta.themeColor, }); @@ -436,6 +443,7 @@ router.get('/gallery/:post', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, + privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); @@ -460,6 +468,7 @@ router.get('/channels/:channel', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, + privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); @@ -473,6 +482,10 @@ router.get('/channels/:channel', async (ctx, next) => { router.get('/_info_card_', async ctx => { const meta = await fetchMeta(true); + if (meta.privateMode) { + ctx.status = 403; + return; + } ctx.remove('X-Frame-Options'); @@ -520,6 +533,7 @@ router.get('(.*)', async ctx => { desc: meta.description, icon: meta.iconUrl, themeColor: meta.themeColor, + privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); }); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 32499aa45..79d21c07e 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -51,6 +51,8 @@ html meta(name='description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨') block meta + if privateMode + meta(name='robots' content='noindex') block og meta(property='og:title' content= title || 'Misskey') diff --git a/packages/backend/src/server/web/views/channel.pug b/packages/backend/src/server/web/views/channel.pug index 486f0ecc4..c4594b766 100644 --- a/packages/backend/src/server/web/views/channel.pug +++ b/packages/backend/src/server/web/views/channel.pug @@ -1,18 +1,20 @@ extends ./base block vars - - const title = channel.name; + - const title = privateMode ? instanceName : channel.name; - const url = `${config.url}/channels/${channel.id}`; block title = `${title} | ${instanceName}` block desc - meta(name='description' content= channel.description) + unless privateMode + meta(name='description' content=channel.description) block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= channel.description) - meta(property='og:url' content= url) - meta(property='og:image' content= channel.bannerUrl) + unless privateMode + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= channel.description) + meta(property='og:url' content= url) + meta(property='og:image' content= channel.bannerUrl) diff --git a/packages/backend/src/server/web/views/clip.pug b/packages/backend/src/server/web/views/clip.pug index 4c692bf59..2432470c1 100644 --- a/packages/backend/src/server/web/views/clip.pug +++ b/packages/backend/src/server/web/views/clip.pug @@ -2,30 +2,33 @@ extends ./base block vars - const user = clip.user; - - const title = clip.name; + - const title = privateMode ? instanceName : clip.name; - const url = `${config.url}/clips/${clip.id}`; block title = `${title} | ${instanceName}` block desc - meta(name='description' content= clip.description) + unless privateMode + meta(name='description' content= clip.description) block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= clip.description) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + unless privateMode + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= clip.description) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - if profile.noCrawle - meta(name='robots' content='noindex') + unless privateMode + if profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:clip-id' content=clip.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:clip-id' content=clip.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) diff --git a/packages/backend/src/server/web/views/gallery-post.pug b/packages/backend/src/server/web/views/gallery-post.pug index ca0663a48..1b1c2fbfb 100644 --- a/packages/backend/src/server/web/views/gallery-post.pug +++ b/packages/backend/src/server/web/views/gallery-post.pug @@ -2,32 +2,35 @@ extends ./base block vars - const user = post.user; - - const title = post.title; + - const title = privateMode ? instanceName : post.title; - const url = `${config.url}/gallery/${post.id}`; block title = `${title} | ${instanceName}` block desc - meta(name='description' content= post.description) + unless privateMode + meta(name='description' content= post.description) block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= post.description) - meta(property='og:url' content= url) - meta(property='og:image' content= post.files[0].thumbnailUrl) + unless privateMode + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= post.description) + meta(property='og:url' content= url) + meta(property='og:image' content= post.files[0].thumbnailUrl) block meta - if user.host || profile.noCrawle - meta(name='robots' content='noindex') + unless privateMode + if user.host || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) - if !user.host - link(rel='alternate' href=url type='application/activity+json') + if !user.host + link(rel='alternate' href=url type='application/activity+json') diff --git a/packages/backend/src/server/web/views/note.pug b/packages/backend/src/server/web/views/note.pug index 65696ea13..6b55f6ba0 100644 --- a/packages/backend/src/server/web/views/note.pug +++ b/packages/backend/src/server/web/views/note.pug @@ -2,7 +2,7 @@ extends ./base block vars - const user = note.user; - - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; + - const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username})` : `@${user.username}`); - const url = `${config.url}/notes/${note.id}`; - const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null; @@ -10,33 +10,36 @@ block title = `${title} | ${instanceName}` block desc - meta(name='description' content= summary) + unless privateMode + meta(name='description' content= summary) block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= summary) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + unless privateMode + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= summary) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - if user.host || isRenote || profile.noCrawle - meta(name='robots' content='noindex') + unless privateMode + if user.host || isRenote || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:note-id' content=note.id) - - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:note-id' content=note.id) - if note.prev - link(rel='prev' href=`${config.url}/notes/${note.prev}`) - if note.next - link(rel='next' href=`${config.url}/notes/${note.next}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) - if !user.host - link(rel='alternate' href=url type='application/activity+json') - if note.uri - link(rel='alternate' href=note.uri type='application/activity+json') + if note.prev + link(rel='prev' href=`${config.url}/notes/${note.prev}`) + if note.next + link(rel='next' href=`${config.url}/notes/${note.next}`) + + if !user.host + link(rel='alternate' href=url type='application/activity+json') + if note.uri + link(rel='alternate' href=note.uri type='application/activity+json') diff --git a/packages/backend/src/server/web/views/page.pug b/packages/backend/src/server/web/views/page.pug index 4219e76a5..109528213 100644 --- a/packages/backend/src/server/web/views/page.pug +++ b/packages/backend/src/server/web/views/page.pug @@ -2,30 +2,33 @@ extends ./base block vars - const user = page.user; - - const title = page.title; + - const title = privateMode ? instanceName : page.title; - const url = `${config.url}/@${user.username}/${page.name}`; block title = `${title} | ${instanceName}` block desc - meta(name='description' content= page.summary) + unless privateMode + meta(name='description' content= page.summary) block og - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= page.summary) - meta(property='og:url' content= url) - meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl) + unless privateMode + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= page.summary) + meta(property='og:url' content= url) + meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl) block meta - if profile.noCrawle - meta(name='robots' content='noindex') + unless privateMode + if profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:page-id' content=page.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:page-id' content=page.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) diff --git a/packages/backend/src/server/web/views/user.pug b/packages/backend/src/server/web/views/user.pug index 119993fdb..cc14dedb3 100644 --- a/packages/backend/src/server/web/views/user.pug +++ b/packages/backend/src/server/web/views/user.pug @@ -1,39 +1,42 @@ extends ./base block vars - - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; + - const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username})` : `@${user.username}`); - const url = `${config.url}/@${(user.host ? `${user.username}@${user.host}` : user.username)}`; block title = `${title} | ${instanceName}` block desc - meta(name='description' content= profile.description) + unless privateMode + meta(name='description' content= profile.description) block og - meta(property='og:type' content='blog') - meta(property='og:title' content= title) - meta(property='og:description' content= profile.description) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + unless privateMode + meta(property='og:type' content='blog') + meta(property='og:title' content= title) + meta(property='og:description' content= profile.description) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - if user.host || profile.noCrawle - meta(name='robots' content='noindex') + unless privateMode + if user.host || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) - if profile.twitter - meta(name='twitter:creator' content=`@${profile.twitter.screenName}`) + if profile.twitter + meta(name='twitter:creator' content=`@${profile.twitter.screenName}`) - if !sub - if !user.host - link(rel='alternate' href=`${config.url}/users/${user.id}` type='application/activity+json') - if user.uri - link(rel='alternate' href=user.uri type='application/activity+json') - if profile.url - link(rel='alternate' href=profile.url type='text/html') + if !sub + if !user.host + link(rel='alternate' href=`${config.url}/users/${user.id}` type='application/activity+json') + if user.uri + link(rel='alternate' href=user.uri type='application/activity+json') + if profile.url + link(rel='alternate' href=profile.url type='text/html') - each m in me - link(rel='me' href=`${m}`) + each m in me + link(rel='me' href=`${m}`) -- 2.43.0 From b4582a829fe343f67617d8f479a419aae982ad8d Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Mon, 25 Jul 2022 23:51:48 -0400 Subject: [PATCH 06/14] Fix linter errors --- .../src/remote/activitypub/check-fetch.ts | 1 - packages/backend/src/server/activitypub.ts | 18 +++++++++--------- .../backend/src/server/activitypub/featured.ts | 2 +- .../src/server/activitypub/followers.ts | 4 ++-- .../src/server/activitypub/following.ts | 4 ++-- .../backend/src/server/activitypub/outbox.ts | 8 ++++---- .../src/server/api/endpoints/notes/children.ts | 2 +- 7 files changed, 19 insertions(+), 20 deletions(-) diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts index 8a53396b6..bf9aaa75b 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -7,7 +7,6 @@ import { toPuny } from '@/misc/convert-host.js'; import DbResolver from '@/remote/activitypub/db-resolver.js'; import { getApId } from '@/remote/activitypub/type.js'; - export default async function checkFetch(req: IncomingMessage): Promise { const meta = await fetchMeta(); if (meta.secureMode || meta.privateMode) { diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index 250a39bf0..95bed8a6c 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -70,7 +70,7 @@ router.get('/notes/:note', async (ctx, next) => { if (!isActivityPubReq(ctx)) return await next(); const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -87,7 +87,7 @@ router.get('/notes/:note', async (ctx, next) => { } // リモートだったらリダイレクト - if (note.userHost != null) { + if (note.userHost !== null) { if (note.uri == null || isSelfHost(note.userHost)) { ctx.status = 500; return; @@ -110,7 +110,7 @@ router.get('/notes/:note', async (ctx, next) => { // note activity router.get('/notes/:note/activity', async ctx => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -160,7 +160,7 @@ router.get('/users/:user/publickey', async ctx => { } const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -220,7 +220,7 @@ router.get('/users/:user', async (ctx, next) => { } const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -246,7 +246,7 @@ router.get('/@:user', async (ctx, next) => { } const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -269,7 +269,7 @@ router.get('/actor', async (ctx, next) => { // emoji router.get('/emojis/:emoji', async ctx => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -297,7 +297,7 @@ router.get('/emojis/:emoji', async ctx => { // like router.get('/likes/:like', async ctx => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -329,7 +329,7 @@ router.get('/likes/:like', async ctx => { // follow router.get('/follows/:follower/:followee', async ctx => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } diff --git a/packages/backend/src/server/activitypub/featured.ts b/packages/backend/src/server/activitypub/featured.ts index 87e4f8320..bde44ca06 100644 --- a/packages/backend/src/server/activitypub/featured.ts +++ b/packages/backend/src/server/activitypub/featured.ts @@ -11,7 +11,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } diff --git a/packages/backend/src/server/activitypub/followers.ts b/packages/backend/src/server/activitypub/followers.ts index 833f0e77f..79b9ac001 100644 --- a/packages/backend/src/server/activitypub/followers.ts +++ b/packages/backend/src/server/activitypub/followers.ts @@ -14,7 +14,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -22,7 +22,7 @@ export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; const cursor = ctx.request.query.cursor; - if (cursor != null && typeof cursor !== 'string') { + if (cursor !== null && typeof cursor !== 'string') { ctx.status = 400; return; } diff --git a/packages/backend/src/server/activitypub/following.ts b/packages/backend/src/server/activitypub/following.ts index f843d79f0..e689ab145 100644 --- a/packages/backend/src/server/activitypub/following.ts +++ b/packages/backend/src/server/activitypub/following.ts @@ -14,7 +14,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -22,7 +22,7 @@ export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; const cursor = ctx.request.query.cursor; - if (cursor != null && typeof cursor !== 'string') { + if (cursor !== null && typeof cursor !== 'string') { ctx.status = 400; return; } diff --git a/packages/backend/src/server/activitypub/outbox.ts b/packages/backend/src/server/activitypub/outbox.ts index 4a6b5caff..fb631d3c7 100644 --- a/packages/backend/src/server/activitypub/outbox.ts +++ b/packages/backend/src/server/activitypub/outbox.ts @@ -18,7 +18,7 @@ import { fetchMeta } from '@/misc/fetch-meta.js'; export default async (ctx: Router.RouterContext) => { const verify = await checkFetch(ctx.req); - if (verify != 200) { + if (verify !== 200) { ctx.status = verify; return; } @@ -26,20 +26,20 @@ export default async (ctx: Router.RouterContext) => { const userId = ctx.params.user; const sinceId = ctx.request.query.since_id; - if (sinceId != null && typeof sinceId !== 'string') { + if (sinceId !== null && typeof sinceId !== 'string') { ctx.status = 400; return; } const untilId = ctx.request.query.until_id; - if (untilId != null && typeof untilId !== 'string') { + if (untilId !== null && typeof untilId !== 'string') { ctx.status = 400; return; } const page = ctx.request.query.page === 'true'; - if (countIf(x => x != null, [sinceId, untilId]) > 1) { + if (countIf(x => x !== null, [sinceId, untilId]) > 1) { ctx.status = 400; return; } diff --git a/packages/backend/src/server/api/endpoints/notes/children.ts b/packages/backend/src/server/api/endpoints/notes/children.ts index feaf94dcf..7f2245c7e 100644 --- a/packages/backend/src/server/api/endpoints/notes/children.ts +++ b/packages/backend/src/server/api/endpoints/notes/children.ts @@ -55,7 +55,7 @@ export default define(meta, paramDef, async (ps, user) => { .andWhere('note.id IN (SELECT id FROM note_replies(:noteId, :depth, :limit))', { noteId: ps.noteId, depth: ps.depth, limit: ps.limit }) .innerJoinAndSelect('note.user', 'user') .leftJoinAndSelect('user.avatar', 'avatar') - .leftJoinAndSelect('user.banner', 'banner') + .leftJoinAndSelect('user.banner', 'banner'); generateVisibilityQuery(query, user); if (user) { -- 2.43.0 From 664df9a16333c8ab86c177f4c6a4df3b04be485d Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Tue, 26 Jul 2022 00:07:25 -0400 Subject: [PATCH 07/14] Add en-US strings for secure mode --- locales/en-US.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/locales/en-US.yml b/locales/en-US.yml index bfcb74825..7819ddbeb 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -774,6 +774,13 @@ middle: "Medium" low: "Low" emailNotConfiguredWarning: "Email address not set." ratio: "Ratio" +secureMode: "Secure Mode (Authorized Fetch)" +instanceSecurity: "Instance Security" +secureModeInfo: "Requests from other instances must be signed, otherwise notes won't be returned. signToActivityPubGet must be set to true in the other instance's configuration file." +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" customCss: "Custom CSS" customCssWarn: "This setting should only be used if you know what it does. Entering improper values may cause the client to stop functioning normally." -- 2.43.0 From 55b2aebec4c25511d9ebecd39c50938dee19b374 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Wed, 27 Jul 2022 02:30:49 -0400 Subject: [PATCH 08/14] Remove signToActivityPubGet option Makes it so that all requests are signed, equivalent to signToActivityPubGet always being true. --- .config/example.yml | 3 --- chart/files/default.yml | 3 --- locales/en-US.yml | 2 +- locales/ja-JP.yml | 2 +- packages/backend/src/config/types.ts | 2 -- packages/backend/src/remote/activitypub/resolver.ts | 2 +- 6 files changed, 3 insertions(+), 11 deletions(-) diff --git a/.config/example.yml b/.config/example.yml index d78a3b678..b2c76e8c4 100644 --- a/.config/example.yml +++ b/.config/example.yml @@ -120,9 +120,6 @@ redis: # Proxy remote files (default: false) #proxyRemoteFiles: true -# Sign to ActivityPub GET request (default: false) -#signToActivityPubGet: true - #allowedPrivateNetworks: [ # '127.0.0.1/32' #] diff --git a/chart/files/default.yml b/chart/files/default.yml index a9ef22f42..91a947f26 100644 --- a/chart/files/default.yml +++ b/chart/files/default.yml @@ -154,9 +154,6 @@ id: "aid" # Media Proxy #mediaProxy: https://example.com/proxy -# Sign to ActivityPub GET request (default: false) -#signToActivityPubGet: true - #allowedPrivateNetworks: [ # '127.0.0.1/32' #] diff --git a/locales/en-US.yml b/locales/en-US.yml index 7819ddbeb..e47d40d24 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -776,7 +776,7 @@ emailNotConfiguredWarning: "Email address not set." ratio: "Ratio" secureMode: "Secure Mode (Authorized Fetch)" instanceSecurity: "Instance Security" -secureModeInfo: "Requests from other instances must be signed, otherwise notes won't be returned. signToActivityPubGet must be set to true in the other instance's configuration file." +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" diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index e58787e57..9b370e7a9 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -778,7 +778,7 @@ emailNotConfiguredWarning: "メールアドレスの設定がされていませ ratio: "比率" secureMode: "セキュアモード (Authorized Fetch)" instanceSecurity: "インスタンスのセキュリティー" -secureModeInfo: "他のインスタンスからリクエストするときに、証明を付けなければ返送しません。他のインスタンスの設定ファイルでsignToActivityPubGetはtrueにしてください。" +secureModeInfo: "他のインスタンスからリクエストするときに、証明を付けなければ返送しません。" privateMode: "非公開モード" privateModeInfo: "有効にして、許可されているインスタンスのみがリクエストできます。すべてのノートが公開に非表示にします。" allowedInstances: "許可されたインスタンス" diff --git a/packages/backend/src/config/types.ts b/packages/backend/src/config/types.ts index 78510c837..2f182e1ae 100644 --- a/packages/backend/src/config/types.ts +++ b/packages/backend/src/config/types.ts @@ -63,8 +63,6 @@ export type Source = { mediaProxy?: string; proxyRemoteFiles?: boolean; - - signToActivityPubGet?: boolean; }; /** diff --git a/packages/backend/src/remote/activitypub/resolver.ts b/packages/backend/src/remote/activitypub/resolver.ts index 24fdbe277..7c72a0185 100644 --- a/packages/backend/src/remote/activitypub/resolver.ts +++ b/packages/backend/src/remote/activitypub/resolver.ts @@ -76,7 +76,7 @@ export default class Resolver { throw new Error('Instance is not allowed'); } - if (config.signToActivityPubGet && !this.user) { + if (!this.user) { this.user = await getInstanceActor(); } -- 2.43.0 From 4753b5058c7fa01b6ddddcf4793742f8627a0883 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Sat, 30 Jul 2022 18:59:04 -0400 Subject: [PATCH 09/14] Translate/remove new comments --- packages/backend/src/queue/processors/inbox.ts | 2 +- packages/backend/src/remote/activitypub/check-fetch.ts | 9 +++------ packages/backend/src/server/api/endpoints.ts | 4 ++-- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/packages/backend/src/queue/processors/inbox.ts b/packages/backend/src/queue/processors/inbox.ts index 422632059..cc8390d69 100644 --- a/packages/backend/src/queue/processors/inbox.ts +++ b/packages/backend/src/queue/processors/inbox.ts @@ -39,7 +39,7 @@ export default async (job: Bull.Job): Promise => { return `Blocked request: ${host}`; } - // 非公開モードなら許可なインスタンスのみ + // Only permitted instances if in private mode. if (meta.privateMode && !meta.allowedHosts.includes(host)) { return `Blocked request: ${host}`; } diff --git a/packages/backend/src/remote/activitypub/check-fetch.ts b/packages/backend/src/remote/activitypub/check-fetch.ts index bf9aaa75b..7dd9a51c0 100644 --- a/packages/backend/src/remote/activitypub/check-fetch.ts +++ b/packages/backend/src/remote/activitypub/check-fetch.ts @@ -37,31 +37,28 @@ export default async function checkFetch(req: IncomingMessage): Promise const dbResolver = new DbResolver(); - // HTTP-Signature keyIdを元にDBから取得 + // Get user from database based on HTTP-Signature keyId let authUser = await dbResolver.getAuthUserFromKeyId(signature.keyId); - // keyIdでわからなければ、resolveしてみる + // If keyid is unknown, try resolving it if (authUser == null) { try { keyId.hash = ''; authUser = await dbResolver.getAuthUserFromApId(getApId(keyId.toString())); } catch (e) { - // できなければ駄目 return 403; } } - // publicKey がなくても終了 if (authUser?.key == null) { return 403; } - // もう一回チェック if (authUser.user.host !== host) { return 403; } - // HTTP-Signatureの検証 + // HTTP-Signature validation const httpSignatureValidated = httpSignature.verifySignature(signature, authUser.key.keyPem); if (!httpSignatureValidated) { diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index 6693a4bf6..39b6b6d33 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -693,8 +693,8 @@ export interface IEndpointMeta { readonly secure?: boolean; /** - * プライベートモードでなら、このエンドポイントにリクエストするときにユーザー情報が必要か否か - * 省略した場合は false として解釈されます + * If in private mode, whether credentials are required when making a request to this endpoint. + * If omitted, this is interpreted as false. */ readonly requireCredentialPrivateMode?: boolean; -- 2.43.0 From 7485d8d3600367ad5d7856399bdd7f78eebcc08f Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Sun, 31 Jul 2022 22:54:06 -0400 Subject: [PATCH 10/14] Remove deprecated URLs --- .../backend/src/server/api/endpoints/admin/update-meta.ts | 4 ---- packages/backend/src/server/api/endpoints/meta.ts | 2 -- 2 files changed, 6 deletions(-) diff --git a/packages/backend/src/server/api/endpoints/admin/update-meta.ts b/packages/backend/src/server/api/endpoints/admin/update-meta.ts index 3b42a62d2..e79fa59d7 100644 --- a/packages/backend/src/server/api/endpoints/admin/update-meta.ts +++ b/packages/backend/src/server/api/endpoints/admin/update-meta.ts @@ -148,10 +148,6 @@ export default define(meta, paramDef, async (ps, me) => { set.secureMode = ps.secureMode; } - if (ps.mascotImageUrl !== undefined) { - set.mascotImageUrl = ps.mascotImageUrl; - } - if (ps.bannerUrl !== undefined) { set.bannerUrl = ps.bannerUrl; } diff --git a/packages/backend/src/server/api/endpoints/meta.ts b/packages/backend/src/server/api/endpoints/meta.ts index 43babed9b..56b1965db 100644 --- a/packages/backend/src/server/api/endpoints/meta.ts +++ b/packages/backend/src/server/api/endpoints/meta.ts @@ -297,8 +297,6 @@ export default define(meta, paramDef, async (ps, me) => { description: instance.description, langs: instance.langs, tosUrl: instance.ToSUrl, - repositoryUrl: instance.repositoryUrl, - feedbackUrl: instance.feedbackUrl, secureMode: instance.secureMode, privateMode: instance.privateMode, -- 2.43.0 From cce01c9a70c4e78e130f80da2c2a6ee004ab34ca Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Sun, 31 Jul 2022 22:59:21 -0400 Subject: [PATCH 11/14] security: combine save functions --- packages/client/src/pages/admin/security.vue | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/packages/client/src/pages/admin/security.vue b/packages/client/src/pages/admin/security.vue index c5fb842fe..8e0efec74 100644 --- a/packages/client/src/pages/admin/security.vue +++ b/packages/client/src/pages/admin/security.vue @@ -43,7 +43,7 @@ - {{ i18n.ts.save }} + {{ i18n.ts.save }} @@ -88,16 +88,9 @@ async function init() { allowedHosts = meta.allowedHosts.join('\n'); } -function save() { +function save(): void { os.apiWithDialog('admin/update-meta', { summalyProxy, - }).then(() => { - fetchInstance(); - }); -} - -function saveInstance() { - os.apiWithDialog('admin/update-meta', { secureMode, privateMode, allowedHosts: allowedHosts.split('\n'), -- 2.43.0 From e5595ca31ccaaf0231df39df048c803296b3027d Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Sun, 31 Jul 2022 23:03:37 -0400 Subject: [PATCH 12/14] Skip rendering private data in privateMode This reverts commit cfd251d9dc8261482f9f55118bc30481aa5c9757. Instead of adding a conditional in the Pug templates, just skip rendering altogether on the affected routes. From https://akkoma.dev/FoundKeyGang/FoundKey/pulls/31: > I'm not really happy with how the pug templates have > unless privatemode everywhere. I think it would make more sense to > not render the template in the first place if you are in private > mode? I think you should be able to just skip to next in the > router as if you didn't find something. --- packages/backend/src/server/web/index.ts | 43 +++++++++++++--- .../backend/src/server/web/views/base.pug | 2 - .../backend/src/server/web/views/channel.pug | 16 +++--- .../backend/src/server/web/views/clip.pug | 33 ++++++------ .../src/server/web/views/gallery-post.pug | 35 ++++++------- .../backend/src/server/web/views/note.pug | 51 +++++++++---------- .../backend/src/server/web/views/page.pug | 33 ++++++------ .../backend/src/server/web/views/user.pug | 47 ++++++++--------- 8 files changed, 135 insertions(+), 125 deletions(-) diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index bd5efcc31..809ecf6f2 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -22,11 +22,12 @@ import { Users, Notes, UserProfiles, Pages, Channels, Clips, GalleryPosts } from import * as Acct from '@/misc/acct.js'; import { getNoteSummary } from '@/misc/get-note-summary.js'; import { queues } from '@/queue/queues.js'; +import { MINUTE, DAY } from '@/const.js'; import { genOpenapiSpec } from '../api/openapi/gen-spec.js'; +import meta from '../api/endpoints/meta.js'; import { urlPreviewHandler } from './url-preview.js'; import { manifestHandler } from './manifest.js'; import packFeed from './feed.js'; -import { MINUTE, DAY } from '@/const.js'; const _filename = fileURLToPath(import.meta.url); const _dirname = dirname(_filename); @@ -271,6 +272,12 @@ router.get('/@:user.json', async ctx => { //#region SSR (for crawlers) // User router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + await next(); + return; + } + const { username, host } = Acct.parse(ctx.params.user); const user = await Users.findOneBy({ usernameLower: username.toLowerCase(), @@ -294,7 +301,6 @@ router.get(['/@:user', '/@:user/:sub'], async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, - privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); } else { @@ -360,6 +366,12 @@ router.get('/notes/:note', async (ctx, next) => { // Page router.get('/@:user/pages/:page', async (ctx, next) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + await next(); + return; + } + const { username, host } = Acct.parse(ctx.params.user); const user = await Users.findOneBy({ usernameLower: username.toLowerCase(), @@ -384,7 +396,6 @@ router.get('/@:user/pages/:page', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, - privateMode: meta.privateMode, }); if (['public'].includes(page.visibility)) { @@ -402,6 +413,12 @@ router.get('/@:user/pages/:page', async (ctx, next) => { // Clip // TODO: 非publicなclipのハンドリング router.get('/clips/:clip', async (ctx, next) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + await next(); + return; + } + const clip = await Clips.findOneBy({ id: ctx.params.clip, }); @@ -415,7 +432,6 @@ router.get('/clips/:clip', async (ctx, next) => { profile, avatarUrl: await Users.getAvatarUrl(await Users.findOneByOrFail({ id: clip.userId })), instanceName: meta.name || 'Misskey', - privateMode: meta.privateMode, icon: meta.iconUrl, themeColor: meta.themeColor, }); @@ -430,6 +446,12 @@ router.get('/clips/:clip', async (ctx, next) => { // Gallery post router.get('/gallery/:post', async (ctx, next) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + await next(); + return; + } + const post = await GalleryPosts.findOneBy({ id: ctx.params.post }); if (post) { @@ -443,7 +465,6 @@ router.get('/gallery/:post', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, - privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); @@ -456,6 +477,12 @@ router.get('/gallery/:post', async (ctx, next) => { // Channel router.get('/channels/:channel', async (ctx, next) => { + const meta = await fetchMeta(); + if (meta.privateMode) { + await next(); + return; + } + const channel = await Channels.findOneBy({ id: ctx.params.channel, }); @@ -468,7 +495,6 @@ router.get('/channels/:channel', async (ctx, next) => { instanceName: meta.name || 'Misskey', icon: meta.iconUrl, themeColor: meta.themeColor, - privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); @@ -526,6 +552,10 @@ router.get('/streaming', async ctx => { // Render base html for all requests router.get('(.*)', async ctx => { const meta = await fetchMeta(); + if (meta.privateMode) { + return; + } + await ctx.render('base', { img: meta.bannerUrl, title: meta.name || 'Misskey', @@ -533,7 +563,6 @@ router.get('(.*)', async ctx => { desc: meta.description, icon: meta.iconUrl, themeColor: meta.themeColor, - privateMode: meta.privateMode, }); ctx.set('Cache-Control', 'public, max-age=15'); }); diff --git a/packages/backend/src/server/web/views/base.pug b/packages/backend/src/server/web/views/base.pug index 79d21c07e..32499aa45 100644 --- a/packages/backend/src/server/web/views/base.pug +++ b/packages/backend/src/server/web/views/base.pug @@ -51,8 +51,6 @@ html meta(name='description' content= desc || '✨🌎✨ A interplanetary communication platform ✨🚀✨') block meta - if privateMode - meta(name='robots' content='noindex') block og meta(property='og:title' content= title || 'Misskey') diff --git a/packages/backend/src/server/web/views/channel.pug b/packages/backend/src/server/web/views/channel.pug index c4594b766..486f0ecc4 100644 --- a/packages/backend/src/server/web/views/channel.pug +++ b/packages/backend/src/server/web/views/channel.pug @@ -1,20 +1,18 @@ extends ./base block vars - - const title = privateMode ? instanceName : channel.name; + - const title = channel.name; - const url = `${config.url}/channels/${channel.id}`; block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content=channel.description) + meta(name='description' content= channel.description) block og - unless privateMode - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= channel.description) - meta(property='og:url' content= url) - meta(property='og:image' content= channel.bannerUrl) + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= channel.description) + meta(property='og:url' content= url) + meta(property='og:image' content= channel.bannerUrl) diff --git a/packages/backend/src/server/web/views/clip.pug b/packages/backend/src/server/web/views/clip.pug index 2432470c1..4c692bf59 100644 --- a/packages/backend/src/server/web/views/clip.pug +++ b/packages/backend/src/server/web/views/clip.pug @@ -2,33 +2,30 @@ extends ./base block vars - const user = clip.user; - - const title = privateMode ? instanceName : clip.name; + - const title = clip.name; - const url = `${config.url}/clips/${clip.id}`; block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content= clip.description) + meta(name='description' content= clip.description) block og - unless privateMode - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= clip.description) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= clip.description) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - unless privateMode - if profile.noCrawle - meta(name='robots' content='noindex') + if profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:clip-id' content=clip.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:clip-id' content=clip.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) diff --git a/packages/backend/src/server/web/views/gallery-post.pug b/packages/backend/src/server/web/views/gallery-post.pug index 1b1c2fbfb..ca0663a48 100644 --- a/packages/backend/src/server/web/views/gallery-post.pug +++ b/packages/backend/src/server/web/views/gallery-post.pug @@ -2,35 +2,32 @@ extends ./base block vars - const user = post.user; - - const title = privateMode ? instanceName : post.title; + - const title = post.title; - const url = `${config.url}/gallery/${post.id}`; block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content= post.description) + meta(name='description' content= post.description) block og - unless privateMode - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= post.description) - meta(property='og:url' content= url) - meta(property='og:image' content= post.files[0].thumbnailUrl) + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= post.description) + meta(property='og:url' content= url) + meta(property='og:image' content= post.files[0].thumbnailUrl) block meta - unless privateMode - if user.host || profile.noCrawle - meta(name='robots' content='noindex') + if user.host || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) - if !user.host - link(rel='alternate' href=url type='application/activity+json') + if !user.host + link(rel='alternate' href=url type='application/activity+json') diff --git a/packages/backend/src/server/web/views/note.pug b/packages/backend/src/server/web/views/note.pug index 6b55f6ba0..65696ea13 100644 --- a/packages/backend/src/server/web/views/note.pug +++ b/packages/backend/src/server/web/views/note.pug @@ -2,7 +2,7 @@ extends ./base block vars - const user = note.user; - - const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username})` : `@${user.username}`); + - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; - const url = `${config.url}/notes/${note.id}`; - const isRenote = note.renote && note.text == null && note.fileIds.length == 0 && note.poll == null; @@ -10,36 +10,33 @@ block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content= summary) + meta(name='description' content= summary) block og - unless privateMode - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= summary) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= summary) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - unless privateMode - if user.host || isRenote || profile.noCrawle - meta(name='robots' content='noindex') + if user.host || isRenote || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:note-id' content=note.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:note-id' content=note.id) + + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + if note.prev + link(rel='prev' href=`${config.url}/notes/${note.prev}`) + if note.next + link(rel='next' href=`${config.url}/notes/${note.next}`) - if note.prev - link(rel='prev' href=`${config.url}/notes/${note.prev}`) - if note.next - link(rel='next' href=`${config.url}/notes/${note.next}`) - - if !user.host - link(rel='alternate' href=url type='application/activity+json') - if note.uri - link(rel='alternate' href=note.uri type='application/activity+json') + if !user.host + link(rel='alternate' href=url type='application/activity+json') + if note.uri + link(rel='alternate' href=note.uri type='application/activity+json') diff --git a/packages/backend/src/server/web/views/page.pug b/packages/backend/src/server/web/views/page.pug index 109528213..4219e76a5 100644 --- a/packages/backend/src/server/web/views/page.pug +++ b/packages/backend/src/server/web/views/page.pug @@ -2,33 +2,30 @@ extends ./base block vars - const user = page.user; - - const title = privateMode ? instanceName : page.title; + - const title = page.title; - const url = `${config.url}/@${user.username}/${page.name}`; block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content= page.summary) + meta(name='description' content= page.summary) block og - unless privateMode - meta(property='og:type' content='article') - meta(property='og:title' content= title) - meta(property='og:description' content= page.summary) - meta(property='og:url' content= url) - meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl) + meta(property='og:type' content='article') + meta(property='og:title' content= title) + meta(property='og:description' content= page.summary) + meta(property='og:url' content= url) + meta(property='og:image' content= page.eyeCatchingImage ? page.eyeCatchingImage.thumbnailUrl : avatarUrl) block meta - unless privateMode - if profile.noCrawle - meta(name='robots' content='noindex') + if profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) - meta(name='misskey:page-id' content=page.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) + meta(name='misskey:page-id' content=page.id) - // todo - if user.twitter - meta(name='twitter:creator' content=`@${user.twitter.screenName}`) + // todo + if user.twitter + meta(name='twitter:creator' content=`@${user.twitter.screenName}`) diff --git a/packages/backend/src/server/web/views/user.pug b/packages/backend/src/server/web/views/user.pug index cc14dedb3..119993fdb 100644 --- a/packages/backend/src/server/web/views/user.pug +++ b/packages/backend/src/server/web/views/user.pug @@ -1,42 +1,39 @@ extends ./base block vars - - const title = privateMode ? instanceName : (user.name ? `${user.name} (@${user.username})` : `@${user.username}`); + - const title = user.name ? `${user.name} (@${user.username})` : `@${user.username}`; - const url = `${config.url}/@${(user.host ? `${user.username}@${user.host}` : user.username)}`; block title = `${title} | ${instanceName}` block desc - unless privateMode - meta(name='description' content= profile.description) + meta(name='description' content= profile.description) block og - unless privateMode - meta(property='og:type' content='blog') - meta(property='og:title' content= title) - meta(property='og:description' content= profile.description) - meta(property='og:url' content= url) - meta(property='og:image' content= avatarUrl) + meta(property='og:type' content='blog') + meta(property='og:title' content= title) + meta(property='og:description' content= profile.description) + meta(property='og:url' content= url) + meta(property='og:image' content= avatarUrl) block meta - unless privateMode - if user.host || profile.noCrawle - meta(name='robots' content='noindex') + if user.host || profile.noCrawle + meta(name='robots' content='noindex') - meta(name='misskey:user-username' content=user.username) - meta(name='misskey:user-id' content=user.id) + meta(name='misskey:user-username' content=user.username) + meta(name='misskey:user-id' content=user.id) - if profile.twitter - meta(name='twitter:creator' content=`@${profile.twitter.screenName}`) + if profile.twitter + meta(name='twitter:creator' content=`@${profile.twitter.screenName}`) - if !sub - if !user.host - link(rel='alternate' href=`${config.url}/users/${user.id}` type='application/activity+json') - if user.uri - link(rel='alternate' href=user.uri type='application/activity+json') - if profile.url - link(rel='alternate' href=profile.url type='text/html') + if !sub + if !user.host + link(rel='alternate' href=`${config.url}/users/${user.id}` type='application/activity+json') + if user.uri + link(rel='alternate' href=user.uri type='application/activity+json') + if profile.url + link(rel='alternate' href=profile.url type='text/html') - each m in me - link(rel='me' href=`${m}`) + each m in me + link(rel='me' href=`${m}`) -- 2.43.0 From 429cb3ad7b9c3bda898a8c3a0e7d363b64ac31b0 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Mon, 1 Aug 2022 00:00:35 -0400 Subject: [PATCH 13/14] Remove check for signature in emoji fetch --- packages/backend/src/server/activitypub.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index 95bed8a6c..c72fb47fd 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -268,12 +268,6 @@ router.get('/actor', async (ctx, next) => { // emoji router.get('/emojis/:emoji', async ctx => { - const verify = await checkFetch(ctx.req); - if (verify !== 200) { - ctx.status = verify; - return; - } - const emoji = await Emojis.findOneBy({ host: IsNull(), name: ctx.params.emoji, -- 2.43.0 From a1b50a5ba59538ca7f5f1c7522e8aa35e2ae8d95 Mon Sep 17 00:00:00 2001 From: Francis Dinh Date: Thu, 11 Aug 2022 10:06:33 -0400 Subject: [PATCH 14/14] Set Cache-Control to 'no-store' in private/secure mode --- packages/backend/src/server/activitypub.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/backend/src/server/activitypub.ts b/packages/backend/src/server/activitypub.ts index 56d103993..e0067ac03 100644 --- a/packages/backend/src/server/activitypub.ts +++ b/packages/backend/src/server/activitypub.ts @@ -281,7 +281,7 @@ router.get('/emojis/:emoji', async ctx => { ctx.body = renderActivity(await renderEmoji(emoji)); const meta = await fetchMeta(); if (meta.secureMode || meta.privateMode) { - ctx.set('Cache-Control', 'private, max-age=0, must-revalidate'); + ctx.set('Cache-Control', 'no-store'); } else { ctx.set('Cache-Control', 'public, max-age=180'); } -- 2.43.0