diff --git a/Cargo.lock b/Cargo.lock index 25eacb6a2b..974715ab54 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -213,6 +213,7 @@ dependencies = [ "chrono", "cuid2", "emojis", + "futures-util", "idna 1.0.2", "image", "isahc", diff --git a/Cargo.toml b/Cargo.toml index b1d594a12f..421ae8b674 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,6 +23,7 @@ chrono = { version = "0.4.38", default-features = false } convert_case = { version = "0.6.0", default-features = false } cuid2 = { version = "0.1.2", default-features = false } emojis = { version = "0.6.3", default-features = false } +futures-util = { version = "0.3.30", default-features = false } idna = { version = "1.0.2", default-features = false } image = { version = "0.25.2", default-features = false } isahc = { version = "1.7.2", default-features = false } diff --git a/docs/changelog.md b/docs/changelog.md index 3c88bb75c0..1f4729fc7f 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -7,6 +7,11 @@ This changelog is not an exhaustive list. Code refactorings, minor bug fixes, do - Server administrators must check [notice-for-admins.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/notice-for-admins.md) as well. - Third-party client/bot developers may want to check [api-change.md](https://firefish.dev/firefish/firefish/-/blob/main/docs/api-change.md) as well. +## [v20240729](https://firefish.dev/firefish/firefish/-/merge_requests/11214/commits) + +- Fix bugs (including a medium severity security issue) + - We are very thankful to Laura Hausmann for kindly sharing the information about the security issue. + ## [v20240728](https://firefish.dev/firefish/firefish/-/merge_requests/11211/commits) - Improve `admin/emoji/add` API diff --git a/docs/downgrade.sql b/docs/downgrade.sql index a645eb1b65..24f0f4baa8 100644 --- a/docs/downgrade.sql +++ b/docs/downgrade.sql @@ -1,6 +1,7 @@ BEGIN; DELETE FROM "migrations" WHERE name IN ( + 'SetAccessTokenName1722134626110', 'CreateSystemActors1720618854585', 'AddMastodonSubscriptionType1715181461692', 'SwSubscriptionAccessToken1709395223611', diff --git a/locales/en-US.yml b/locales/en-US.yml index d89ff098ac..e3cf890e39 100644 --- a/locales/en-US.yml +++ b/locales/en-US.yml @@ -1668,6 +1668,10 @@ _2fa: removeKeyConfirm: "Really delete the {name} key?" token: "2FA Token" _permissions: + read: "Read (read timelines, notifications, reactions, mutes, account information, etc.)" + write: "Write (make posts, react to posts, mute users, edit account information, etc.)" + push: "Send push notifications" + follow: "Follow and unfollow accounts" "read:account": "View your account information" "write:account": "Edit your account information" "read:blocks": "View your list of blocked users" diff --git a/locales/th-TH.yml b/locales/th-TH.yml index 93904a1125..ce998721cc 100644 --- a/locales/th-TH.yml +++ b/locales/th-TH.yml @@ -3,7 +3,7 @@ headlineFirefish: "แพลตฟอร์มโซเชียลมีเด 🚀" introFirefish: "ยินดีต้อนรับค่ะ/ครับ! Firefish เป็นแพลตฟอร์มโซเชียลมีเดียแบบโอเพนซอร์สที่มีการกระจายอำนาจซึ่งให้บริการฟรีตลอดไป! 🚀" -monthAndDay: "{เดือน}/{วัน}" +monthAndDay: "{month}/{day}" search: "ค้นหา" notifications: "การเเจ้งเตือน" username: "ชื่อผู้ใช้" @@ -433,7 +433,7 @@ text: "ข้อความ" enable: "เปิดใช้งาน" next: "ถัด​ไป" retype: "พิมพ์รหัสอีกครั้ง" -noteOf: "โพสต์โดย {ผู้ใช้งาน}" +noteOf: "โพสต์โดย {user}" inviteToGroup: "ชวนเข้ากลุ่ม" quoteAttached: "อ้างอิง" quoteQuestion: "นายต้องการที่จะอ้างอิงหรอ?" diff --git a/package.json b/package.json index d98bbb1326..e6cffd117b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firefish", - "version": "20240728", + "version": "20240729", "repository": { "type": "git", "url": "https://firefish.dev/firefish/firefish.git" @@ -47,7 +47,7 @@ "@biomejs/cli-darwin-x64": "1.8.3", "@biomejs/cli-linux-arm64": "1.8.3", "@biomejs/cli-linux-x64": "1.8.3", - "@types/node": "20.14.12", + "@types/node": "20.14.13", "execa": "9.3.0", "pnpm": "9.6.0" } diff --git a/packages/backend-rs/Cargo.toml b/packages/backend-rs/Cargo.toml index f6176ec0a4..54efddecbe 100644 --- a/packages/backend-rs/Cargo.toml +++ b/packages/backend-rs/Cargo.toml @@ -27,6 +27,7 @@ bcrypt = { workspace = true, features = ["std"] } chrono = { workspace = true } cuid2 = { workspace = true } emojis = { workspace = true } +futures-util = { workspace = true, features = ["io"] } idna = { workspace = true, features = ["std", "compiled_data"] } image = { workspace = true, features = ["avif", "bmp", "gif", "ico", "jpeg", "png", "tiff", "webp"] } isahc = { workspace = true, features = ["http2", "text-decoding", "json"] } diff --git a/packages/backend-rs/src/federation/nodeinfo/fetch.rs b/packages/backend-rs/src/federation/nodeinfo/fetch.rs index e7bdb0b071..307d86d273 100644 --- a/packages/backend-rs/src/federation/nodeinfo/fetch.rs +++ b/packages/backend-rs/src/federation/nodeinfo/fetch.rs @@ -3,6 +3,7 @@ //! ref: use crate::{federation::nodeinfo::schema::*, util::http_client}; +use futures_util::io::AsyncReadExt; use isahc::AsyncReadResponseExt; use serde::Deserialize; @@ -41,7 +42,7 @@ pub struct NodeinfoLink { async fn fetch_nodeinfo_links(host: &str) -> Result { let client = http_client::client()?; let wellknown_url = format!("https://{}/.well-known/nodeinfo", host); - let mut wellknown_response = client.get_async(&wellknown_url).await?; + let wellknown_response = client.get_async(&wellknown_url).await?; if !wellknown_response.status().is_success() { tracing::debug!("{:#?}", wellknown_response.body()); @@ -52,7 +53,12 @@ async fn fetch_nodeinfo_links(host: &str) -> Result { ))); } - Ok(serde_json::from_str(&wellknown_response.text().await?)?) + // Read up to 1 MiB of the response body + let text = wellknown_response + .map(|body| body.take(1024 * 1024)) + .text() + .await?; + Ok(serde_json::from_str(&text)?) } /// Check if any of the following relations is present in the given [NodeinfoLinks]. diff --git a/packages/backend-rs/src/misc/get_image_size.rs b/packages/backend-rs/src/misc/get_image_size.rs index 939f17f755..d10151483a 100644 --- a/packages/backend-rs/src/misc/get_image_size.rs +++ b/packages/backend-rs/src/misc/get_image_size.rs @@ -1,6 +1,7 @@ use crate::{database::cache, util::http_client}; +use futures_util::AsyncReadExt; use image::{ImageError, ImageFormat, ImageReader}; -use isahc::AsyncReadResponseExt; +use isahc::prelude::*; use nom_exif::{parse_jpeg_exif, EntryValue, ExifTag}; use std::io::Cursor; use tokio::sync::Mutex; @@ -73,11 +74,10 @@ pub async fn get_image_size_from_url(url: &str) -> Result { tracing::info!("retrieving image from {}", url); - let mut response = http_client::client()?.get_async(url).await?; + let response = http_client::client()?.get_async(url).await?; if !response.status().is_success() { tracing::info!("status: {}", response.status()); - tracing::debug!("response body: {:#?}", response.body()); return Err(Error::BadStatus(format!( "{} returned {}", url, @@ -85,7 +85,11 @@ pub async fn get_image_size_from_url(url: &str) -> Result { ))); } - let image_bytes = response.bytes().await?; + // Read up to 8 MiB of the response body + let image_bytes = response + .map(|body| body.take(8 * 1024 * 1024)) + .bytes() + .await?; let reader = ImageReader::new(Cursor::new(&image_bytes)).with_guessed_format()?; diff --git a/packages/backend-rs/src/misc/latest_version.rs b/packages/backend-rs/src/misc/latest_version.rs index f49ac81099..a7e5568427 100644 --- a/packages/backend-rs/src/misc/latest_version.rs +++ b/packages/backend-rs/src/misc/latest_version.rs @@ -1,6 +1,7 @@ //! Fetch latest Firefish version from the Firefish repository use crate::{database::cache, util::http_client}; +use futures_util::AsyncReadExt; use isahc::AsyncReadResponseExt; use serde::Deserialize; @@ -30,13 +31,14 @@ async fn get_latest_version() -> Result { version: String, } + // Read up to 1 MiB of the response body let mut response = http_client::client()? .get_async(UPSTREAM_PACKAGE_JSON_URL) - .await?; + .await? + .map(|body| body.take(1024 * 1024)); if !response.status().is_success() { tracing::info!("status: {}", response.status()); - tracing::debug!("response body: {:#?}", response.body()); return Err(Error::BadStatus(response.status().to_string())); } diff --git a/packages/backend-rs/src/misc/translate.rs b/packages/backend-rs/src/misc/translate.rs index 7e9d5a005f..d783b86952 100644 --- a/packages/backend-rs/src/misc/translate.rs +++ b/packages/backend-rs/src/misc/translate.rs @@ -96,6 +96,7 @@ pub async fn translate( mod deepl_translate { use crate::util::http_client; + use futures_util::AsyncReadExt; use isahc::{AsyncReadResponseExt, Request}; use serde::Deserialize; use serde_json::json; @@ -156,7 +157,13 @@ mod deepl_translate { .header("Content-Type", "application/json") .body(serde_json::to_string(&body)?)?; - let response = client.send_async(request).await?.json::().await?; + // Read up to 1 MiB of the response body + let response = client + .send_async(request) + .await? + .map(|body| body.take(1024 * 1024)) + .json::() + .await?; let result = response .translations @@ -191,6 +198,7 @@ mod deepl_translate { mod libre_translate { use crate::util::http_client; + use futures_util::AsyncReadExt; use isahc::{AsyncReadResponseExt, Request}; use serde::Deserialize; use serde_json::json; @@ -248,9 +256,11 @@ mod libre_translate { .header("Content-Type", "application/json") .body(serde_json::to_string(&body)?)?; + // Read up to 1 MiB of the response body let result = client .send_async(request) .await? + .map(|body| body.take(1024 * 1024)) .json::() .await?; diff --git a/packages/backend/package.json b/packages/backend/package.json index 4cddcb6c14..d0f89a4f2b 100644 --- a/packages/backend/package.json +++ b/packages/backend/package.json @@ -57,7 +57,7 @@ "gunzip-maybe": "1.4.2", "hpagent": "1.2.0", "ioredis": "5.4.1", - "ip-cidr": "4.0.1", + "ip-cidr": "4.0.2", "is-svg": "5.0.1", "jsdom": "24.1.1", "json5": "2.2.3", @@ -135,7 +135,7 @@ "@types/koa__cors": "5.0.0", "@types/koa__multer": "2.0.7", "@types/koa__router": "12.0.4", - "@types/node": "20.14.12", + "@types/node": "20.14.13", "@types/node-fetch": "2.6.11", "@types/nodemailer": "6.4.15", "@types/oauth": "0.9.5", diff --git a/packages/backend/src/migration/1722134626110-set-access-token-name.ts b/packages/backend/src/migration/1722134626110-set-access-token-name.ts new file mode 100644 index 0000000000..4b9824b11c --- /dev/null +++ b/packages/backend/src/migration/1722134626110-set-access-token-name.ts @@ -0,0 +1,16 @@ +import type { MigrationInterface, QueryRunner } from "typeorm"; + +export class SetAccessTokenName1722134626110 implements MigrationInterface { + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `UPDATE "access_token" SET "name" = "app"."name" FROM "app" WHERE "access_token"."name" IS NULL AND "access_token"."appId" = "app"."id"`, + ); + await queryRunner.query( + `UPDATE "access_token" SET "description" = "app"."description" FROM "app" WHERE "access_token"."description" IS NULL AND "access_token"."appId" = "app"."id"`, + ); + } + + public async down(_: QueryRunner): Promise { + /* You don't need to revert this migration. */ + } +} diff --git a/packages/backend/src/misc/fetch.ts b/packages/backend/src/misc/fetch.ts index 5af3b08fa5..da3b5750ee 100644 --- a/packages/backend/src/misc/fetch.ts +++ b/packages/backend/src/misc/fetch.ts @@ -57,7 +57,6 @@ export async function getResponse(args: { body?: string; headers: Record; timeout?: number; - size?: number; redirect?: RequestRedirect; }) { if (!isSafeUrl(args.url)) { @@ -76,7 +75,7 @@ export async function getResponse(args: { headers: args.headers, body: args.body, timeout, - size: args.size || 10 * 1024 * 1024, + size: 10 * 1024 * 1024, agent: getAgentByUrl, signal: controller.signal, redirect: args.redirect, diff --git a/packages/backend/src/remote/activitypub/misc/ld-signature.ts b/packages/backend/src/remote/activitypub/misc/ld-signature.ts index 2d1e7ef6b2..b654e89767 100644 --- a/packages/backend/src/remote/activitypub/misc/ld-signature.ts +++ b/packages/backend/src/remote/activitypub/misc/ld-signature.ts @@ -126,6 +126,7 @@ export class LdSignature { headers: { Accept: "application/ld+json, application/json", }, + size: 1024 * 1024, // 1MiB // TODO //timeout: this.loderTimeout, agent: (u) => (u.protocol === "http:" ? httpAgent : httpsAgent), diff --git a/packages/backend/src/remote/activitypub/models/person.ts b/packages/backend/src/remote/activitypub/models/person.ts index 8a94af4bed..e9c1b5bd1b 100644 --- a/packages/backend/src/remote/activitypub/models/person.ts +++ b/packages/backend/src/remote/activitypub/models/person.ts @@ -17,7 +17,6 @@ import { User } from "@/models/entities/user.js"; import type { Emoji } from "@/models/entities/emoji.js"; import { UserNotePining } from "@/models/entities/user-note-pining.js"; import { - genId, genIdAt, InternalEvent, isSameOrigin, @@ -52,6 +51,7 @@ import { extractApHashtags } from "./tag.js"; import { resolveNote, extractEmojis } from "./note.js"; import { resolveImage } from "./image.js"; import { inspect } from "node:util"; +import fetch from "node-fetch"; const nameLength = 128; const summaryLength = 2048; @@ -207,6 +207,7 @@ export async function createPerson( try { const data = await fetch(person.followers, { headers: { Accept: "application/json" }, + size: 1024 * 1024 }); const json_data = JSON.parse(await data.text()); @@ -222,6 +223,7 @@ export async function createPerson( try { const data = await fetch(person.following, { headers: { Accept: "application/json" }, + size: 1024 * 1024 }); const json_data = JSON.parse(await data.text()); @@ -488,10 +490,11 @@ export async function updatePerson( if (typeof person.followers === "string") { try { - let data = await fetch(person.followers, { + const data = await fetch(person.followers, { headers: { Accept: "application/json" }, + size: 1024 * 1024 }); - let json_data = JSON.parse(await data.text()); + const json_data = JSON.parse(await data.text()); followersCount = json_data.totalItems; } catch { @@ -503,10 +506,11 @@ export async function updatePerson( if (typeof person.following === "string") { try { - let data = await fetch(person.following, { + const data = await fetch(person.following, { headers: { Accept: "application/json" }, + size: 1024 * 1024 }); - let json_data = JSON.parse(await data.text()); + const json_data = JSON.parse(await data.text()); followingCount = json_data.totalItems; } catch { @@ -518,10 +522,10 @@ export async function updatePerson( if (typeof person.outbox === "string") { try { - let data = await fetch(person.outbox, { + const data = await fetch(person.outbox, { headers: { Accept: "application/json" }, }); - let json_data = JSON.parse(await data.text()); + const json_data = JSON.parse(await data.text()); notesCount = json_data.totalItems; } catch (e) { @@ -725,9 +729,10 @@ export async function updateFeatured(userId: User["id"], resolver?: Resolver) { let td = 0; for (const note of featuredNotes.filter((note) => note != null)) { td -= 1000; + const createdAt = new Date(Date.now() + td); transactionalEntityManager.insert(UserNotePining, { - id: genId(new Date(Date.now() + td)), - createdAt: new Date(), + id: genIdAt(createdAt), + createdAt, userId: user.id, noteId: note!.id, }); diff --git a/packages/backend/src/server/api/mastodon/helpers/auth.ts b/packages/backend/src/server/api/mastodon/helpers/auth.ts index 847aef08a3..f0856e7971 100644 --- a/packages/backend/src/server/api/mastodon/helpers/auth.ts +++ b/packages/backend/src/server/api/mastodon/helpers/auth.ts @@ -1,8 +1,11 @@ import type OAuth from "@/server/api/mastodon/entities/oauth/oauth.js"; -import { generateSecureRandomString } from "backend-rs"; +import { + fetchMeta, + getTimestamp, + generateSecureRandomString, + genIdAt, +} from "backend-rs"; import { Apps, AccessTokens } from "@/models/index.js"; -import { genId } from "backend-rs"; -import { fetchMeta, getTimestamp } from "backend-rs"; import type { MastoContext } from "@/server/api/mastodon/index.js"; import { MastoApiError } from "@/server/api/mastodon/middleware/catch-errors.js"; import { difference, toSingleLast, unique } from "@/prelude/array.js"; @@ -44,12 +47,13 @@ export class AuthHelpers { permission: scopes, }); } catch { - const id = genId(); + const createdAt = new Date(); + const id = genIdAt(createdAt); app = await Apps.insert({ id, secret: generateSecureRandomString(32), - createdAt: new Date(), + createdAt, name: client_name, description: website, permission: scopes, @@ -100,14 +104,18 @@ export class AuthHelpers { if (!callbackUrls.some((url) => url.startsWith(body.redirect_uri))) throw new MastoApiError(400, "Redirect URI not in list"); const secret = generateSecureRandomString(32); + const createdAt = new Date(); + const id = genIdAt(createdAt); const token = await AccessTokens.insert({ - id: genId(), + name: app.name, + description: app.description, + id, token: secret, hash: secret, appId: app.id, userId: user.id, permission: scopes, - createdAt: new Date(), + createdAt, fetched: false, }).then((x) => AccessTokens.findOneByOrFail(x.identifiers[0])); @@ -175,16 +183,19 @@ export class AuthHelpers { if (!app || body.client_secret !== app.secret) throw invalidClientError; if (difference(scopes, app.permission).length > 0) throw invalidScopeError; - + const createdAt = new Date(); + const id = genIdAt(createdAt); const secret = generateSecureRandomString(32); const token = await AccessTokens.insert({ - id: genId(), + name: app.name, + description: app.description, + id, token: secret, hash: secret, appId: app.id, userId: null, permission: scopes, - createdAt: new Date(), + createdAt, fetched: false, }).then((x) => AccessTokens.findOneByOrFail(x.identifiers[0])); diff --git a/packages/backend/src/services/fetch-instance-metadata.ts b/packages/backend/src/services/fetch-instance-metadata.ts index 58d7ae338e..494027a37c 100644 --- a/packages/backend/src/services/fetch-instance-metadata.ts +++ b/packages/backend/src/services/fetch-instance-metadata.ts @@ -156,6 +156,7 @@ async function fetchFaviconUrl( // TODO //timeout: 10000, agent: getAgentByUrl, + size: 1024 * 1024 }); if (favicon.ok) { diff --git a/packages/firefish-js/package.json b/packages/firefish-js/package.json index 4d0a225eae..21a5f3716d 100644 --- a/packages/firefish-js/package.json +++ b/packages/firefish-js/package.json @@ -21,7 +21,7 @@ }, "devDependencies": { "@types/jest": "29.5.12", - "@types/node": "20.14.12", + "@types/node": "20.14.13", "jest": "29.7.0", "jest-fetch-mock": "3.0.3", "jest-websocket-mock": "2.5.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7bc0de5c3d..e6eabaca8f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -28,8 +28,8 @@ importers: specifier: 1.8.3 version: 1.8.3 '@types/node': - specifier: 20.14.12 - version: 20.14.12 + specifier: 20.14.13 + version: 20.14.13 execa: specifier: 9.3.0 version: 9.3.0 @@ -160,8 +160,8 @@ importers: specifier: 5.4.1 version: 5.4.1 ip-cidr: - specifier: 4.0.1 - version: 4.0.1 + specifier: 4.0.2 + version: 4.0.2 is-svg: specifier: 5.0.1 version: 5.0.1 @@ -311,7 +311,7 @@ importers: version: 0.2.3 typeorm: specifier: 0.3.20 - version: 0.3.20(ioredis@5.4.1)(pg@8.12.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + version: 0.3.20(ioredis@5.4.1)(pg@8.12.0)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) ulid: specifier: 2.3.0 version: 2.3.0 @@ -389,8 +389,8 @@ importers: specifier: 12.0.4 version: 12.0.4 '@types/node': - specifier: 20.14.12 - version: 20.14.12 + specifier: 20.14.13 + version: 20.14.13 '@types/node-fetch': specifier: 2.6.11 version: 2.6.11 @@ -471,7 +471,7 @@ importers: version: 9.5.1(typescript@5.5.4)(webpack@5.93.0) ts-node: specifier: 10.9.2 - version: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + version: 10.9.2(@types/node@20.14.13)(typescript@5.5.4) tsc-alias: specifier: 1.8.10 version: 1.8.10 @@ -558,7 +558,7 @@ importers: version: 10.0.0 '@vitejs/plugin-vue': specifier: 5.1.1 - version: 5.1.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4)) + version: 5.1.1(vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4)) '@vue/runtime-core': specifier: 3.4.34 version: 3.4.34 @@ -708,10 +708,10 @@ importers: version: 10.0.0 vite: specifier: 5.3.5 - version: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3) + version: 5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3) vite-plugin-compression: specifier: 0.5.1 - version: 0.5.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)) + version: 0.5.1(vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3)) vue: specifier: 3.4.34 version: 3.4.34(typescript@5.5.4) @@ -741,11 +741,11 @@ importers: specifier: 29.5.12 version: 29.5.12 '@types/node': - specifier: 20.14.12 - version: 20.14.12 + specifier: 20.14.13 + version: 20.14.13 jest: specifier: 29.7.0 - version: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + version: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) jest-fetch-mock: specifier: 3.0.3 version: 3.0.3 @@ -757,10 +757,10 @@ importers: version: 9.3.1 ts-jest: specifier: 29.2.3 - version: 29.2.3(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)))(typescript@5.5.4) + version: 29.2.3(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(jest@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)))(typescript@5.5.4) ts-node: specifier: 10.9.2 - version: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + version: 10.9.2(@types/node@20.14.13)(typescript@5.5.4) tsc-alias: specifier: 1.8.10 version: 1.8.10 @@ -781,10 +781,10 @@ importers: version: 6.2.1 vite: specifier: 5.3.5 - version: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3) + version: 5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3) vite-plugin-compression: specifier: 0.5.1 - version: 0.5.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)) + version: 0.5.1(vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3)) packages: @@ -2497,8 +2497,8 @@ packages: '@types/node-fetch@2.6.11': resolution: {integrity: sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==} - '@types/node@20.14.12': - resolution: {integrity: sha512-r7wNXakLeSsGT0H1AU863vS2wa5wBOK4bWMjZz2wj+8nBx+m5PeIn0k8AloSLpRuiwdRQZwarZqHE4FNArPuJQ==} + '@types/node@20.14.13': + resolution: {integrity: sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==} '@types/nodemailer@6.4.15': resolution: {integrity: sha512-0EBJxawVNjPkng1zm2vopRctuWVCxk34JcIlRuXSf54habUWdz1FB7wHDqOqvDa8Mtpt0Q3LTXQkAs2LNyK5jQ==} @@ -4349,8 +4349,8 @@ packages: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} - ip-cidr@4.0.1: - resolution: {integrity: sha512-V5Nce94SVJ7NtyT/UKUeTM7sY3V7TEk48hURhtBgTiGduOa5t6p9Hd+zBOGvr4Gu7iWPxFVYNl017p0akQA84w==} + ip-cidr@4.0.2: + resolution: {integrity: sha512-KifhLKBjdS/hB3TD4UUOalVp1BpzPFvRpgJvXcP0Ya98tuSQTUQ71iI7EW7CKddkBJTYB3GfTWl5eJwpLOXj2A==} engines: {node: '>=16.14.0'} ip-regex@4.3.0: @@ -7504,7 +7504,7 @@ snapshots: '@inquirer/figures': 1.0.5 '@inquirer/type': 1.5.1 '@types/mute-stream': 0.0.4 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 cli-spinners: 2.9.2 @@ -7607,27 +7607,27 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 slash: 3.0.0 - '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4))': + '@jest/core@29.7.0(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4))': dependencies: '@jest/console': 29.7.0 '@jest/reporters': 29.7.0 '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -7652,7 +7652,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -7670,7 +7670,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.12 + '@types/node': 20.14.13 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -7692,7 +7692,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.25 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -7762,7 +7762,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -8374,11 +8374,11 @@ snapshots: '@types/accepts@1.3.7': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/adm-zip@0.5.5': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/async-lock@1.4.2': {} @@ -8408,18 +8408,18 @@ snapshots: '@types/body-parser@1.19.5': dependencies: '@types/connect': 3.4.38 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/cacheable-request@6.0.3': dependencies: '@types/http-cache-semantics': 4.0.4 '@types/keyv': 3.1.4 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/responselike': 1.0.3 '@types/co-body@6.1.3': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/qs': 6.9.15 '@types/color-convert@2.0.3': @@ -8430,7 +8430,7 @@ snapshots: '@types/connect@3.4.38': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/content-disposition@0.5.8': {} @@ -8439,7 +8439,7 @@ snapshots: '@types/connect': 3.4.38 '@types/express': 4.17.21 '@types/keygrip': 1.0.6 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/disposable-email-domains@1.0.6': {} @@ -8464,7 +8464,7 @@ snapshots: '@types/express-serve-static-core@4.19.5': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/qs': 6.9.15 '@types/range-parser': 1.2.7 '@types/send': 0.17.4 @@ -8478,20 +8478,20 @@ snapshots: '@types/fluent-ffmpeg@2.1.24': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/formidable@2.0.6': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/glob@8.1.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/http-assert@1.5.5': {} @@ -8518,7 +8518,7 @@ snapshots: '@types/jsdom@21.1.7': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/tough-cookie': 4.0.5 parse5: 7.1.2 @@ -8534,7 +8534,7 @@ snapshots: '@types/keyv@3.1.4': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/koa-bodyparser@4.3.12': dependencies: @@ -8573,7 +8573,7 @@ snapshots: '@types/http-errors': 2.0.4 '@types/keygrip': 1.0.6 '@types/koa-compose': 3.2.8 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/koa__cors@5.0.0': dependencies: @@ -8597,36 +8597,36 @@ snapshots: '@types/mute-stream@0.0.4': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/needle@3.3.0': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/node-fetch@2.6.11': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 form-data: 4.0.0 - '@types/node@20.14.12': + '@types/node@20.14.13': dependencies: undici-types: 5.26.5 '@types/nodemailer@6.4.15': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/normalize-package-data@2.4.4': {} '@types/oauth@0.9.5': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/opencc-js@1.0.3': {} '@types/pg@8.11.6': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 pg-protocol: 1.6.1 pg-types: 4.0.2 @@ -8635,7 +8635,7 @@ snapshots: '@types/probe-image-size@7.2.5': dependencies: '@types/needle': 3.3.0 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/pug@2.0.10': {} @@ -8643,7 +8643,7 @@ snapshots: '@types/qrcode@1.5.5': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/qs@6.9.15': {} @@ -8657,7 +8657,7 @@ snapshots: '@types/responselike@1.0.3': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/sanitize-html@2.11.0': dependencies: @@ -8670,12 +8670,12 @@ snapshots: '@types/send@0.17.4': dependencies: '@types/mime': 1.3.5 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/serve-static@1.15.7': dependencies: '@types/http-errors': 2.0.4 - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/send': 0.17.4 '@types/sinonjs__fake-timers@8.1.5': {} @@ -8700,13 +8700,13 @@ snapshots: '@types/websocket@1.0.10': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/wrap-ansi@3.0.0': {} '@types/ws@8.5.11': dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 '@types/yargs-parser@21.0.3': {} @@ -8714,9 +8714,9 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@vitejs/plugin-vue@5.1.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))': + '@vitejs/plugin-vue@5.1.1(vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3))(vue@3.4.34(typescript@5.5.4))': dependencies: - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3) + vite: 5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3) vue: 3.4.34(typescript@5.5.4) '@volar/language-core@2.4.0-alpha.18': @@ -9571,13 +9571,13 @@ snapshots: crc-32: 1.2.2 readable-stream: 4.5.2 - create-jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + create-jest@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -10507,7 +10507,7 @@ snapshots: jsbn: 1.1.0 sprintf-js: 1.1.3 - ip-cidr@4.0.1: + ip-cidr@4.0.2: dependencies: ip-address: 9.0.5 @@ -10684,7 +10684,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.3 @@ -10704,16 +10704,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest-cli@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + create-jest: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) exit: 0.1.2 import-local: 3.2.0 - jest-config: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-config: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -10723,7 +10723,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest-config@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): dependencies: '@babel/core': 7.24.9 '@jest/test-sequencer': 29.7.0 @@ -10748,8 +10748,8 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.12 - ts-node: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + '@types/node': 20.14.13 + ts-node: 10.9.2(@types/node@20.14.13)(typescript@5.5.4) transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -10778,7 +10778,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -10795,7 +10795,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.12 + '@types/node': 20.14.13 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -10834,7 +10834,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -10869,7 +10869,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -10897,7 +10897,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 cjs-module-lexer: 1.3.1 collect-v8-coverage: 1.0.2 @@ -10943,7 +10943,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -10962,7 +10962,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.12 + '@types/node': 20.14.13 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -10976,23 +10976,23 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 merge-stream: 2.0.0 supports-color: 8.1.1 jest-worker@29.7.0: dependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + jest@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + '@jest/core': 29.7.0(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) '@jest/types': 29.6.3 import-local: 3.2.0 - jest-cli: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest-cli: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -12739,12 +12739,12 @@ snapshots: trim-newlines@3.0.1: {} - ts-jest@29.2.3(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(jest@29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)))(typescript@5.5.4): + ts-jest@29.2.3(@babel/core@7.24.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.24.9))(jest@29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.12)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)) + jest: 29.7.0(@types/node@20.14.13)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -12768,14 +12768,14 @@ snapshots: typescript: 5.5.4 webpack: 5.93.0 - ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4): + ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4): dependencies: '@cspotcode/source-map-support': 0.8.1 '@tsconfig/node10': 1.0.11 '@tsconfig/node12': 1.0.11 '@tsconfig/node14': 1.0.3 '@tsconfig/node16': 1.0.4 - '@types/node': 20.14.12 + '@types/node': 20.14.13 acorn: 8.12.1 acorn-walk: 8.3.3 arg: 4.1.3 @@ -12844,7 +12844,7 @@ snapshots: typedarray@0.0.6: {} - typeorm@0.3.20(ioredis@5.4.1)(pg@8.12.0)(ts-node@10.9.2(@types/node@20.14.12)(typescript@5.5.4)): + typeorm@0.3.20(ioredis@5.4.1)(pg@8.12.0)(ts-node@10.9.2(@types/node@20.14.13)(typescript@5.5.4)): dependencies: '@sqltools/formatter': 1.2.5 app-root-path: 3.1.0 @@ -12864,7 +12864,7 @@ snapshots: optionalDependencies: ioredis: 5.4.1 pg: 8.12.0 - ts-node: 10.9.2(@types/node@20.14.12)(typescript@5.5.4) + ts-node: 10.9.2(@types/node@20.14.13)(typescript@5.5.4) transitivePeerDependencies: - supports-color @@ -12975,22 +12975,22 @@ snapshots: core-util-is: 1.0.2 extsprintf: 1.3.0 - vite-plugin-compression@0.5.1(vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3)): + vite-plugin-compression@0.5.1(vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3)): dependencies: chalk: 4.1.2 debug: 4.3.6 fs-extra: 10.1.0 - vite: 5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3) + vite: 5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3) transitivePeerDependencies: - supports-color - vite@5.3.5(@types/node@20.14.12)(sass@1.77.8)(terser@5.31.3): + vite@5.3.5(@types/node@20.14.13)(sass@1.77.8)(terser@5.31.3): dependencies: esbuild: 0.21.5 postcss: 8.4.40 rollup: 4.19.1 optionalDependencies: - '@types/node': 20.14.12 + '@types/node': 20.14.13 fsevents: 2.3.3 sass: 1.77.8 terser: 5.31.3