diff --git a/package.json b/package.json index 7c5d118241..9b144a2f1f 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "build": "pnpm build-pre && pnpm -r build && pnpm build-assets", "build-storybook": "pnpm --filter frontend build-storybook", "build-misskey-js-with-types": "pnpm build-pre && pnpm --filter backend... --filter=!misskey-js build && pnpm --filter backend generate-api-json --no-build && ncp packages/backend/built/api.json packages/misskey-js/generator/api.json && pnpm --filter misskey-js update-autogen-code && pnpm --filter misskey-js build && pnpm --filter misskey-js api", - "start": "pnpm check:connect && cd packages/backend && node ./built/boot/entry.js", + "start": "pnpm check:connect && cd packages/backend && MK_WARNED_ABOUT_CONFIG=true node ./built/boot/entry.js", "start:test": "cd packages/backend && cross-env NODE_ENV=test node ./built/boot/entry.js", "init": "pnpm migrate", "migrate": "cd packages/backend && pnpm migrate", diff --git a/packages/backend/src/boot/master.ts b/packages/backend/src/boot/master.ts index 736a6c70d2..583db240c5 100644 --- a/packages/backend/src/boot/master.ts +++ b/packages/backend/src/boot/master.ts @@ -112,6 +112,11 @@ export async function masterMain() { await server(); } + if (config.clusterLimit === 0) { + bootLogger.error("Configuration error: we can't create workers, `config.clusterLimit` is 0 (if you don't want to use clustering, set the environment variable `MK_DISABLE_CLUSTERING` to a non-empty value instead)", null, true); + process.exit(1); + } + await spawnWorkers(config.clusterLimit); } @@ -180,7 +185,10 @@ async function connectDb(): Promise { */ async function spawnWorkers(limit = 1) { - const workers = Math.min(limit, os.cpus().length); + const cpuCount = os.cpus().length; + // in some weird environments, node can't count the CPUs; we trust the config in those cases + const workers = cpuCount === 0 ? limit : Math.min(limit, cpuCount); + bootLogger.info(`Starting ${workers} worker${workers === 1 ? '' : 's'}...`); await Promise.all([...Array(workers)].map(spawnWorker)); bootLogger.succ('All workers started'); diff --git a/packages/backend/src/config.ts b/packages/backend/src/config.ts index 74abd19552..87c2d55aa3 100644 --- a/packages/backend/src/config.ts +++ b/packages/backend/src/config.ts @@ -12,9 +12,10 @@ import * as Sentry from '@sentry/node'; import type { RedisOptions } from 'ioredis'; type RedisOptionsSource = Partial & { - host: string; - port: number; + host?: string; + port?: number; family?: number; + path?: string, pass: string; db?: number; prefix?: string; @@ -221,8 +222,15 @@ export function loadConfig(): Config { JSON.parse(fs.readFileSync(`${_dirname}/../../../built/_vite_/manifest.json`, 'utf-8')) : { 'src/_boot_.ts': { file: 'src/_boot_.ts' } }; - const config = globSync(path).sort() - .map(path => fs.readFileSync(path, 'utf-8')) + const configFiles = globSync(path).sort(); + + if (configFiles.length === 0 + && !process.env['MK_WARNED_ABOUT_CONFIG']) { + console.log('No config files loaded, check if this is intentional'); + process.env['MK_WARNED_ABOUT_CONFIG'] = true; + } + + const config = configFiles.map(path => fs.readFileSync(path, 'utf-8')) .map(contents => yaml.load(contents) as Source) .reduce( (acc: Source, cur: Source) => Object.assign(acc, cur), @@ -252,7 +260,7 @@ export function loadConfig(): Config { version, publishTarballInsteadOfProvideRepositoryUrl: !!config.publishTarballInsteadOfProvideRepositoryUrl, url: url.origin, - port: config.port ?? parseInt(process.env.PORT ?? '', 10), + port: config.port ?? parseInt(process.env.PORT ?? '3000', 10), socket: config.socket, chmodSocket: config.chmodSocket, disableHsts: config.disableHsts, @@ -440,8 +448,8 @@ function applyEnvOverrides(config: Source) { // these are all the settings that can be overridden - _apply_top([['url', 'port', 'socket', 'chmodSocket', 'disableHsts']]); - _apply_top(['db', ['host', 'port', 'db', 'user', 'pass']]); + _apply_top([['url', 'port', 'socket', 'chmodSocket', 'disableHsts', 'id', 'dbReplications']]); + _apply_top(['db', ['host', 'port', 'db', 'user', 'pass', 'disableCache']]); _apply_top(['dbSlaves', Array.from((config.dbSlaves ?? []).keys()), ['host', 'port', 'db', 'user', 'pass']]); _apply_top([ ['redis', 'redisForPubsub', 'redisForJobQueue', 'redisForTimelines'], @@ -451,7 +459,8 @@ function applyEnvOverrides(config: Source) { _apply_top([['sentryForFrontend', 'sentryForBackend'], 'options', ['dsn', 'profileSampleRate', 'serverName', 'includeLocalVariables', 'proxy', 'keepAlive', 'caCerts']]); _apply_top(['sentryForBackend', 'enableNodeProfiling']); _apply_top([['clusterLimit', 'deliverJobConcurrency', 'inboxJobConcurrency', 'relashionshipJobConcurrency', 'deliverJobPerSec', 'inboxJobPerSec', 'relashionshipJobPerSec', 'deliverJobMaxAttempts', 'inboxJobMaxAttempts']]); - _apply_top([['outgoingAddress', 'outgoingAddressFamily', 'proxy', 'proxySmtp', 'mediaProxy', 'videoThumbnailGenerator']]); + _apply_top([['outgoingAddress', 'outgoingAddressFamily', 'proxy', 'proxySmtp', 'mediaProxy', 'proxyRemoteFiles','videoThumbnailGenerator']]); _apply_top([['maxFileSize', 'maxNoteLength', 'pidFile']]); _apply_top(['import', ['downloadTimeout', 'maxFileSize']]); + _apply_top([['signToActivityPubGet', 'checkActivityPubGetSignature']]); } diff --git a/packages/backend/src/core/GlobalEventService.ts b/packages/backend/src/core/GlobalEventService.ts index aa6110a47f..753011cded 100644 --- a/packages/backend/src/core/GlobalEventService.ts +++ b/packages/backend/src/core/GlobalEventService.ts @@ -136,6 +136,7 @@ export interface NoteEventTypes { }; replied: { id: MiNote['id']; + userId: MiUser['id']; }; } type NoteStreamEventTypes = { diff --git a/packages/backend/src/core/NoteCreateService.ts b/packages/backend/src/core/NoteCreateService.ts index 1845d14b2c..a7f2bf5a5c 100644 --- a/packages/backend/src/core/NoteCreateService.ts +++ b/packages/backend/src/core/NoteCreateService.ts @@ -833,6 +833,7 @@ export class NoteCreateService implements OnApplicationShutdown { if (data.reply) { this.globalEventService.publishNoteStream(data.reply.id, 'replied', { id: note.id, + userId: user.id, }); // 通知 if (data.reply.userHost === null) { diff --git a/packages/backend/src/core/activitypub/models/ApImageService.ts b/packages/backend/src/core/activitypub/models/ApImageService.ts index 3d98c5b764..b281ac9728 100644 --- a/packages/backend/src/core/activitypub/models/ApImageService.ts +++ b/packages/backend/src/core/activitypub/models/ApImageService.ts @@ -82,7 +82,7 @@ export class ApImageService { url: image.url, user: actor, uri: image.url, - sensitive: image.sensitive, + sensitive: !!(image.sensitive), isLink: !shouldBeCached, comment: truncate(image.name ?? undefined, DB_MAX_IMAGE_COMMENT_LENGTH), }); diff --git a/packages/backend/src/core/entities/InstanceEntityService.ts b/packages/backend/src/core/entities/InstanceEntityService.ts index 24f6704848..7695e6dfa7 100644 --- a/packages/backend/src/core/entities/InstanceEntityService.ts +++ b/packages/backend/src/core/entities/InstanceEntityService.ts @@ -64,8 +64,9 @@ export class InstanceEntityService { @bindThis public packMany( instances: MiInstance[], + me?: { id: MiUser['id']; } | null | undefined, ) { - return Promise.all(instances.map(x => this.pack(x))); + return Promise.all(instances.map(x => this.pack(x, me))); } } diff --git a/packages/backend/src/postgres.ts b/packages/backend/src/postgres.ts index e6da273423..047b7f8ae9 100644 --- a/packages/backend/src/postgres.ts +++ b/packages/backend/src/postgres.ts @@ -240,12 +240,8 @@ export function createPostgresDataSource(config: Config) { cache: !config.db.disableCache && process.env.NODE_ENV !== 'test' ? { // dbをcloseしても何故かredisのコネクションが内部的に残り続けるようで、テストの際に支障が出るため無効にする(キャッシュも含めてテストしたいため本当は有効にしたいが...) type: 'ioredis', options: { - host: config.redis.host, - port: config.redis.port, - family: config.redis.family ?? 0, - password: config.redis.pass, + ...config.redis, keyPrefix: `${config.redis.prefix}:query:`, - db: config.redis.db ?? 0, }, } : false, logging: log, diff --git a/packages/backend/src/server/api/endpoints/federation/instances.ts b/packages/backend/src/server/api/endpoints/federation/instances.ts index c3f2247b69..c1ce3f2238 100644 --- a/packages/backend/src/server/api/endpoints/federation/instances.ts +++ b/packages/backend/src/server/api/endpoints/federation/instances.ts @@ -203,7 +203,7 @@ export default class extends Endpoint { // eslint- const instances = await query.limit(ps.limit).offset(ps.offset).getMany(); - return await this.instanceEntityService.packMany(instances); + return await this.instanceEntityService.packMany(instances, me); }); } } diff --git a/packages/backend/src/server/api/endpoints/federation/stats.ts b/packages/backend/src/server/api/endpoints/federation/stats.ts index bac54970ab..69900bff9a 100644 --- a/packages/backend/src/server/api/endpoints/federation/stats.ts +++ b/packages/backend/src/server/api/endpoints/federation/stats.ts @@ -107,9 +107,9 @@ export default class extends Endpoint { // eslint- const gotPubCount = topPubInstances.map(x => x.followingCount).reduce((a, b) => a + b, 0); return await awaitAll({ - topSubInstances: this.instanceEntityService.packMany(topSubInstances), + topSubInstances: this.instanceEntityService.packMany(topSubInstances, me), otherFollowersCount: Math.max(0, allSubCount - gotSubCount), - topPubInstances: this.instanceEntityService.packMany(topPubInstances), + topPubInstances: this.instanceEntityService.packMany(topPubInstances, me), otherFollowingCount: Math.max(0, allPubCount - gotPubCount), }); }); diff --git a/packages/backend/src/server/api/stream/Connection.ts b/packages/backend/src/server/api/stream/Connection.ts index 96082827f8..c24459c1e1 100644 --- a/packages/backend/src/server/api/stream/Connection.ts +++ b/packages/backend/src/server/api/stream/Connection.ts @@ -205,6 +205,18 @@ export default class Connection { @bindThis private async onNoteStreamMessage(data: GlobalEvents['note']['payload']) { + // we must not send to the frontend information about notes from + // users who blocked the logged-in user, even when they're replies + // to notes the logged-in user can see + if (data.type === 'replied') { + const noteUserId = data.body.body.userId; + if (noteUserId !== null) { + if (this.userIdsWhoBlockingMe.has(noteUserId)) { + return; + } + } + } + this.sendMessageToWs('noteUpdated', { id: data.body.id, type: data.type, diff --git a/packages/frontend/src/components/MkNote.vue b/packages/frontend/src/components/MkNote.vue index 7df84a70db..70651507ed 100644 --- a/packages/frontend/src/components/MkNote.vue +++ b/packages/frontend/src/components/MkNote.vue @@ -14,7 +14,7 @@ SPDX-License-Identifier: AGPL-3.0-only >
- + :