mirror of
https://github.com/misskey-dev/misskey.git
synced 2026-05-14 11:05:47 +02:00
Merge branch 'develop' into renovate/major-backend-update-dependencies
This commit is contained in:
@@ -10,7 +10,7 @@ const __dirname = path.dirname(__filename);
|
||||
|
||||
const args = [];
|
||||
args.push(...[
|
||||
...semver.satisfies(process.version, '^20.17.0 || ^22.0.0') ? ['--no-experimental-require-module'] : [],
|
||||
...semver.satisfies(process.version, '^20.17.0 || ^22.0.0 || ^24.10.0') ? ['--no-experimental-require-module'] : [],
|
||||
'--experimental-vm-modules',
|
||||
'--experimental-import-meta-resolve',
|
||||
path.join(__dirname, 'node_modules/jest/bin/jest.js'),
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class RoleBadgesRemoteUsers1760607435831 {
|
||||
name = 'RoleBadgesRemoteUsers1760607435831'
|
||||
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ADD "showRoleBadgesOfRemoteUsers" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" DROP COLUMN "showRoleBadgesOfRemoteUsers"`);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: syuilo and misskey-project
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
export class UnnecessaryNullDefault1760790899857 {
|
||||
name = 'UnnecessaryNullDefault1760790899857'
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async up(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "abuse_report_notification_recipient" ALTER COLUMN "userId" DROP DEFAULT`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_report_notification_recipient" ALTER COLUMN "systemWebhookId" DROP DEFAULT`);
|
||||
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "urlPreviewUserAgent" DROP DEFAULT`);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {QueryRunner} queryRunner
|
||||
*/
|
||||
async down(queryRunner) {
|
||||
await queryRunner.query(`ALTER TABLE "meta" ALTER COLUMN "urlPreviewUserAgent" SET DEFAULT NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_report_notification_recipient" ALTER COLUMN "systemWebhookId" SET DEFAULT NULL`);
|
||||
await queryRunner.query(`ALTER TABLE "abuse_report_notification_recipient" ALTER COLUMN "userId" SET DEFAULT NULL`);
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"engines": {
|
||||
"node": "^22.15.0"
|
||||
"node": "^22.15.0 || ^24.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "node ./built/boot/entry.js",
|
||||
@@ -39,17 +39,17 @@
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@swc/core-android-arm64": "1.3.11",
|
||||
"@swc/core-darwin-arm64": "1.13.19",
|
||||
"@swc/core-darwin-x64": "1.13.19",
|
||||
"@swc/core-darwin-arm64": "1.13.20",
|
||||
"@swc/core-darwin-x64": "1.13.20",
|
||||
"@swc/core-freebsd-x64": "1.3.11",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.13.19",
|
||||
"@swc/core-linux-arm64-gnu": "1.13.19",
|
||||
"@swc/core-linux-arm64-musl": "1.13.19",
|
||||
"@swc/core-linux-x64-gnu": "1.13.19",
|
||||
"@swc/core-linux-x64-musl": "1.13.19",
|
||||
"@swc/core-win32-arm64-msvc": "1.13.19",
|
||||
"@swc/core-win32-ia32-msvc": "1.13.19",
|
||||
"@swc/core-win32-x64-msvc": "1.13.19",
|
||||
"@swc/core-linux-arm-gnueabihf": "1.13.20",
|
||||
"@swc/core-linux-arm64-gnu": "1.13.20",
|
||||
"@swc/core-linux-arm64-musl": "1.13.20",
|
||||
"@swc/core-linux-x64-gnu": "1.13.20",
|
||||
"@swc/core-linux-x64-musl": "1.13.20",
|
||||
"@swc/core-win32-arm64-msvc": "1.13.20",
|
||||
"@swc/core-win32-ia32-msvc": "1.13.20",
|
||||
"@swc/core-win32-x64-msvc": "1.13.20",
|
||||
"@tensorflow/tfjs": "4.22.0",
|
||||
"@tensorflow/tfjs-node": "4.22.0",
|
||||
"bufferutil": "4.0.9",
|
||||
@@ -69,8 +69,8 @@
|
||||
"utf-8-validate": "6.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"@aws-sdk/client-s3": "3.899.0",
|
||||
"@aws-sdk/lib-storage": "3.900.0",
|
||||
"@aws-sdk/client-s3": "3.908.0",
|
||||
"@aws-sdk/lib-storage": "3.908.0",
|
||||
"@discordapp/twemoji": "16.0.1",
|
||||
"@fastify/accepts": "5.0.3",
|
||||
"@fastify/cookie": "11.0.2",
|
||||
@@ -87,8 +87,8 @@
|
||||
"@nestjs/core": "11.1.6",
|
||||
"@nestjs/testing": "11.1.6",
|
||||
"@peertube/http-signature": "1.7.0",
|
||||
"@sentry/node": "10.17.0",
|
||||
"@sentry/profiling-node": "10.17.0",
|
||||
"@sentry/node": "10.20.0",
|
||||
"@sentry/profiling-node": "10.20.0",
|
||||
"@simplewebauthn/server": "13.2.1",
|
||||
"@sinonjs/fake-timers": "15.0.0",
|
||||
"@smithy/node-http-handler": "4.3.0",
|
||||
@@ -103,7 +103,7 @@
|
||||
"bcryptjs": "3.0.2",
|
||||
"blurhash": "2.0.5",
|
||||
"body-parser": "2.2.0",
|
||||
"bullmq": "5.59.0",
|
||||
"bullmq": "5.61.0",
|
||||
"cacheable-lookup": "7.0.0",
|
||||
"cbor": "10.0.11",
|
||||
"chalk": "5.6.2",
|
||||
@@ -120,12 +120,12 @@
|
||||
"file-type": "21.0.0",
|
||||
"fluent-ffmpeg": "2.1.3",
|
||||
"form-data": "4.0.4",
|
||||
"got": "14.4.9",
|
||||
"happy-dom": "19.0.2",
|
||||
"got": "14.5.0",
|
||||
"happy-dom": "20.0.7",
|
||||
"hpagent": "1.2.0",
|
||||
"htmlescape": "1.1.1",
|
||||
"http-link-header": "1.1.3",
|
||||
"ioredis": "5.8.0",
|
||||
"ioredis": "5.8.1",
|
||||
"ip-cidr": "4.0.2",
|
||||
"ipaddr.js": "2.2.0",
|
||||
"is-svg": "6.1.0",
|
||||
@@ -145,7 +145,7 @@
|
||||
"nanoid": "5.1.6",
|
||||
"nested-property": "4.0.0",
|
||||
"node-fetch": "3.3.2",
|
||||
"nodemailer": "7.0.6",
|
||||
"nodemailer": "7.0.9",
|
||||
"nsfwjs": "4.2.0",
|
||||
"oauth": "0.10.2",
|
||||
"oauth2orize": "1.12.0",
|
||||
@@ -169,12 +169,12 @@
|
||||
"rxjs": "7.8.2",
|
||||
"sanitize-html": "2.17.0",
|
||||
"secure-json-parse": "4.0.0",
|
||||
"semver": "7.7.2",
|
||||
"sharp": "0.33.5",
|
||||
"semver": "7.7.3",
|
||||
"slacc": "0.0.10",
|
||||
"strict-event-emitter-types": "2.0.0",
|
||||
"stringz": "2.1.0",
|
||||
"systeminformation": "5.27.10",
|
||||
"systeminformation": "5.27.11",
|
||||
"tinycolor2": "1.6.0",
|
||||
"tmp": "0.2.5",
|
||||
"tsc-alias": "1.8.16",
|
||||
@@ -190,7 +190,7 @@
|
||||
"devDependencies": {
|
||||
"@jest/globals": "29.7.0",
|
||||
"@nestjs/platform-express": "11.1.6",
|
||||
"@sentry/vue": "10.17.0",
|
||||
"@sentry/vue": "10.20.0",
|
||||
"@simplewebauthn/types": "12.0.0",
|
||||
"@swc/jest": "0.2.39",
|
||||
"@types/accepts": "1.3.7",
|
||||
@@ -208,7 +208,7 @@
|
||||
"@types/jsrsasign": "10.5.15",
|
||||
"@types/mime-types": "3.0.1",
|
||||
"@types/ms": "2.1.0",
|
||||
"@types/node": "24.6.1",
|
||||
"@types/node": "24.9.1",
|
||||
"@types/nodemailer": "7.0.2",
|
||||
"@types/oauth": "0.9.6",
|
||||
"@types/oauth2orize": "1.11.5",
|
||||
@@ -229,8 +229,8 @@
|
||||
"@types/vary": "1.1.3",
|
||||
"@types/web-push": "3.6.4",
|
||||
"@types/ws": "8.18.1",
|
||||
"@typescript-eslint/eslint-plugin": "8.45.0",
|
||||
"@typescript-eslint/parser": "8.45.0",
|
||||
"@typescript-eslint/eslint-plugin": "8.46.1",
|
||||
"@typescript-eslint/parser": "8.46.1",
|
||||
"aws-sdk-client-mock": "4.1.0",
|
||||
"cross-env": "10.1.0",
|
||||
"eslint-plugin-import": "2.32.0",
|
||||
|
||||
@@ -517,40 +517,43 @@ export class DriveService {
|
||||
this.registerLogger.debug(`ADD DRIVE FILE: user ${user?.id ?? 'not set'}, name ${detectedName}, tmp ${path}`);
|
||||
|
||||
//#region Check drive usage and mime type
|
||||
if (user && !isLink) {
|
||||
if (user != null && !isLink) {
|
||||
const isLocalUser = this.userEntityService.isLocalUser(user);
|
||||
const policies = await this.roleService.getUserPolicies(user.id);
|
||||
const isModerator = isLocalUser ? await this.roleService.isModerator(user) : false;
|
||||
if (!isModerator) {
|
||||
const policies = await this.roleService.getUserPolicies(user.id);
|
||||
|
||||
const allowedMimeTypes = policies.uploadableFileTypes;
|
||||
const isAllowed = allowedMimeTypes.some((mimeType) => {
|
||||
if (mimeType === '*' || mimeType === '*/*') return true;
|
||||
if (mimeType.endsWith('/*')) return info.type.mime.startsWith(mimeType.slice(0, -1));
|
||||
return info.type.mime === mimeType;
|
||||
});
|
||||
if (!isAllowed) {
|
||||
throw new IdentifiableError('bd71c601-f9b0-4808-9137-a330647ced9b', `Unallowed file type: ${info.type.mime}`);
|
||||
}
|
||||
|
||||
const driveCapacity = 1024 * 1024 * policies.driveCapacityMb;
|
||||
const maxFileSize = 1024 * 1024 * policies.maxFileSizeMb;
|
||||
|
||||
if (maxFileSize < info.size) {
|
||||
if (isLocalUser) {
|
||||
throw new IdentifiableError('f9e4e5f3-4df4-40b5-b400-f236945f7073', 'Max file size exceeded.');
|
||||
const allowedMimeTypes = policies.uploadableFileTypes;
|
||||
const isAllowed = allowedMimeTypes.some((mimeType) => {
|
||||
if (mimeType === '*' || mimeType === '*/*') return true;
|
||||
if (mimeType.endsWith('/*')) return info.type.mime.startsWith(mimeType.slice(0, -1));
|
||||
return info.type.mime === mimeType;
|
||||
});
|
||||
if (!isAllowed) {
|
||||
throw new IdentifiableError('bd71c601-f9b0-4808-9137-a330647ced9b', `Unallowed file type: ${info.type.mime}`);
|
||||
}
|
||||
}
|
||||
|
||||
const usage = await this.driveFileEntityService.calcDriveUsageOf(user);
|
||||
const driveCapacity = 1024 * 1024 * policies.driveCapacityMb;
|
||||
const maxFileSize = 1024 * 1024 * policies.maxFileSizeMb;
|
||||
|
||||
this.registerLogger.debug('drive capacity override applied');
|
||||
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
|
||||
|
||||
// If usage limit exceeded
|
||||
if (driveCapacity < usage + info.size) {
|
||||
if (isLocalUser) {
|
||||
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
|
||||
if (maxFileSize < info.size) {
|
||||
if (isLocalUser) {
|
||||
throw new IdentifiableError('f9e4e5f3-4df4-40b5-b400-f236945f7073', 'Max file size exceeded.');
|
||||
}
|
||||
}
|
||||
|
||||
const usage = await this.driveFileEntityService.calcDriveUsageOf(user);
|
||||
|
||||
this.registerLogger.debug('drive capacity override applied');
|
||||
this.registerLogger.debug(`overrideCap: ${driveCapacity}bytes, usage: ${usage}bytes, u+s: ${usage + info.size}bytes`);
|
||||
|
||||
// If usage limit exceeded
|
||||
if (driveCapacity < usage + info.size) {
|
||||
if (isLocalUser) {
|
||||
throw new IdentifiableError('c6244ed2-a39a-4e1c-bf93-f0fbd7764fa6', 'No free space.');
|
||||
}
|
||||
await this.expireOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as MiRemoteUser, driveCapacity - info.size);
|
||||
}
|
||||
await this.expireOldFile(await this.usersRepository.findOneByOrFail({ id: user.id }) as MiRemoteUser, driveCapacity - info.size);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
@@ -20,8 +20,8 @@ import { AiService } from '@/core/AiService.js';
|
||||
import { LoggerService } from '@/core/LoggerService.js';
|
||||
import type Logger from '@/logger.js';
|
||||
import { bindThis } from '@/decorators.js';
|
||||
import type { PredictionType } from 'nsfwjs';
|
||||
import { isMimeImage } from '@/misc/is-mime-image.js';
|
||||
import type { PredictionType } from 'nsfwjs';
|
||||
|
||||
export type FileInfo = {
|
||||
size: number;
|
||||
|
||||
@@ -172,6 +172,14 @@ export class NoteDraftService {
|
||||
me: MiLocalUser,
|
||||
data: Partial<NoteDraftOptions>,
|
||||
): Promise<void> {
|
||||
if (data.isActuallyScheduled) {
|
||||
if (data.scheduledAt == null) {
|
||||
throw new IdentifiableError('94a89a43-3591-400a-9c17-dd166e71fdfa', 'scheduledAt is required when isActuallyScheduled is true');
|
||||
} else if (data.scheduledAt.getTime() < Date.now()) {
|
||||
throw new IdentifiableError('b34d0c1b-996f-4e34-a428-c636d98df457', 'scheduledAt must be in the future');
|
||||
}
|
||||
}
|
||||
|
||||
if (data.pollExpiresAt != null) {
|
||||
if (data.pollExpiresAt.getTime() < Date.now()) {
|
||||
throw new IdentifiableError('04da457d-b083-4055-9082-955525eda5a5', 'Cannot create expired poll');
|
||||
@@ -320,6 +328,7 @@ export class NoteDraftService {
|
||||
|
||||
@bindThis
|
||||
public async clearSchedule(draftId: MiNoteDraft['id']): Promise<void> {
|
||||
// TODO: 線形探索なのをどうにかする
|
||||
const jobs = await this.queueService.postScheduledNoteQueue.getJobs(['delayed', 'waiting', 'active']);
|
||||
for (const job of jobs) {
|
||||
if (job.data.noteDraftId === draftId) {
|
||||
|
||||
@@ -109,8 +109,7 @@ export const DEFAULT_POLICIES: RolePolicies = {
|
||||
canImportUserLists: false,
|
||||
chatAvailability: 'available',
|
||||
uploadableFileTypes: [
|
||||
'text/plain',
|
||||
'text/csv',
|
||||
'text/*',
|
||||
'application/json',
|
||||
'image/*',
|
||||
'video/*',
|
||||
|
||||
@@ -512,8 +512,8 @@ export class UserEntityService implements OnModuleInit {
|
||||
} : undefined) : undefined,
|
||||
emojis: this.customEmojiService.populateEmojis(user.emojis, user.host),
|
||||
onlineStatus: this.getOnlineStatus(user),
|
||||
// パフォーマンス上の理由でローカルユーザーのみ
|
||||
badgeRoles: user.host == null ? this.roleService.getUserBadgeRoles(user.id).then((rs) => rs
|
||||
// パフォーマンス上の理由で、明示的に設定しない場合はローカルユーザーのみ取得
|
||||
badgeRoles: (this.meta.showRoleBadgesOfRemoteUsers || user.host == null) ? this.roleService.getUserBadgeRoles(user.id).then((rs) => rs
|
||||
.filter((r) => r.isPublic || iAmModerator)
|
||||
.sort((a, b) => b.displayOrder - a.displayOrder)
|
||||
.map((r) => ({
|
||||
|
||||
@@ -717,6 +717,11 @@ export class MiMeta {
|
||||
})
|
||||
public remoteNotesCleaningExpiryDaysForEachNotes: number;
|
||||
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
public showRoleBadgesOfRemoteUsers: boolean;
|
||||
|
||||
@Column('jsonb', {
|
||||
default: { },
|
||||
})
|
||||
|
||||
@@ -153,11 +153,14 @@ export class MiNoteDraft {
|
||||
|
||||
//#endregion
|
||||
|
||||
// 予約日時
|
||||
// これがあるだけでは実際に予約されているかどうかはわからない
|
||||
@Column('timestamp with time zone', {
|
||||
nullable: true,
|
||||
})
|
||||
public scheduledAt: Date | null;
|
||||
|
||||
// scheduledAtに基づいて実際にスケジュールされているか
|
||||
@Column('boolean', {
|
||||
default: false,
|
||||
})
|
||||
|
||||
@@ -593,6 +593,10 @@ export const meta = {
|
||||
type: 'number',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
showRoleBadgesOfRemoteUsers: {
|
||||
type: 'boolean',
|
||||
optional: false, nullable: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
} as const;
|
||||
@@ -748,6 +752,7 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
enableRemoteNotesCleaning: instance.enableRemoteNotesCleaning,
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: instance.remoteNotesCleaningExpiryDaysForEachNotes,
|
||||
remoteNotesCleaningMaxProcessingDurationInMinutes: instance.remoteNotesCleaningMaxProcessingDurationInMinutes,
|
||||
showRoleBadgesOfRemoteUsers: instance.showRoleBadgesOfRemoteUsers,
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
@@ -209,6 +209,7 @@ export const paramDef = {
|
||||
enableRemoteNotesCleaning: { type: 'boolean' },
|
||||
remoteNotesCleaningExpiryDaysForEachNotes: { type: 'number' },
|
||||
remoteNotesCleaningMaxProcessingDurationInMinutes: { type: 'number' },
|
||||
showRoleBadgesOfRemoteUsers: { type: 'boolean' },
|
||||
},
|
||||
required: [],
|
||||
} as const;
|
||||
@@ -743,6 +744,10 @@ export default class extends Endpoint<typeof meta, typeof paramDef> { // eslint-
|
||||
set.remoteNotesCleaningMaxProcessingDurationInMinutes = ps.remoteNotesCleaningMaxProcessingDurationInMinutes;
|
||||
}
|
||||
|
||||
if (ps.showRoleBadgesOfRemoteUsers !== undefined) {
|
||||
set.showRoleBadgesOfRemoteUsers = ps.showRoleBadgesOfRemoteUsers;
|
||||
}
|
||||
|
||||
const before = await this.metaService.fetch(true);
|
||||
|
||||
await this.metaService.update(set);
|
||||
|
||||
@@ -316,8 +316,12 @@ export const uploadFile = async (user?: UserToken, { path, name, blob }: UploadO
|
||||
: new URL(path, new URL('resources/', import.meta.url));
|
||||
|
||||
const formData = new FormData();
|
||||
formData.append('file', blob ??
|
||||
new File([new Uint8Array(await readFile(absPath))], basename(absPath.toString())));
|
||||
formData.append(
|
||||
'file',
|
||||
blob ?? new Blob([new Uint8Array(await readFile(absPath))]),
|
||||
basename(absPath.toString()),
|
||||
);
|
||||
|
||||
formData.append('force', 'true');
|
||||
if (name) {
|
||||
formData.append('name', name);
|
||||
|
||||
Reference in New Issue
Block a user