Skip to content

Commit

Permalink
Merge branch 'develop' into enhance/mismatch-uri-hosts
Browse files Browse the repository at this point in the history
  • Loading branch information
4ster1sk authored Dec 28, 2024
2 parents dc95ae9 + 5eeddf5 commit f239a60
Show file tree
Hide file tree
Showing 61 changed files with 1,279 additions and 234 deletions.
23 changes: 15 additions & 8 deletions .github/workflows/docker-develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
workflow_dispatch:

env:
REGISTRY_IMAGE: misskey/misskey
REGISTRY_IMAGE: ghcr.io/${{ github.repository }}

jobs:
# see https://docs.docker.com/build/ci/github-actions/multi-platform/#distribute-build-across-multiple-runners
Expand All @@ -20,7 +20,7 @@ jobs:
platform:
- linux/amd64
- linux/arm64
if: github.repository == 'misskey-dev/misskey'
if: github.repository == '4ster1sk/misskey'
steps:
- name: Prepare
run: |
Expand All @@ -30,11 +30,16 @@ jobs:
uses: actions/[email protected]
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Docker Hub
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Update version
run : |
commit_id=$(git rev-parse --short HEAD)
jq --arg commit_id "$commit_id" '.version += "-build-" + $commit_id' package.json > tmp.json && mv tmp.json package.json
- name: Build and push by digest
id: build
uses: docker/build-push-action@v6
Expand Down Expand Up @@ -73,11 +78,13 @@ jobs:
merge-multiple: true
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
tags: ${{ env.REGISTRY_IMAGE }}:develop
- name: Create manifest list and push
working-directory: /tmp/digests
run: |
Expand Down
8 changes: 8 additions & 0 deletions locales/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ lightThemes: "Light themes"
darkThemes: "Dark themes"
syncDeviceDarkMode: "Sync Dark Mode with your device settings"
drive: "Drive"
driveSearchbarPlaceholder: "Search drive"
driveSearchNotFound: "{query} not found"
fileName: "Filename"
selectFile: "Select a file"
selectFiles: "Select files"
Expand Down Expand Up @@ -1776,6 +1778,7 @@ _role:
canUpdateBioMedia: "Can edit an icon or a banner image"
pinMax: "Maximum number of pinned notes"
antennaMax: "Maximum number of antennas"
antennaNotesMax: "Maximum number of notes stored in antennas"
wordMuteMax: "Maximum number of characters allowed in word mutes"
webhookMax: "Maximum number of Webhooks"
clipMax: "Maximum number of Clips"
Expand Down Expand Up @@ -2732,6 +2735,11 @@ _embedCodeGen:
generateCode: "Generate embed code"
codeGenerated: "The code has been generated"
codeGeneratedDescription: "Paste the generated code into your website to embed the content."
_searchSite:
google: "Google"
bing: "Bing"
duckduckgo: "DuckDuckGo"
yahoo: "Yahoo! Japan"
_selfXssPrevention:
warning: "WARNING"
title: "\"Paste something on this screen\" is all a scam."
Expand Down
44 changes: 44 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1322,6 +1322,14 @@ export interface Locale extends ILocale {
* ドライブ
*/
"drive": string;
/**
* 検索ドライブ
*/
"driveSearchbarPlaceholder": string;
/**
* {query}は見つかりません
*/
"driveSearchNotFound": ParameterizedString<"query">;
/**
* ファイル名
*/
Expand Down Expand Up @@ -6917,6 +6925,10 @@ export interface Locale extends ILocale {
* ドライブ容量
*/
"driveCapacity": string;
/**
* ファイルサイズ上限
*/
"fileSizeLimit": string;
/**
* ファイルにNSFWを常に付与
*/
Expand All @@ -6933,6 +6945,10 @@ export interface Locale extends ILocale {
* アンテナの作成可能数
*/
"antennaMax": string;
/**
* アンテナに保持する最大ノート数
*/
"antennaNotesMax": string;
/**
* ワードミュートの最大文字数
*/
Expand Down Expand Up @@ -10569,6 +10585,24 @@ export interface Locale extends ILocale {
*/
"codeGeneratedDescription": string;
};
"_searchSite": {
/**
* Google
*/
"google": string;
/**
* Bing
*/
"bing": string;
/**
* DuckDuckGo
*/
"duckduckgo": string;
/**
* Yahoo! Japan
*/
"yahoo": string;
};
"_selfXssPrevention": {
/**
* 警告
Expand Down Expand Up @@ -10601,6 +10635,16 @@ export interface Locale extends ILocale {
*/
"sent": string;
};
"_customizeFeature": {
/**
* 独自機能
*/
"title": string;
/**
* Signupの無効化
*/
"disableSignup": string;
};
"_remoteLookupErrors": {
"_federationNotAllowed": {
/**
Expand Down
13 changes: 13 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,8 @@ lightThemes: "明るいテーマ"
darkThemes: "暗いテーマ"
syncDeviceDarkMode: "デバイスのダークモードと同期する"
drive: "ドライブ"
driveSearchbarPlaceholder: "検索ドライブ"
driveSearchNotFound: "{query}は見つかりません"
fileName: "ファイル名"
selectFile: "ファイルを選択"
selectFiles: "ファイルを選択"
Expand Down Expand Up @@ -1788,10 +1790,12 @@ _role:
canManageCustomEmojis: "カスタム絵文字の管理"
canManageAvatarDecorations: "アバターデコレーションの管理"
driveCapacity: "ドライブ容量"
fileSizeLimit: "ファイルサイズ上限"
alwaysMarkNsfw: "ファイルにNSFWを常に付与"
canUpdateBioMedia: "アイコンとバナーの更新を許可"
pinMax: "ノートのピン留めの最大数"
antennaMax: "アンテナの作成可能数"
antennaNotesMax: "アンテナに保持する最大ノート数"
wordMuteMax: "ワードミュートの最大文字数"
webhookMax: "Webhookの作成可能数"
clipMax: "クリップの作成可能数"
Expand Down Expand Up @@ -2815,6 +2819,11 @@ _embedCodeGen:
generateCode: "埋め込みコードを作成"
codeGenerated: "コードが生成されました"
codeGeneratedDescription: "生成されたコードをウェブサイトに貼り付けてご利用ください。"
_searchSite:
google: "Google"
bing: "Bing"
duckduckgo: "DuckDuckGo"
yahoo: "Yahoo! Japan"

_selfXssPrevention:
warning: "警告"
Expand All @@ -2827,6 +2836,10 @@ _followRequest:
recieved: "受け取った申請"
sent: "送った申請"

_customizeFeature:
title: "独自機能"
disableSignup: "Signupの無効化"

_remoteLookupErrors:
_federationNotAllowed:
title: "このサーバーとは通信できません"
Expand Down
2 changes: 1 addition & 1 deletion packages/backend/assets/robots.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
user-agent: *
allow: /
disallow: /

# todo: sitemap
16 changes: 16 additions & 0 deletions packages/backend/migration/1733996957482-signinButtonToToggle.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: ruru
* SPDX-License-Identifier: AGPL-3.0-only
*/

export class SigninButtonToToggle1733996957482 {
name = 'SigninButtonToToggle1733996957482'

async up(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" ADD "disableSignup" boolean NOT NULL DEFAULT false`);
}

async down(queryRunner) {
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "disableSignup"`);
}
}
10 changes: 9 additions & 1 deletion packages/backend/src/core/AntennaService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { UtilityService } from '@/core/UtilityService.js';
import { bindThis } from '@/decorators.js';
import type { GlobalEvents } from '@/core/GlobalEventService.js';
import { FanoutTimelineService } from '@/core/FanoutTimelineService.js';
import { RolePolicies, RoleService } from '@/core/RoleService.js';
import type { OnApplicationShutdown } from '@nestjs/common';

@Injectable()
Expand All @@ -40,6 +41,7 @@ export class AntennaService implements OnApplicationShutdown {
private utilityService: UtilityService,
private globalEventService: GlobalEventService,
private fanoutTimelineService: FanoutTimelineService,
private roleService: RoleService,
) {
this.antennasFetched = false;
this.antennas = [];
Expand Down Expand Up @@ -99,8 +101,14 @@ export class AntennaService implements OnApplicationShutdown {

const redisPipeline = this.redisForTimelines.pipeline();

const policies = new Map((await Promise.allSettled(Array.from(new Set(matchedAntennas.map(antenna => antenna.userId))).map(async userId => [userId, await this.roleService.getUserPolicies(userId)] as const)))
.filter((result): result is PromiseFulfilledResult<[string, RolePolicies]> => result.status === 'fulfilled')
.map(result => result.value));

for (const antenna of matchedAntennas) {
this.fanoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, 200, redisPipeline);
const { antennaNotesLimit } = policies.get(antenna.userId) ?? await this.roleService.getUserPolicies(antenna.userId);

this.fanoutTimelineService.push(`antennaTimeline:${antenna.id}`, note.id, antennaNotesLimit, redisPipeline);
this.globalEventService.publishAntennaStream(antenna.id, 'note', note);
}

Expand Down
2 changes: 1 addition & 1 deletion packages/backend/src/core/CustomEmojiService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ export class CustomEmojiService implements OnApplicationShutdown {
this.localEmojisCache.refresh();

this.globalEventService.publishBroadcastStream('emojiAdded', {
emoji: await this.emojiEntityService.packDetailed(emoji.id),
emoji: await this.emojiEntityService.packDetailed(emoji),
});

if (moderator) {
Expand Down
13 changes: 10 additions & 3 deletions packages/backend/src/core/DriveService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,8 @@ export class DriveService {
?? `${ this.meta.objectStorageUseSSL ? 'https' : 'http' }://${ this.meta.objectStorageEndpoint }${ this.meta.objectStoragePort ? `:${this.meta.objectStoragePort}` : '' }/${ this.meta.objectStorageBucket }`;

// for original
const key = `${this.meta.objectStoragePrefix}/${randomUUID()}${ext}`;
const p = `${this.meta.objectStoragePrefix ? this.meta.objectStoragePrefix + '/' : ''}`;
const key = `${p}${randomUUID()}${ext}`;
const url = `${ baseUrl }/${ key }`;

// for alts
Expand All @@ -190,15 +191,15 @@ export class DriveService {
];

if (alts.webpublic) {
webpublicKey = `${this.meta.objectStoragePrefix}/webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicKey = `${p}webpublic-${randomUUID()}.${alts.webpublic.ext}`;
webpublicUrl = `${ baseUrl }/${ webpublicKey }`;

this.registerLogger.info(`uploading webpublic: ${webpublicKey}`);
uploads.push(this.upload(webpublicKey, alts.webpublic.data, alts.webpublic.type, alts.webpublic.ext, name));
}

if (alts.thumbnail) {
thumbnailKey = `${this.meta.objectStoragePrefix}/thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailKey = `${p}thumbnail-${randomUUID()}.${alts.thumbnail.ext}`;
thumbnailUrl = `${ baseUrl }/${ thumbnailKey }`;

this.registerLogger.info(`uploading thumbnail: ${thumbnailKey}`);
Expand Down Expand Up @@ -478,6 +479,12 @@ export class DriveService {
sensitiveThresholdForPorn: 0.75,
enableSensitiveMediaDetectionForVideos: this.meta.enableSensitiveMediaDetectionForVideos,
});
//ファイル単位の容量制限チェック
if (user == null) {
//system user skip
} else if (info.size > (await this.roleService.getUserPolicies(user.id)).fileSizeLimit * 1024 * 1024) {
throw new IdentifiableError('e5989b6d-ae66-49ed-88af-516ded10ca0c', 'File size limit over');
}
this.registerLogger.info(`${JSON.stringify(info)}`);

// 現状 false positive が多すぎて実用に耐えない
Expand Down
19 changes: 18 additions & 1 deletion packages/backend/src/core/NoteCreateService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ import { isReply } from '@/misc/is-reply.js';
import { trackPromise } from '@/misc/promise-tracker.js';
import { IdentifiableError } from '@/misc/identifiable-error.js';
import { CollapsedQueue } from '@/misc/collapsed-queue.js';
import type Logger from '@/logger.js';
import { LoggerService } from '@/core/LoggerService.js';
import { CacheService } from '@/core/CacheService.js';

type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
Expand Down Expand Up @@ -149,6 +151,7 @@ type Option = {
export class NoteCreateService implements OnApplicationShutdown {
#shutdownController = new AbortController();
private updateNotesCountQueue: CollapsedQueue<MiNote['id'], number>;
private logger: Logger;

constructor(
@Inject(DI.config)
Expand Down Expand Up @@ -218,9 +221,11 @@ export class NoteCreateService implements OnApplicationShutdown {
private instanceChart: InstanceChart,
private utilityService: UtilityService,
private userBlockingService: UserBlockingService,
private loggerService: LoggerService,
private cacheService: CacheService,
) {
this.updateNotesCountQueue = new CollapsedQueue(process.env.NODE_ENV !== 'test' ? 60 * 1000 * 5 : 0, this.collapseNotesCount, this.performUpdateNotesCount);
this.logger = this.loggerService.getLogger('noteCreateService');
}

@bindThis
Expand Down Expand Up @@ -368,6 +373,18 @@ export class NoteCreateService implements OnApplicationShutdown {
// if the host is media-silenced, custom emojis are not allowed
if (this.utilityService.isMediaSilencedHost(this.meta.mediaSilencedHosts, user.host)) emojis = [];

const willCauseNotification = mentionedUsers.some(u => u.host === null)
|| (data.visibility === 'specified' && data.visibleUsers?.some(u => u.host === null))
|| data.reply?.userHost === null || (this.isQuote(data) && data.renote?.userHost === null) || false;

if (process.env.MISSKEY_BLOCK_MENTIONS_FROM_UNFAMILIAR_REMOTE_USERS === 'true' && user.host !== null && willCauseNotification) {
const userEntity = await this.usersRepository.findOneBy({ id: user.id });
if ((userEntity?.followersCount ?? 0) === 0) {
this.logger.error('Request rejected because user has no local followers', { user: user.id, note: data });
throw new IdentifiableError('e11b3a16-f543-4885-8eb1-66cad131dbfd', 'Notes including mentions, replies, or renotes from remote users are not allowed until user has at least one local follower.');
}
}

tags = tags.filter(tag => Array.from(tag).length <= 128).splice(0, 32);

if (data.reply && (user.id !== data.reply.userId) && !mentionedUsers.some(u => u.id === data.reply!.userId)) {
Expand Down Expand Up @@ -742,7 +759,7 @@ export class NoteCreateService implements OnApplicationShutdown {
}

@bindThis
private isQuote(note: Option & { renote: MiNote }): note is Option & { renote: MiNote } & (
private isQuote(note: Option): note is Option & { renote: MiNote } & (
{ text: string } | { cw: string } | { reply: MiNote } | { poll: IPoll } | { files: MiDriveFile[] }
) {
// NOTE: SYNC WITH misc/is-quote.ts
Expand Down
Loading

0 comments on commit f239a60

Please sign in to comment.