diff --git a/CHANGELOG.md b/CHANGELOG.md index a54b613c82..9aed010214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -## Unreleased +## 2025.5.0 ### General - diff --git a/locales/ca-ES.yml b/locales/ca-ES.yml index 23d20b8e13..8d723825f3 100644 --- a/locales/ca-ES.yml +++ b/locales/ca-ES.yml @@ -220,6 +220,7 @@ silenceThisInstance: "Silencia aquesta instància " mediaSilenceThisInstance: "Silenciar els arxius d'aquesta instància " operations: "Accions" software: "Programari" +softwareName: "Nom del programari" version: "Versió" metadata: "Metadades" withNFiles: "{n} fitxer(s)" @@ -1423,6 +1424,7 @@ _settings: ifOn: "Quan s'activa" ifOff: "Quan es desactiva" enableSyncThemesBetweenDevices: "Sincronitzar els temes instal·lats entre dispositius" + enablePullToRefresh: "Lliscar i actualitzar " _chat: showSenderName: "Mostrar el nom del remitent" sendOnEnter: "Introdueix per enviar" @@ -1468,6 +1470,7 @@ _delivery: manuallySuspended: "Suspendre manualment" goneSuspended: "Servidor suspès perquè el servidor s'ha esborrat" autoSuspendedForNotResponding: "Servidor suspès perquè el servidor no respon" + softwareSuspended: "Suspès perquè el programari ha deixat de desenvolupar-se " _bubbleGame: howToPlay: "Com es juga" hold: "Mantenir" @@ -1599,6 +1602,8 @@ _serverSettings: openRegistration: "Registres oberts" openRegistrationWarning: "Obrir els registres és arriscat. Es recomana obrir-los només si el servidor és monitorat constantment i per respondre immediatament davant qualsevol problema." thisSettingWillAutomaticallyOffWhenModeratorsInactive: "Si no es detecta activitat per part del moderador durant un període de temps, aquesta opció es desactiva automàticament per evitar el correu brossa." + deliverSuspendedSoftware: "Programari que ja no es distribueix" + deliverSuspendedSoftwareDescription: "Pots especificar un rang de noms i versions del programari del servidor per detenir l'entrega, per exemple, degut a vulnerabilitats. Aquesta informació la proporciona el servidor i la seva fiabilitat no es garantitzada. Es pot fer servir una especificació de rang sencer per especificar una versió, però es recomana especificar una versió anterior, com >= 2024.3.1-0, perquè especificar >= 2024.3.1 no incloure versions personalitzades com 2024.3.1-custom.0." _accountMigration: moveFrom: "Migrar un altre compte a aquest" moveFromSub: "Crear un àlies per un altre compte" diff --git a/locales/de-DE.yml b/locales/de-DE.yml index 41c3f495a2..2c7a1d6f95 100644 --- a/locales/de-DE.yml +++ b/locales/de-DE.yml @@ -220,6 +220,7 @@ silenceThisInstance: "Instanz stummschalten" mediaSilenceThisInstance: "Medien dieses Servers stummschalten" operations: "Aktionen" software: "Software" +softwareName: "Software Name" version: "Version" metadata: "Metadaten" withNFiles: "{n} Datei(en)" @@ -1423,6 +1424,7 @@ _settings: ifOn: "Wenn eingeschaltet" ifOff: "Wenn ausgeschaltet" enableSyncThemesBetweenDevices: "Synchronisierung von installierten Themen auf verschiedenen Endgeräten" + enablePullToRefresh: "Ziehen zum Aktualisieren" _chat: showSenderName: "Name des Absenders anzeigen" sendOnEnter: "Eingabetaste sendet Nachricht" @@ -1468,6 +1470,7 @@ _delivery: manuallySuspended: "Manuell gesperrt" goneSuspended: "Gesperrt wegen Löschung des Servers" autoSuspendedForNotResponding: "Gesperrt, weil der Server nicht antwortet" + softwareSuspended: "Ausgesetzt, weil die Software nicht mehr beliefert wird" _bubbleGame: howToPlay: "Wie man spielt" hold: "Halten" @@ -1599,6 +1602,8 @@ _serverSettings: openRegistration: "Registrierung von Konten aktivieren" openRegistrationWarning: "Das Aktivieren von Registrierungen ist riskant. Es wird empfohlen, sie nur dann zu aktivieren, wenn der Server ständig überwacht wird und im Falle eines Problems sofort reagiert werden kann." thisSettingWillAutomaticallyOffWhenModeratorsInactive: "Wenn über einen bestimmten Zeitraum keine Moderatorenaktivität festgestellt wird, wird diese Einstellung automatisch deaktiviert, um Spam zu verhindern." + deliverSuspendedSoftware: "Software, die nicht mehr beliefert wird" + deliverSuspendedSoftwareDescription: "Sie können eine Auswahl von Namen und Versionen verschiedener Serversoftware angeben, um die Zustellung zu stoppen, z. B. aufgrund von Sicherheitslücken. Diese Versionsinformationen werden vom Server bereitgestellt und ihre Zuverlässigkeit ist nicht garantiert. Es wird jedoch empfohlen, eine Vorabversion anzugeben, wie z. B. >= 2024.3.1-0, da die Angabe >= 2024.3.1 keine benutzerdefinierten Versionen wie 2024.3.1-custom.0 einschließt." _accountMigration: moveFrom: "Von einem anderen Konto zu diesem migrieren" moveFromSub: "Alias für ein anderes Konto erstellen" diff --git a/locales/en-US.yml b/locales/en-US.yml index 8e4063ae8a..71a442a187 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -220,6 +220,7 @@ silenceThisInstance: "Silence this instance" mediaSilenceThisInstance: "Media-silence this server" operations: "Operations" software: "Software" +softwareName: "Software" version: "Version" metadata: "Metadata" withNFiles: "{n} file(s)" @@ -1423,6 +1424,7 @@ _settings: ifOn: "When turned on" ifOff: "When turned off" enableSyncThemesBetweenDevices: "Synchronize installed themes across devices" + enablePullToRefresh: "Pull to Refresh" _chat: showSenderName: "Show sender's name" sendOnEnter: "Press Enter to send" @@ -1468,6 +1470,7 @@ _delivery: manuallySuspended: "Manually suspended" goneSuspended: "Server is suspended due to server deletion" autoSuspendedForNotResponding: "Server is suspended due to no responding" + softwareSuspended: "Suspended as this software is no longer being distributed to" _bubbleGame: howToPlay: "How to play" hold: "Hold" @@ -1599,6 +1602,8 @@ _serverSettings: openRegistration: "Make the account creation open" openRegistrationWarning: "Opening registration carries risks. It is recommended to only enable it if you have a system in place to continuously monitor the server and respond immediately in case of any issues." thisSettingWillAutomaticallyOffWhenModeratorsInactive: "If no moderator activity is detected for a while, this setting will be automatically turned off to prevent spam." + deliverSuspendedSoftware: "Suspended Software" + deliverSuspendedSoftwareDescription: "You can specify a range of names and versions of the server's software to stop delivery for vulnerability or other reasons. This version information is provided by the server and is not guaranteed to be reliable. A semver range specification can be used to specify the version, but specifying >= 2024.3.1 will not include custom versions such as 2024.3.1-custom.0, so it is recommended that a prerelease specification be used, such as >= 2024.3.1-0" _accountMigration: moveFrom: "Migrate another account to this one" moveFromSub: "Create alias to another account" diff --git a/locales/index.d.ts b/locales/index.d.ts index 1ceafff21c..88fdb3d5d0 100644 --- a/locales/index.d.ts +++ b/locales/index.d.ts @@ -5725,6 +5725,10 @@ export interface Locale extends ILocale { * ひっぱって更新 */ "enablePullToRefresh": string; + /** + * マウスでは、ホイールを押し込みながらドラッグします。 + */ + "enablePullToRefresh_description": string; /** * サーバーと接続を確立し、リアルタイムでコンテンツを更新します。通信量とバッテリーの消費が多くなる場合があります。 */ diff --git a/locales/ja-JP.yml b/locales/ja-JP.yml index 732e10b599..e0fde01309 100644 --- a/locales/ja-JP.yml +++ b/locales/ja-JP.yml @@ -1431,6 +1431,7 @@ _settings: ifOff: "オフのとき" enableSyncThemesBetweenDevices: "デバイス間でインストールしたテーマを同期" enablePullToRefresh: "ひっぱって更新" + enablePullToRefresh_description: "マウスでは、ホイールを押し込みながらドラッグします。" realtimeMode_description: "サーバーと接続を確立し、リアルタイムでコンテンツを更新します。通信量とバッテリーの消費が多くなる場合があります。" contentsUpdateFrequency: "コンテンツの取得頻度" contentsUpdateFrequency_description: "高いほどリアルタイムにコンテンツが更新されますが、パフォーマンスが低下し、通信量とバッテリーの消費が多くなります。" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 1508fca431..64b05e58f5 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -220,6 +220,7 @@ silenceThisInstance: "静音此服务器" mediaSilenceThisInstance: "隐藏此服务器的媒体文件" operations: "操作" software: "软件" +softwareName: "软件名" version: "版本" metadata: "元数据" withNFiles: "{n} 个文件" @@ -1422,6 +1423,7 @@ _settings: showNavbarSubButtons: "在导航栏中显示副按钮" ifOn: "启用时" ifOff: "关闭时" + enablePullToRefresh: "开启下拉刷新" _chat: showSenderName: "显示发送者的名字" sendOnEnter: "回车键发送" @@ -1467,6 +1469,7 @@ _delivery: manuallySuspended: "手动停止中" goneSuspended: "因服务器被删除而停止" autoSuspendedForNotResponding: "因服务器无应答而停止" + softwareSuspended: "因有不可用的软件而停止" _bubbleGame: howToPlay: "游戏说明" hold: "抓住" @@ -1598,6 +1601,7 @@ _serverSettings: openRegistration: "开放注册" openRegistrationWarning: "开放注册有风险。建议仅当能够持续监控服务器并在出现问题时能够立即响应时才打开它。" thisSettingWillAutomaticallyOffWhenModeratorsInactive: "若在一段时间内没有检测到管理活动,为防止垃圾信息,此设定将自动关闭。" + deliverSuspendedSoftware: "不可用的软件" _accountMigration: moveFrom: "从别的账号迁移到此账户" moveFromSub: "为另一个账户建立别名" diff --git a/locales/zh-TW.yml b/locales/zh-TW.yml index 152f34feeb..a57d26c113 100644 --- a/locales/zh-TW.yml +++ b/locales/zh-TW.yml @@ -220,6 +220,7 @@ silenceThisInstance: "禁言此伺服器" mediaSilenceThisInstance: "將這個伺服器的媒體設為禁言" operations: "操作" software: "軟體" +softwareName: "軟體名稱" version: "版本" metadata: "詮釋資料" withNFiles: "{n} 個檔案" @@ -1423,6 +1424,7 @@ _settings: ifOn: "開啟時" ifOff: "關閉時" enableSyncThemesBetweenDevices: "在裝置之間同步已安裝的主題" + enablePullToRefresh: "下拉更新" _chat: showSenderName: "顯示發送者的名稱" sendOnEnter: "按下 Enter 發送訊息" @@ -1468,6 +1470,7 @@ _delivery: manuallySuspended: "手動暫停中" goneSuspended: "因為伺服器刪除所以暫停中" autoSuspendedForNotResponding: "因為伺服器沒有回應所以暫停中" + softwareSuspended: "此軟體因已停止發佈,目前無法使用" _bubbleGame: howToPlay: "玩法說明" hold: "保留" @@ -1599,6 +1602,8 @@ _serverSettings: openRegistration: "允許建立帳戶" openRegistrationWarning: "開放註冊伴隨著風險。 建議只有在伺服器受到持續監控,並準備好在出現問題時能立即處理的情況下才開放註冊。" thisSettingWillAutomaticallyOffWhenModeratorsInactive: "如果在一段期間內沒有偵測到任何審查員活動,此設定將自動關閉,以防止垃圾內容。" + deliverSuspendedSoftware: "已停止發佈的軟體" + deliverSuspendedSoftwareDescription: "由於脆弱性等原因,可以指定伺服器軟體的名稱與版本範圍來停止其發佈。這些版本資訊是由伺服器所提供,其可靠性無法保證。版本的指定可以使用 semver(語意化版本控制) 的範圍語法,但如果指定為 >= 2024.3.1,則像 2024.3.1-custom.0 這樣的自訂版本將不會被包含在內,因此建議使用 >= 2024.3.1-0 的方式來同時包含預發佈版本。" _accountMigration: moveFrom: "從其他帳戶遷移到這個帳戶" moveFromSub: "為另一個帳戶建立別名" diff --git a/package.json b/package.json index 8649d1eac7..e10f4e9461 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "misskey", - "version": "2025.4.1", + "version": "2025.5.0-alpha.0", "codename": "nasubi", "repository": { "type": "git", diff --git a/packages/backend/package.json b/packages/backend/package.json index 0574403ce1..3c6dcc6523 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -223,6 +223,7 @@ "@types/semver": "7.7.0", "@types/simple-oauth2": "5.0.7", "@types/sinonjs__fake-timers": "8.1.5", + "@types/supertest": "6.0.3", "@types/tinycolor2": "1.4.6", "@types/tmp": "0.2.6", "@types/vary": "1.1.3", @@ -239,6 +240,7 @@ "jest-mock": "29.7.0", "nodemon": "3.1.10", "pid-port": "1.0.2", - "simple-oauth2": "5.1.0" + "simple-oauth2": "5.1.0", + "supertest": "7.1.0" } } diff --git a/packages/backend/src/server/ServerService.ts b/packages/backend/src/server/ServerService.ts index 355d7ca08e..c859f1d82c 100644 --- a/packages/backend/src/server/ServerService.ts +++ b/packages/backend/src/server/ServerService.ts @@ -7,7 +7,7 @@ import cluster from 'node:cluster'; import * as fs from 'node:fs'; import { fileURLToPath } from 'node:url'; import { Inject, Injectable, OnApplicationShutdown } from '@nestjs/common'; -import Fastify, { FastifyInstance } from 'fastify'; +import Fastify, { type FastifyInstance } from 'fastify'; import fastifyStatic from '@fastify/static'; import fastifyRawBody from 'fastify-raw-body'; import { IsNull } from 'typeorm'; @@ -309,6 +309,13 @@ export class ServerService implements OnApplicationShutdown { await this.#fastify.close(); } + /** + * Get the Fastify instance for testing. + */ + public get fastify(): FastifyInstance { + return this.#fastify; + } + @bindThis async onApplicationShutdown(signal: string): Promise { await this.dispose(); diff --git a/packages/backend/src/server/api/endpoints/drive/files/create.ts b/packages/backend/src/server/api/endpoints/drive/files/create.ts index 17face8f82..11c255a361 100644 --- a/packages/backend/src/server/api/endpoints/drive/files/create.ts +++ b/packages/backend/src/server/api/endpoints/drive/files/create.ts @@ -61,6 +61,7 @@ export const meta = { message: 'Cannot upload the file because it exceeds the maximum file size.', code: 'MAX_FILE_SIZE_EXCEEDED', id: 'b9d8c348-33f0-4673-b9a9-5d4da058977a', + httpStatusCode: 413, }, }, } as const; diff --git a/packages/backend/test/unit/server/api/drive/files/create.ts b/packages/backend/test/unit/server/api/drive/files/create.ts new file mode 100644 index 0000000000..9b38f4d744 --- /dev/null +++ b/packages/backend/test/unit/server/api/drive/files/create.ts @@ -0,0 +1,164 @@ +/* + * SPDX-FileCopyrightText: syuilo and misskey-project + * SPDX-License-Identifier: AGPL-3.0-only + */ + +import { Test, TestingModule } from '@nestjs/testing'; +import { FastifyInstance } from 'fastify'; +import request from 'supertest'; +import { randomString } from '../../../../../utils.js'; +import { CoreModule } from '@/core/CoreModule.js'; +import { RoleService } from '@/core/RoleService.js'; +import { DI } from '@/di-symbols.js'; +import { GlobalModule } from '@/GlobalModule.js'; +import { DriveFoldersRepository, MiDriveFolder, MiRole, UserProfilesRepository, UsersRepository } from '@/models/_.js'; +import { MiUser } from '@/models/User.js'; +import { ServerModule } from '@/server/ServerModule.js'; +import { ServerService } from '@/server/ServerService.js'; +import { IdService } from '@/core/IdService.js'; + +describe('/drive/files/create', () => { + let module: TestingModule; + let server: FastifyInstance; + let roleService: RoleService; + let idService: IdService; + + let root: MiUser; + let role_tinyAttachment: MiRole; + + let folder: MiDriveFolder; + + beforeAll(async () => { + module = await Test.createTestingModule({ + imports: [GlobalModule, CoreModule, ServerModule], + }).compile(); + module.enableShutdownHooks(); + + const serverService = module.get(ServerService); + await serverService.launch(); + server = serverService.fastify; + + idService = module.get(IdService); + + const usersRepository = module.get(DI.usersRepository); + await usersRepository.delete({}); + root = await usersRepository.insert({ + id: idService.gen(), + username: 'root', + usernameLower: 'root', + token: '1234567890123456', + }).then(x => usersRepository.findOneByOrFail(x.identifiers[0])); + + const userProfilesRepository = module.get(DI.userProfilesRepository); + await userProfilesRepository.delete({}); + await userProfilesRepository.insert({ + userId: root.id, + }); + + const driveFoldersRepository = module.get(DI.driveFoldersRepository); + folder = await driveFoldersRepository.insertOne({ + id: idService.gen(), + name: 'root-folder', + parentId: null, + userId: root.id, + }); + + roleService = module.get(RoleService); + role_tinyAttachment = await roleService.create({ + name: 'test-role001', + description: 'Test role001 description', + target: 'manual', + policies: { + maxFileSizeMb: { + useDefault: false, + priority: 1, + // 10byte + value: 10 / 1024 / 1024, + }, + }, + }); + }); + + beforeEach(async () => { + await roleService.unassign(root.id, role_tinyAttachment.id).catch(() => { + }); + }); + + afterAll(async () => { + await server.close(); + await module.close(); + }); + + async function postFile(props: { + name: string, + comment: string, + isSensitive: boolean, + force: boolean, + fileContent: Buffer | string, + }) { + const { name, comment, isSensitive, force, fileContent } = props; + + return await request(server.server) + .post('/api/drive/files/create') + .set('Content-Type', 'multipart/form-data') + .attach('file', fileContent) + .field('name', name) + .field('comment', comment) + .field('isSensitive', isSensitive) + .field('force', force) + .field('folderId', folder.id) + .field('i', root.token ?? ''); + } + + test('200 ok', async () => { + const name = randomString(); + const comment = randomString(); + const result = await postFile({ + name: name, + comment: comment, + isSensitive: true, + force: true, + fileContent: Buffer.from('a'.repeat(1000 * 1000)), + }); + expect(result.statusCode).toBe(200); + expect(result.body.name).toBe(name + '.unknown'); + expect(result.body.comment).toBe(comment); + expect(result.body.isSensitive).toBe(true); + expect(result.body.folderId).toBe(folder.id); + }); + + test('200 ok(with role)', async () => { + await roleService.assign(root.id, role_tinyAttachment.id); + + const name = randomString(); + const comment = randomString(); + const result = await postFile({ + name: name, + comment: comment, + isSensitive: true, + force: true, + fileContent: Buffer.from('a'.repeat(10)), + }); + expect(result.statusCode).toBe(200); + expect(result.body.name).toBe(name + '.unknown'); + expect(result.body.comment).toBe(comment); + expect(result.body.isSensitive).toBe(true); + expect(result.body.folderId).toBe(folder.id); + }); + + test('413 too large', async () => { + await roleService.assign(root.id, role_tinyAttachment.id); + + const name = randomString(); + const comment = randomString(); + const result = await postFile({ + name: name, + comment: comment, + isSensitive: true, + force: true, + fileContent: Buffer.from('a'.repeat(11)), + }); + expect(result.statusCode).toBe(413); + expect(result.body.error.code).toBe('MAX_FILE_SIZE_EXCEEDED'); + }); +}); diff --git a/packages/frontend/src/components/MkPullToRefresh.vue b/packages/frontend/src/components/MkPullToRefresh.vue index 7f5148dac0..7b5335aa74 100644 --- a/packages/frontend/src/components/MkPullToRefresh.vue +++ b/packages/frontend/src/components/MkPullToRefresh.vue @@ -77,31 +77,37 @@ function unlockDownScroll() { } function moveStart(event: PointerEvent) { - const scrollPos = scrollEl!.scrollTop; - if (scrollPos === 0) { - lockDownScroll(); - if (!isPulling.value && !isRefreshing.value) { - isPulling.value = true; - startScreenY = getScreenY(event); - pullDistance.value = 0; + if (event.pointerType === 'mouse' && event.button !== 1) return; + if (isRefreshing.value) return; - // タッチデバイスでPointerEventを使うとなんか挙動がおかしいので、TouchEventとMouseEventを使い分ける - if (event.pointerType === 'mouse') { - window.addEventListener('mousemove', moving, { passive: true }); - window.addEventListener('mouseup', () => { - window.removeEventListener('mousemove', moving); - onPullRelease(); - }, { passive: true, once: true }); - } else { - window.addEventListener('touchmove', moving, { passive: true }); - window.addEventListener('touchend', () => { - window.removeEventListener('touchmove', moving); - onPullRelease(); - }, { passive: true, once: true }); - } - } - } else { + const scrollPos = scrollEl!.scrollTop; + if (scrollPos !== 0) { unlockDownScroll(); + return; + } + + lockDownScroll(); + + // マウスでのpull時、画面上のテキスト選択が発生したり、ブラウザの中クリックによる挙動が競合したりして画面がスクロールされたりするのを防ぐ + window.document.body.setAttribute('inert', 'true'); + + isPulling.value = true; + startScreenY = getScreenY(event); + pullDistance.value = 0; + + // タッチデバイスでPointerEventを使うとなんか挙動がおかしいので、TouchEventとMouseEventを使い分ける + if (event.pointerType === 'mouse') { + window.addEventListener('mousemove', moving, { passive: true }); + window.addEventListener('mouseup', () => { + window.removeEventListener('mousemove', moving); + onPullRelease(); + }, { passive: true, once: true }); + } else { + window.addEventListener('touchmove', moving, { passive: true }); + window.addEventListener('touchend', () => { + window.removeEventListener('touchmove', moving); + onPullRelease(); + }, { passive: true, once: true }); } } @@ -168,8 +174,6 @@ function toggleScrollLockOnTouchEnd() { } function moving(event: MouseEvent | TouchEvent) { - if (!isPulling.value || isRefreshing.value) return; - if ((scrollEl?.scrollTop ?? 0) > SCROLL_STOP + pullDistance.value || isHorizontalSwipeSwiping.value) { pullDistance.value = 0; isPulledEnough.value = false; @@ -185,11 +189,6 @@ function moving(event: MouseEvent | TouchEvent) { const moveHeight = moveScreenY - startScreenY!; pullDistance.value = Math.min(Math.max(moveHeight, 0), MAX_PULL_DISTANCE); - // マウスでのpull時、画面上のテキスト選択が発生して画面がスクロールされたりするのを防ぐ - if (pullDistance.value > 3) { // ある程度遊びを持たせないと通常のクリックでも発火しクリックできなくなる - window.document.body.setAttribute('inert', 'true'); - } - isPulledEnough.value = pullDistance.value >= FIRE_THRESHOLD; } diff --git a/packages/frontend/src/pages/settings/preferences.vue b/packages/frontend/src/pages/settings/preferences.vue index 4571e24ac9..f22b3b84d9 100644 --- a/packages/frontend/src/pages/settings/preferences.vue +++ b/packages/frontend/src/pages/settings/preferences.vue @@ -487,6 +487,7 @@ SPDX-License-Identifier: AGPL-3.0-only + diff --git a/packages/misskey-js/package.json b/packages/misskey-js/package.json index 63fbebd5b5..7941caf632 100644 --- a/packages/misskey-js/package.json +++ b/packages/misskey-js/package.json @@ -1,7 +1,7 @@ { "type": "module", "name": "misskey-js", - "version": "2025.4.1", + "version": "2025.5.0-alpha.0", "description": "Misskey SDK for JavaScript", "license": "MIT", "main": "./built/index.js", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d8bed52a1..0b21d85a28 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -550,6 +550,9 @@ importers: '@types/sinonjs__fake-timers': specifier: 8.1.5 version: 8.1.5 + '@types/supertest': + specifier: 6.0.3 + version: 6.0.3 '@types/tinycolor2': specifier: 1.4.6 version: 1.4.6 @@ -601,6 +604,9 @@ importers: simple-oauth2: specifier: 5.1.0 version: 5.1.0 + supertest: + specifier: 7.1.0 + version: 7.1.0 optionalDependencies: '@swc/core-android-arm64': specifier: 1.3.11 @@ -3142,6 +3148,9 @@ packages: peerDependencies: '@opentelemetry/api': ^1.1.0 + '@paralleldrive/cuid2@2.2.2': + resolution: {integrity: sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==} + '@parcel/watcher-android-arm64@2.5.0': resolution: {integrity: sha512-qlX4eS28bUcQCdribHkg/herLe+0A9RyYC+mm2PXpncit8z5b3nSqGVzMNR3CmtAOgRutiZ02eIJJgP/b1iEFQ==} engines: {node: '>= 10.0.0'} @@ -4285,6 +4294,9 @@ packages: '@types/cookie@0.6.0': resolution: {integrity: sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==} + '@types/cookiejar@2.1.5': + resolution: {integrity: sha512-he+DHOWReW0nghN24E1WUqM0efK4kI9oTqDm6XmK8ZPe2djZ90BSNdGnIyCLzCPw7/pogPlGbzI2wHGGmi4O/Q==} + '@types/debug@4.1.12': resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} @@ -4372,6 +4384,9 @@ packages: '@types/mdx@2.0.3': resolution: {integrity: sha512-IgHxcT3RC8LzFLhKwP3gbMPeaK7BM9eBH46OdapPA7yvuIUJ8H6zHZV53J8hGZcTSnt95jANt+rTBNUUc22ACQ==} + '@types/methods@1.1.4': + resolution: {integrity: sha512-ymXWVrDiCxTBE3+RIrrP533E70eA+9qu7zdWoHuOmGujkYtzf4HQF96b8nwHLqhuf4ykX61IGRIB38CC6/sImQ==} + '@types/micromatch@4.0.9': resolution: {integrity: sha512-7V+8ncr22h4UoYRLnLXSpTxjQrNUXtWHGeMPRJt1nULXI57G9bIcpyrHlmrQ7QK24EyyuXvYcSSWAM8GA9nqCg==} @@ -4510,6 +4525,12 @@ packages: '@types/statuses@2.0.4': resolution: {integrity: sha512-eqNDvZsCNY49OAXB0Firg/Sc2BgoWsntsLUdybGFOhAfCD6QJ2n9HXUIHGqt5qjrxmMv4wS8WLAw43ZkKcJ8Pw==} + '@types/superagent@8.1.9': + resolution: {integrity: sha512-pTVjI73witn+9ILmoJdajHGW2jkSaOzhiFYF1Rd3EQ94kymLqB9PjD9ISg7WaALC7+dCHT0FGe9T2LktLq/3GQ==} + + '@types/supertest@6.0.3': + resolution: {integrity: sha512-8WzXq62EXFhJ7QsH3Ocb/iKQ/Ty9ZVWnVzoTKc9tyyFRRF3a74Tk2+TLFgaFFw364Ere+npzHKEJ6ga2LzIL7w==} + '@types/tedious@4.0.14': resolution: {integrity: sha512-KHPsfX/FoVbUGbyYvk1q9MMQHLPeRZhRJZdO45Q4YjvFkv4hMNghCWTvy7rdKessBsmtz4euWCWAB6/tVpI1Iw==} @@ -5575,6 +5596,9 @@ packages: compare-versions@6.1.1: resolution: {integrity: sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg==} + component-emitter@1.3.1: + resolution: {integrity: sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==} + compress-commons@6.0.2: resolution: {integrity: sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==} engines: {node: '>= 14'} @@ -5632,6 +5656,9 @@ packages: resolution: {integrity: sha512-Xd8lFX4LM9QEEwxQpF9J9NTUh8pmdJO0cyRJhFiDoLTk2eH8FXlRv2IFGYVadZpqI3j8fhNrSdKCeYPxiAhLXw==} engines: {node: '>=18'} + cookiejar@2.1.4: + resolution: {integrity: sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==} + core-js@3.29.1: resolution: {integrity: sha512-+jwgnhg6cQxKYIIjGtAHq2nwUOolo9eoFZ4sHfUH09BLXBgxnH4gA0zEd+t+BO2cNB8idaBtZFcFTRjQJRJmAw==} @@ -5941,6 +5968,9 @@ packages: devlop@1.1.0: resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dezalgo@1.0.4: + resolution: {integrity: sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==} + diff-match-patch@1.0.5: resolution: {integrity: sha512-IayShXAgj/QMXgB0IWmKx+rOPuGMhqm5w6jvFxmVenXKIzRqTAAsbBPT3kWQeGANj3jGgvcvv4yK6SxqYmikgw==} @@ -6602,6 +6632,10 @@ packages: resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==} engines: {node: '>=12.20.0'} + formidable@3.5.4: + resolution: {integrity: sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==} + engines: {node: '>=14.0.0'} + forwarded-parse@2.1.2: resolution: {integrity: sha512-alTFZZQDKMporBH77856pXgzhEzaUVmLCDk+egLgIgHst3Tpndzz8MnKe+GzRJRfvVdn69HhpW7cmXzvtLvJAw==} @@ -10015,6 +10049,14 @@ packages: peerDependencies: postcss: ^8.4.31 + superagent@9.0.2: + resolution: {integrity: sha512-xuW7dzkUpcJq7QnhOsnNUgtYp3xRwpt2F7abdRYIpCsAt0hhUqia0EdxyXZQQpNmGtsCzYHryaKSV3q3GJnq7w==} + engines: {node: '>=14.18.0'} + + supertest@7.1.0: + resolution: {integrity: sha512-5QeSO8hSrKghtcWEoPiO036fxH0Ii2wVQfFZSP0oqQhmjk8bOLhDFXr4JrvaFmPuEWUoq4znY3uSi8UzLKxGqw==} + engines: {node: '>=14.18.0'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} @@ -11528,7 +11570,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.25.6 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11548,7 +11590,7 @@ snapshots: '@babel/traverse': 7.24.7 '@babel/types': 7.25.6 convert-source-map: 2.0.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -11770,7 +11812,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.24.7 '@babel/parser': 7.25.6 '@babel/types': 7.25.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -12106,7 +12148,7 @@ snapshots: '@eslint/config-array@0.20.0': dependencies: '@eslint/object-schema': 2.1.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -12120,7 +12162,7 @@ snapshots: '@eslint/eslintrc@3.3.1': dependencies: ajv: 6.12.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) espree: 10.3.0 globals: 14.0.0 ignore: 5.3.1 @@ -13159,6 +13201,10 @@ snapshots: '@opentelemetry/api': 1.9.0 '@opentelemetry/core': 1.30.1(@opentelemetry/api@1.9.0) + '@paralleldrive/cuid2@2.2.2': + dependencies: + '@noble/hashes': 1.7.1 + '@parcel/watcher-android-arm64@2.5.0': optional: true @@ -14506,7 +14552,7 @@ snapshots: '@tokenizer/inflate@0.2.7': dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) fflate: 0.8.2 token-types: 6.0.0 transitivePeerDependencies: @@ -14586,6 +14632,8 @@ snapshots: '@types/cookie@0.6.0': {} + '@types/cookiejar@2.1.5': {} + '@types/debug@4.1.12': dependencies: '@types/ms': 0.7.34 @@ -14679,6 +14727,8 @@ snapshots: '@types/mdx@2.0.3': {} + '@types/methods@1.1.4': {} + '@types/micromatch@4.0.9': dependencies: '@types/braces': 3.0.1 @@ -14814,6 +14864,18 @@ snapshots: '@types/statuses@2.0.4': {} + '@types/superagent@8.1.9': + dependencies: + '@types/cookiejar': 2.1.5 + '@types/methods': 1.1.4 + '@types/node': 22.15.2 + form-data: 4.0.2 + + '@types/supertest@6.0.3': + dependencies: + '@types/methods': 1.1.4 + '@types/superagent': 8.1.9 + '@types/tedious@4.0.14': dependencies: '@types/node': 22.15.2 @@ -14878,7 +14940,7 @@ snapshots: '@typescript-eslint/types': 8.31.0 '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3) '@typescript-eslint/visitor-keys': 8.31.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.25.1 typescript: 5.8.3 transitivePeerDependencies: @@ -14893,7 +14955,7 @@ snapshots: dependencies: '@typescript-eslint/typescript-estree': 8.31.0(typescript@5.8.3) '@typescript-eslint/utils': 8.31.0(eslint@9.25.1)(typescript@5.8.3) - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.25.1 ts-api-utils: 2.1.0(typescript@5.8.3) typescript: 5.8.3 @@ -14906,7 +14968,7 @@ snapshots: dependencies: '@typescript-eslint/types': 8.31.0 '@typescript-eslint/visitor-keys': 8.31.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) fast-glob: 3.3.3 is-glob: 4.0.3 minimatch: 9.0.5 @@ -14943,7 +15005,7 @@ snapshots: dependencies: '@ampproject/remapping': 2.3.0 '@bcoe/v8-coverage': 1.0.2 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -15254,14 +15316,14 @@ snapshots: agent-base@6.0.2: dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color optional: true agent-base@7.1.0: dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -16098,6 +16160,8 @@ snapshots: compare-versions@6.1.1: {} + component-emitter@1.3.1: {} + compress-commons@6.0.2: dependencies: crc-32: 1.2.2 @@ -16150,6 +16214,8 @@ snapshots: cookie@1.0.1: {} + cookiejar@2.1.4: {} + core-js@3.29.1: {} core-util-is@1.0.2: {} @@ -16532,6 +16598,11 @@ snapshots: dependencies: dequal: 2.0.3 + dezalgo@1.0.4: + dependencies: + asap: 2.0.6 + wrappy: 1.0.2 + diff-match-patch@1.0.5: {} diff-sequences@29.6.3: {} @@ -16834,7 +16905,7 @@ snapshots: esbuild-register@3.5.0(esbuild@0.25.3): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) esbuild: 0.25.3 transitivePeerDependencies: - supports-color @@ -17011,7 +17082,7 @@ snapshots: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.6 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) escape-string-regexp: 4.0.0 eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0 @@ -17462,7 +17533,7 @@ snapshots: follow-redirects@1.15.9(debug@4.4.0): optionalDependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) for-each@0.3.3: dependencies: @@ -17490,6 +17561,12 @@ snapshots: dependencies: fetch-blob: 3.2.0 + formidable@3.5.4: + dependencies: + '@paralleldrive/cuid2': 2.2.2 + dezalgo: 1.0.4 + once: 1.4.0 + forwarded-parse@2.1.2: {} forwarded@0.2.0: {} @@ -17904,7 +17981,7 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -17932,7 +18009,7 @@ snapshots: https-proxy-agent@5.0.1: dependencies: agent-base: 6.0.2 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color optional: true @@ -17940,14 +18017,14 @@ snapshots: https-proxy-agent@7.0.2: dependencies: agent-base: 7.1.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.6: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -18045,7 +18122,7 @@ snapshots: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -18279,7 +18356,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -18288,7 +18365,7 @@ snapshots: istanbul-lib-source-maps@5.0.6: dependencies: '@jridgewell/trace-mapping': 0.3.25 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) istanbul-lib-coverage: 3.2.2 transitivePeerDependencies: - supports-color @@ -19312,7 +19389,7 @@ snapshots: micromark@4.0.0: dependencies: '@types/debug': 4.1.12 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) decode-named-character-reference: 1.0.2 devlop: 1.1.0 micromark-core-commonmark: 2.0.0 @@ -20717,7 +20794,7 @@ snapshots: require-in-the-middle@7.3.0: dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -21167,7 +21244,7 @@ snapshots: socks-proxy-agent@8.0.2: dependencies: agent-base: 7.1.3 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) socks: 2.7.1 transitivePeerDependencies: - supports-color @@ -21276,7 +21353,7 @@ snapshots: arg: 5.0.2 bluebird: 3.7.2 check-more-types: 2.24.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) execa: 5.1.1 lazy-ass: 1.6.0 ps-tree: 1.2.0 @@ -21468,6 +21545,27 @@ snapshots: postcss: 8.5.3 postcss-selector-parser: 6.1.2 + superagent@9.0.2: + dependencies: + component-emitter: 1.3.1 + cookiejar: 2.1.4 + debug: 4.4.0(supports-color@8.1.1) + fast-safe-stringify: 2.1.1 + form-data: 4.0.2 + formidable: 3.5.4 + methods: 1.1.2 + mime: 2.6.0 + qs: 6.14.0 + transitivePeerDependencies: + - supports-color + + supertest@7.1.0: + dependencies: + methods: 1.1.2 + superagent: 9.0.2 + transitivePeerDependencies: + - supports-color + supports-color@5.5.0: dependencies: has-flag: 3.0.0 @@ -21825,7 +21923,7 @@ snapshots: app-root-path: 3.1.0 buffer: 6.0.3 dayjs: 1.11.13 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) dotenv: 16.4.7 glob: 10.4.5 reflect-metadata: 0.2.2 @@ -22019,7 +22117,7 @@ snapshots: vite-node@3.1.2(@types/node@22.15.2)(sass@1.87.0)(terser@5.39.0)(tsx@4.19.3): dependencies: cac: 6.7.14 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) es-module-lexer: 1.6.0 pathe: 2.0.3 vite: 6.3.3(@types/node@22.15.2)(sass@1.87.0)(terser@5.39.0)(tsx@4.19.3) @@ -22068,7 +22166,7 @@ snapshots: '@vitest/spy': 3.1.2 '@vitest/utils': 3.1.2 chai: 5.2.0 - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) expect-type: 1.2.1 magic-string: 0.30.17 pathe: 2.0.3 @@ -22155,7 +22253,7 @@ snapshots: vue-eslint-parser@10.1.3(eslint@9.25.1): dependencies: - debug: 4.4.0(supports-color@5.5.0) + debug: 4.4.0(supports-color@8.1.1) eslint: 9.25.1 eslint-scope: 8.3.0 eslint-visitor-keys: 4.2.0