mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-22 20:31:19 +00:00
Merge remote-tracking branch 'origin/main' into upgrade_webmention
This commit is contained in:
commit
8e853f3a15
68 changed files with 1476 additions and 1377 deletions
|
@ -157,7 +157,7 @@ steps:
|
||||||
CARGO_HOME: .cargo_home
|
CARGO_HOME: .cargo_home
|
||||||
commands:
|
commands:
|
||||||
- rustup component add clippy
|
- rustup component add clippy
|
||||||
- cargo clippy --workspace --tests --all-targets --features console -- -D warnings
|
- cargo clippy --workspace --tests --all-targets -- -D warnings
|
||||||
when: *slow_check_paths
|
when: *slow_check_paths
|
||||||
|
|
||||||
cargo_build:
|
cargo_build:
|
||||||
|
@ -240,10 +240,13 @@ steps:
|
||||||
|
|
||||||
publish_release_docker:
|
publish_release_docker:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
secrets: [docker_username, docker_password]
|
|
||||||
settings:
|
settings:
|
||||||
repo: dessalines/lemmy
|
repo: dessalines/lemmy
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
platforms: linux/amd64, linux/arm64
|
platforms: linux/amd64, linux/arm64
|
||||||
build_args:
|
build_args:
|
||||||
- RUST_RELEASE_MODE=release
|
- RUST_RELEASE_MODE=release
|
||||||
|
@ -253,10 +256,13 @@ steps:
|
||||||
|
|
||||||
nightly_build:
|
nightly_build:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
secrets: [docker_username, docker_password]
|
|
||||||
settings:
|
settings:
|
||||||
repo: dessalines/lemmy
|
repo: dessalines/lemmy
|
||||||
dockerfile: docker/Dockerfile
|
dockerfile: docker/Dockerfile
|
||||||
|
username:
|
||||||
|
from_secret: docker_username
|
||||||
|
password:
|
||||||
|
from_secret: docker_password
|
||||||
platforms: linux/amd64,linux/arm64
|
platforms: linux/amd64,linux/arm64
|
||||||
build_args:
|
build_args:
|
||||||
- RUST_RELEASE_MODE=release
|
- RUST_RELEASE_MODE=release
|
||||||
|
|
1372
Cargo.lock
generated
1372
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
59
Cargo.toml
59
Cargo.toml
|
@ -1,5 +1,5 @@
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
version = "0.19.6-beta.4"
|
version = "0.19.6-beta.7"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
description = "A link aggregator for the fediverse"
|
description = "A link aggregator for the fediverse"
|
||||||
license = "AGPL-3.0"
|
license = "AGPL-3.0"
|
||||||
|
@ -37,15 +37,6 @@ debug = 0
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
embed-pictrs = ["pict-rs"]
|
embed-pictrs = ["pict-rs"]
|
||||||
# This feature requires building with `tokio_unstable` flag, see documentation:
|
|
||||||
# https://docs.rs/tokio/latest/tokio/#unstable-features
|
|
||||||
console = [
|
|
||||||
"console-subscriber",
|
|
||||||
"opentelemetry",
|
|
||||||
"opentelemetry-otlp",
|
|
||||||
"tracing-opentelemetry",
|
|
||||||
"reqwest-tracing/opentelemetry_0_16",
|
|
||||||
]
|
|
||||||
json-log = ["tracing-subscriber/json"]
|
json-log = ["tracing-subscriber/json"]
|
||||||
default = []
|
default = []
|
||||||
|
|
||||||
|
@ -89,18 +80,18 @@ unwrap_used = "deny"
|
||||||
unimplemented = "deny"
|
unimplemented = "deny"
|
||||||
|
|
||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
lemmy_api = { version = "=0.19.6-beta.4", path = "./crates/api" }
|
lemmy_api = { version = "=0.19.6-beta.7", path = "./crates/api" }
|
||||||
lemmy_api_crud = { version = "=0.19.6-beta.4", path = "./crates/api_crud" }
|
lemmy_api_crud = { version = "=0.19.6-beta.7", path = "./crates/api_crud" }
|
||||||
lemmy_apub = { version = "=0.19.6-beta.4", path = "./crates/apub" }
|
lemmy_apub = { version = "=0.19.6-beta.7", path = "./crates/apub" }
|
||||||
lemmy_utils = { version = "=0.19.6-beta.4", path = "./crates/utils", default-features = false }
|
lemmy_utils = { version = "=0.19.6-beta.7", path = "./crates/utils", default-features = false }
|
||||||
lemmy_db_schema = { version = "=0.19.6-beta.4", path = "./crates/db_schema" }
|
lemmy_db_schema = { version = "=0.19.6-beta.7", path = "./crates/db_schema" }
|
||||||
lemmy_api_common = { version = "=0.19.6-beta.4", path = "./crates/api_common" }
|
lemmy_api_common = { version = "=0.19.6-beta.7", path = "./crates/api_common" }
|
||||||
lemmy_routes = { version = "=0.19.6-beta.4", path = "./crates/routes" }
|
lemmy_routes = { version = "=0.19.6-beta.7", path = "./crates/routes" }
|
||||||
lemmy_db_views = { version = "=0.19.6-beta.4", path = "./crates/db_views" }
|
lemmy_db_views = { version = "=0.19.6-beta.7", path = "./crates/db_views" }
|
||||||
lemmy_db_views_actor = { version = "=0.19.6-beta.4", path = "./crates/db_views_actor" }
|
lemmy_db_views_actor = { version = "=0.19.6-beta.7", path = "./crates/db_views_actor" }
|
||||||
lemmy_db_views_moderator = { version = "=0.19.6-beta.4", path = "./crates/db_views_moderator" }
|
lemmy_db_views_moderator = { version = "=0.19.6-beta.7", path = "./crates/db_views_moderator" }
|
||||||
lemmy_federate = { version = "=0.19.6-beta.4", path = "./crates/federate" }
|
lemmy_federate = { version = "=0.19.6-beta.7", path = "./crates/federate" }
|
||||||
activitypub_federation = { version = "0.5.8", default-features = false, features = [
|
activitypub_federation = { version = "0.6.0-alpha1", default-features = false, features = [
|
||||||
"actix-web",
|
"actix-web",
|
||||||
] }
|
] }
|
||||||
diesel = "2.1.6"
|
diesel = "2.1.6"
|
||||||
|
@ -108,7 +99,7 @@ diesel_migrations = "2.1.0"
|
||||||
diesel-async = "0.4.1"
|
diesel-async = "0.4.1"
|
||||||
serde = { version = "1.0.204", features = ["derive"] }
|
serde = { version = "1.0.204", features = ["derive"] }
|
||||||
serde_with = "3.9.0"
|
serde_with = "3.9.0"
|
||||||
actix-web = { version = "4.8.0", default-features = false, features = [
|
actix-web = { version = "4.9.0", default-features = false, features = [
|
||||||
"macros",
|
"macros",
|
||||||
"rustls-0_23",
|
"rustls-0_23",
|
||||||
"compress-brotli",
|
"compress-brotli",
|
||||||
|
@ -117,19 +108,17 @@ actix-web = { version = "4.8.0", default-features = false, features = [
|
||||||
"cookies",
|
"cookies",
|
||||||
] }
|
] }
|
||||||
tracing = "0.1.40"
|
tracing = "0.1.40"
|
||||||
tracing-actix-web = { version = "0.7.11", default-features = false }
|
tracing-actix-web = { version = "0.7.10", default-features = false }
|
||||||
tracing-error = "0.2.0"
|
|
||||||
tracing-log = "0.2.0"
|
|
||||||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
|
||||||
url = { version = "2.5.2", features = ["serde"] }
|
url = { version = "2.5.2", features = ["serde"] }
|
||||||
reqwest = { version = "0.11.27", default-features = false, features = [
|
reqwest = { version = "0.12.7", default-features = false, features = [
|
||||||
"json",
|
"json",
|
||||||
"blocking",
|
"blocking",
|
||||||
"gzip",
|
"gzip",
|
||||||
"rustls-tls",
|
"rustls-tls",
|
||||||
] }
|
] }
|
||||||
reqwest-middleware = "0.2.5"
|
reqwest-middleware = "0.3.3"
|
||||||
reqwest-tracing = "0.4.8"
|
reqwest-tracing = "0.5.3"
|
||||||
clokwerk = "0.4.0"
|
clokwerk = "0.4.0"
|
||||||
doku = { version = "0.21.1", features = ["url-2"] }
|
doku = { version = "0.21.1", features = ["url-2"] }
|
||||||
bcrypt = "0.15.1"
|
bcrypt = "0.15.1"
|
||||||
|
@ -152,10 +141,8 @@ diesel-derive-enum = { version = "2.1.0", features = ["postgres"] }
|
||||||
strum = { version = "0.26.3", features = ["derive"] }
|
strum = { version = "0.26.3", features = ["derive"] }
|
||||||
itertools = "0.13.0"
|
itertools = "0.13.0"
|
||||||
futures = "0.3.30"
|
futures = "0.3.30"
|
||||||
http = "0.2.12"
|
http = "1.1"
|
||||||
rosetta-i18n = "0.1.3"
|
rosetta-i18n = "0.1.3"
|
||||||
opentelemetry = { version = "0.19.0", features = ["rt-tokio"] }
|
|
||||||
tracing-opentelemetry = { version = "0.19.0" }
|
|
||||||
ts-rs = { version = "7.1.1", features = [
|
ts-rs = { version = "7.1.1", features = [
|
||||||
"serde-compat",
|
"serde-compat",
|
||||||
"chrono-impl",
|
"chrono-impl",
|
||||||
|
@ -171,7 +158,7 @@ moka = { version = "0.12.8", features = ["future"] }
|
||||||
i-love-jesus = { version = "0.1.0" }
|
i-love-jesus = { version = "0.1.0" }
|
||||||
clap = { version = "4.5.13", features = ["derive", "env"] }
|
clap = { version = "4.5.13", features = ["derive", "env"] }
|
||||||
pretty_assertions = "1.4.0"
|
pretty_assertions = "1.4.0"
|
||||||
derive-new = "0.6.0"
|
derive-new = "0.7.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lemmy_api = { workspace = true }
|
lemmy_api = { workspace = true }
|
||||||
|
@ -188,8 +175,6 @@ diesel-async = { workspace = true }
|
||||||
actix-web = { workspace = true }
|
actix-web = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tracing-actix-web = { workspace = true }
|
tracing-actix-web = { workspace = true }
|
||||||
tracing-error = { workspace = true }
|
|
||||||
tracing-log = { workspace = true }
|
|
||||||
tracing-subscriber = { workspace = true }
|
tracing-subscriber = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
reqwest = { workspace = true }
|
reqwest = { workspace = true }
|
||||||
|
@ -197,10 +182,6 @@ reqwest-middleware = { workspace = true }
|
||||||
reqwest-tracing = { workspace = true }
|
reqwest-tracing = { workspace = true }
|
||||||
clokwerk = { workspace = true }
|
clokwerk = { workspace = true }
|
||||||
serde_json = { workspace = true }
|
serde_json = { workspace = true }
|
||||||
tracing-opentelemetry = { workspace = true, optional = true }
|
|
||||||
opentelemetry = { workspace = true, optional = true }
|
|
||||||
console-subscriber = { version = "0.4.0", optional = true }
|
|
||||||
opentelemetry-otlp = { version = "0.12.0", optional = true }
|
|
||||||
pict-rs = { version = "0.5.16", optional = true }
|
pict-rs = { version = "0.5.16", optional = true }
|
||||||
rustls = { workspace = true }
|
rustls = { workspace = true }
|
||||||
tokio.workspace = true
|
tokio.workspace = true
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
"repository": "https://github.com/LemmyNet/lemmy",
|
"repository": "https://github.com/LemmyNet/lemmy",
|
||||||
"author": "Dessalines",
|
"author": "Dessalines",
|
||||||
"license": "AGPL-3.0",
|
"license": "AGPL-3.0",
|
||||||
"packageManager": "pnpm@9.6.0",
|
"packageManager": "pnpm@9.9.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"lint": "tsc --noEmit && eslint --report-unused-disable-directives && prettier --check 'src/**/*.ts'",
|
"lint": "tsc --noEmit && eslint --report-unused-disable-directives && prettier --check 'src/**/*.ts'",
|
||||||
"fix": "prettier --write src && eslint --fix src",
|
"fix": "prettier --write src && eslint --fix src",
|
||||||
|
|
|
@ -13,22 +13,22 @@ importers:
|
||||||
version: 29.5.12
|
version: 29.5.12
|
||||||
'@types/node':
|
'@types/node':
|
||||||
specifier: ^22.0.2
|
specifier: ^22.0.2
|
||||||
version: 22.0.2
|
version: 22.5.1
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)
|
version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
version: 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^9.8.0
|
specifier: ^9.8.0
|
||||||
version: 9.8.0
|
version: 9.9.1
|
||||||
eslint-plugin-prettier:
|
eslint-plugin-prettier:
|
||||||
specifier: ^5.1.3
|
specifier: ^5.1.3
|
||||||
version: 5.2.1(eslint@9.8.0)(prettier@3.3.3)
|
version: 5.2.1(eslint@9.9.1)(prettier@3.3.3)
|
||||||
jest:
|
jest:
|
||||||
specifier: ^29.5.0
|
specifier: ^29.5.0
|
||||||
version: 29.7.0(@types/node@22.0.2)
|
version: 29.7.0(@types/node@22.5.1)
|
||||||
lemmy-js-client:
|
lemmy-js-client:
|
||||||
specifier: 0.19.5-alpha.1
|
specifier: 0.19.5-alpha.1
|
||||||
version: 0.19.5-alpha.1
|
version: 0.19.5-alpha.1
|
||||||
|
@ -37,20 +37,16 @@ importers:
|
||||||
version: 3.3.3
|
version: 3.3.3
|
||||||
ts-jest:
|
ts-jest:
|
||||||
specifier: ^29.1.0
|
specifier: ^29.1.0
|
||||||
version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4)
|
version: 29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.5.1))(typescript@5.5.4)
|
||||||
typescript:
|
typescript:
|
||||||
specifier: ^5.5.4
|
specifier: ^5.5.4
|
||||||
version: 5.5.4
|
version: 5.5.4
|
||||||
typescript-eslint:
|
typescript-eslint:
|
||||||
specifier: ^8.0.0
|
specifier: ^8.0.0
|
||||||
version: 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
version: 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
|
||||||
'@aashutoshrathi/word-wrap@1.2.6':
|
|
||||||
resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==}
|
|
||||||
engines: {node: '>=0.10.0'}
|
|
||||||
|
|
||||||
'@ampproject/remapping@2.2.1':
|
'@ampproject/remapping@2.2.1':
|
||||||
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
|
resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==}
|
||||||
engines: {node: '>=6.0.0'}
|
engines: {node: '>=6.0.0'}
|
||||||
|
@ -232,16 +228,16 @@ packages:
|
||||||
resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
|
resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==}
|
||||||
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
|
||||||
|
|
||||||
'@eslint/config-array@0.17.1':
|
'@eslint/config-array@0.18.0':
|
||||||
resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==}
|
resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@eslint/eslintrc@3.1.0':
|
'@eslint/eslintrc@3.1.0':
|
||||||
resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
|
resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@eslint/js@9.8.0':
|
'@eslint/js@9.9.1':
|
||||||
resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==}
|
resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
'@eslint/object-schema@2.1.4':
|
'@eslint/object-schema@2.1.4':
|
||||||
|
@ -400,8 +396,8 @@ packages:
|
||||||
'@types/jest@29.5.12':
|
'@types/jest@29.5.12':
|
||||||
resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==}
|
resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==}
|
||||||
|
|
||||||
'@types/node@22.0.2':
|
'@types/node@22.5.1':
|
||||||
resolution: {integrity: sha512-yPL6DyFwY5PiMVEwymNeqUTKsDczQBJ/5T7W/46RwLU/VH+AA8aT5TZkvBviLKLbbm0hlfftEkGrNzfRk/fofQ==}
|
resolution: {integrity: sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==}
|
||||||
|
|
||||||
'@types/stack-utils@2.0.3':
|
'@types/stack-utils@2.0.3':
|
||||||
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
|
resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==}
|
||||||
|
@ -516,8 +512,8 @@ packages:
|
||||||
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
|
||||||
async@3.2.5:
|
async@3.2.6:
|
||||||
resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==}
|
resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==}
|
||||||
|
|
||||||
babel-jest@29.7.0:
|
babel-jest@29.7.0:
|
||||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||||
|
@ -649,15 +645,6 @@ packages:
|
||||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
||||||
debug@4.3.4:
|
|
||||||
resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==}
|
|
||||||
engines: {node: '>=6.0'}
|
|
||||||
peerDependencies:
|
|
||||||
supports-color: '*'
|
|
||||||
peerDependenciesMeta:
|
|
||||||
supports-color:
|
|
||||||
optional: true
|
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==}
|
||||||
engines: {node: '>=6.0'}
|
engines: {node: '>=6.0'}
|
||||||
|
@ -754,10 +741,15 @@ packages:
|
||||||
resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
|
resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
|
|
||||||
eslint@9.8.0:
|
eslint@9.9.1:
|
||||||
resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==}
|
resolution: {integrity: sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==}
|
||||||
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
peerDependencies:
|
||||||
|
jiti: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
jiti:
|
||||||
|
optional: true
|
||||||
|
|
||||||
espree@10.1.0:
|
espree@10.1.0:
|
||||||
resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==}
|
resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==}
|
||||||
|
@ -768,8 +760,8 @@ packages:
|
||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
esquery@1.5.0:
|
esquery@1.6.0:
|
||||||
resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==}
|
resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==}
|
||||||
engines: {node: '>=0.10'}
|
engines: {node: '>=0.10'}
|
||||||
|
|
||||||
esrecurse@4.3.0:
|
esrecurse@4.3.0:
|
||||||
|
@ -928,6 +920,10 @@ packages:
|
||||||
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
|
resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==}
|
||||||
engines: {node: '>= 4'}
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
|
ignore@5.3.2:
|
||||||
|
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
|
||||||
|
engines: {node: '>= 4'}
|
||||||
|
|
||||||
import-fresh@3.3.0:
|
import-fresh@3.3.0:
|
||||||
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -1281,8 +1277,8 @@ packages:
|
||||||
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
|
||||||
optionator@0.9.3:
|
optionator@0.9.4:
|
||||||
resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==}
|
resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==}
|
||||||
engines: {node: '>= 0.8.0'}
|
engines: {node: '>= 0.8.0'}
|
||||||
|
|
||||||
p-limit@2.3.0:
|
p-limit@2.3.0:
|
||||||
|
@ -1416,11 +1412,6 @@ packages:
|
||||||
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
semver@7.6.2:
|
|
||||||
resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==}
|
|
||||||
engines: {node: '>=10'}
|
|
||||||
hasBin: true
|
|
||||||
|
|
||||||
semver@7.6.3:
|
semver@7.6.3:
|
||||||
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
|
resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -1526,8 +1517,8 @@ packages:
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
typescript: '>=4.2.0'
|
typescript: '>=4.2.0'
|
||||||
|
|
||||||
ts-jest@29.2.4:
|
ts-jest@29.2.5:
|
||||||
resolution: {integrity: sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==}
|
resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
@ -1579,8 +1570,8 @@ packages:
|
||||||
engines: {node: '>=14.17'}
|
engines: {node: '>=14.17'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
undici-types@6.11.1:
|
undici-types@6.19.8:
|
||||||
resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==}
|
resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==}
|
||||||
|
|
||||||
update-browserslist-db@1.0.13:
|
update-browserslist-db@1.0.13:
|
||||||
resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
|
resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==}
|
||||||
|
@ -1603,6 +1594,10 @@ packages:
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
|
word-wrap@1.2.5:
|
||||||
|
resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==}
|
||||||
|
engines: {node: '>=0.10.0'}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
|
@ -1635,8 +1630,6 @@ packages:
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@aashutoshrathi/word-wrap@1.2.6': {}
|
|
||||||
|
|
||||||
'@ampproject/remapping@2.2.1':
|
'@ampproject/remapping@2.2.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/gen-mapping': 0.3.3
|
'@jridgewell/gen-mapping': 0.3.3
|
||||||
|
@ -1841,17 +1834,17 @@ snapshots:
|
||||||
|
|
||||||
'@bcoe/v8-coverage@0.2.3': {}
|
'@bcoe/v8-coverage@0.2.3': {}
|
||||||
|
|
||||||
'@eslint-community/eslint-utils@4.4.0(eslint@9.8.0)':
|
'@eslint-community/eslint-utils@4.4.0(eslint@9.9.1)':
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.8.0
|
eslint: 9.9.1
|
||||||
eslint-visitor-keys: 3.4.3
|
eslint-visitor-keys: 3.4.3
|
||||||
|
|
||||||
'@eslint-community/regexpp@4.11.0': {}
|
'@eslint-community/regexpp@4.11.0': {}
|
||||||
|
|
||||||
'@eslint/config-array@0.17.1':
|
'@eslint/config-array@0.18.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/object-schema': 2.1.4
|
'@eslint/object-schema': 2.1.4
|
||||||
debug: 4.3.4
|
debug: 4.3.6
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -1859,10 +1852,10 @@ snapshots:
|
||||||
'@eslint/eslintrc@3.1.0':
|
'@eslint/eslintrc@3.1.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
debug: 4.3.4
|
debug: 4.3.6
|
||||||
espree: 10.1.0
|
espree: 10.1.0
|
||||||
globals: 14.0.0
|
globals: 14.0.0
|
||||||
ignore: 5.3.1
|
ignore: 5.3.2
|
||||||
import-fresh: 3.3.0
|
import-fresh: 3.3.0
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
|
@ -1870,7 +1863,7 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@eslint/js@9.8.0': {}
|
'@eslint/js@9.9.1': {}
|
||||||
|
|
||||||
'@eslint/object-schema@2.1.4': {}
|
'@eslint/object-schema@2.1.4': {}
|
||||||
|
|
||||||
|
@ -1891,7 +1884,7 @@ snapshots:
|
||||||
'@jest/console@29.7.0':
|
'@jest/console@29.7.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
|
@ -1904,14 +1897,14 @@ snapshots:
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
ansi-escapes: 4.3.2
|
ansi-escapes: 4.3.2
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
ci-info: 3.9.0
|
ci-info: 3.9.0
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
jest-changed-files: 29.7.0
|
jest-changed-files: 29.7.0
|
||||||
jest-config: 29.7.0(@types/node@22.0.2)
|
jest-config: 29.7.0(@types/node@22.5.1)
|
||||||
jest-haste-map: 29.7.0
|
jest-haste-map: 29.7.0
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-regex-util: 29.6.3
|
jest-regex-util: 29.6.3
|
||||||
|
@ -1936,7 +1929,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/fake-timers': 29.7.0
|
'@jest/fake-timers': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
|
|
||||||
'@jest/expect-utils@29.7.0':
|
'@jest/expect-utils@29.7.0':
|
||||||
|
@ -1954,7 +1947,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@sinonjs/fake-timers': 10.3.0
|
'@sinonjs/fake-timers': 10.3.0
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
jest-message-util: 29.7.0
|
jest-message-util: 29.7.0
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
|
@ -1976,7 +1969,7 @@ snapshots:
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@jridgewell/trace-mapping': 0.3.22
|
'@jridgewell/trace-mapping': 0.3.22
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
collect-v8-coverage: 1.0.2
|
collect-v8-coverage: 1.0.2
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
|
@ -2046,7 +2039,7 @@ snapshots:
|
||||||
'@jest/schemas': 29.6.3
|
'@jest/schemas': 29.6.3
|
||||||
'@types/istanbul-lib-coverage': 2.0.6
|
'@types/istanbul-lib-coverage': 2.0.6
|
||||||
'@types/istanbul-reports': 3.0.4
|
'@types/istanbul-reports': 3.0.4
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
'@types/yargs': 17.0.32
|
'@types/yargs': 17.0.32
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
|
|
||||||
|
@ -2114,7 +2107,7 @@ snapshots:
|
||||||
|
|
||||||
'@types/graceful-fs@4.1.9':
|
'@types/graceful-fs@4.1.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
|
|
||||||
'@types/istanbul-lib-coverage@2.0.6': {}
|
'@types/istanbul-lib-coverage@2.0.6': {}
|
||||||
|
|
||||||
|
@ -2131,9 +2124,9 @@ snapshots:
|
||||||
expect: 29.7.0
|
expect: 29.7.0
|
||||||
pretty-format: 29.7.0
|
pretty-format: 29.7.0
|
||||||
|
|
||||||
'@types/node@22.0.2':
|
'@types/node@22.5.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
undici-types: 6.11.1
|
undici-types: 6.19.8
|
||||||
|
|
||||||
'@types/stack-utils@2.0.3': {}
|
'@types/stack-utils@2.0.3': {}
|
||||||
|
|
||||||
|
@ -2143,15 +2136,15 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/yargs-parser': 21.0.3
|
'@types/yargs-parser': 21.0.3
|
||||||
|
|
||||||
'@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)':
|
'@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/regexpp': 4.11.0
|
'@eslint-community/regexpp': 4.11.0
|
||||||
'@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/parser': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/scope-manager': 8.0.0
|
'@typescript-eslint/scope-manager': 8.0.0
|
||||||
'@typescript-eslint/type-utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/type-utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/visitor-keys': 8.0.0
|
'@typescript-eslint/visitor-keys': 8.0.0
|
||||||
eslint: 9.8.0
|
eslint: 9.9.1
|
||||||
graphemer: 1.4.0
|
graphemer: 1.4.0
|
||||||
ignore: 5.3.1
|
ignore: 5.3.1
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
|
@ -2161,14 +2154,14 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4)':
|
'@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/scope-manager': 8.0.0
|
'@typescript-eslint/scope-manager': 8.0.0
|
||||||
'@typescript-eslint/types': 8.0.0
|
'@typescript-eslint/types': 8.0.0
|
||||||
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
||||||
'@typescript-eslint/visitor-keys': 8.0.0
|
'@typescript-eslint/visitor-keys': 8.0.0
|
||||||
debug: 4.3.6
|
debug: 4.3.6
|
||||||
eslint: 9.8.0
|
eslint: 9.9.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -2179,10 +2172,10 @@ snapshots:
|
||||||
'@typescript-eslint/types': 8.0.0
|
'@typescript-eslint/types': 8.0.0
|
||||||
'@typescript-eslint/visitor-keys': 8.0.0
|
'@typescript-eslint/visitor-keys': 8.0.0
|
||||||
|
|
||||||
'@typescript-eslint/type-utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)':
|
'@typescript-eslint/type-utils@8.0.0(eslint@9.9.1)(typescript@5.5.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
||||||
'@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
debug: 4.3.6
|
debug: 4.3.6
|
||||||
ts-api-utils: 1.3.0(typescript@5.5.4)
|
ts-api-utils: 1.3.0(typescript@5.5.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
|
@ -2208,13 +2201,13 @@ snapshots:
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@typescript-eslint/utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)':
|
'@typescript-eslint/utils@8.0.0(eslint@9.9.1)(typescript@5.5.4)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0)
|
'@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1)
|
||||||
'@typescript-eslint/scope-manager': 8.0.0
|
'@typescript-eslint/scope-manager': 8.0.0
|
||||||
'@typescript-eslint/types': 8.0.0
|
'@typescript-eslint/types': 8.0.0
|
||||||
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
'@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4)
|
||||||
eslint: 9.8.0
|
eslint: 9.9.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
|
@ -2266,7 +2259,7 @@ snapshots:
|
||||||
|
|
||||||
array-union@2.1.0: {}
|
array-union@2.1.0: {}
|
||||||
|
|
||||||
async@3.2.5: {}
|
async@3.2.6: {}
|
||||||
|
|
||||||
babel-jest@29.7.0(@babel/core@7.23.9):
|
babel-jest@29.7.0(@babel/core@7.23.9):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -2407,13 +2400,13 @@ snapshots:
|
||||||
|
|
||||||
convert-source-map@2.0.0: {}
|
convert-source-map@2.0.0: {}
|
||||||
|
|
||||||
create-jest@29.7.0(@types/node@22.0.2):
|
create-jest@29.7.0(@types/node@22.5.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
jest-config: 29.7.0(@types/node@22.0.2)
|
jest-config: 29.7.0(@types/node@22.5.1)
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
prompts: 2.4.2
|
prompts: 2.4.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -2428,10 +2421,6 @@ snapshots:
|
||||||
shebang-command: 2.0.0
|
shebang-command: 2.0.0
|
||||||
which: 2.0.2
|
which: 2.0.2
|
||||||
|
|
||||||
debug@4.3.4:
|
|
||||||
dependencies:
|
|
||||||
ms: 2.1.2
|
|
||||||
|
|
||||||
debug@4.3.6:
|
debug@4.3.6:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms: 2.1.2
|
ms: 2.1.2
|
||||||
|
@ -2472,9 +2461,9 @@ snapshots:
|
||||||
|
|
||||||
escape-string-regexp@4.0.0: {}
|
escape-string-regexp@4.0.0: {}
|
||||||
|
|
||||||
eslint-plugin-prettier@5.2.1(eslint@9.8.0)(prettier@3.3.3):
|
eslint-plugin-prettier@5.2.1(eslint@9.9.1)(prettier@3.3.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 9.8.0
|
eslint: 9.9.1
|
||||||
prettier: 3.3.3
|
prettier: 3.3.3
|
||||||
prettier-linter-helpers: 1.0.0
|
prettier-linter-helpers: 1.0.0
|
||||||
synckit: 0.9.1
|
synckit: 0.9.1
|
||||||
|
@ -2488,31 +2477,31 @@ snapshots:
|
||||||
|
|
||||||
eslint-visitor-keys@4.0.0: {}
|
eslint-visitor-keys@4.0.0: {}
|
||||||
|
|
||||||
eslint@9.8.0:
|
eslint@9.9.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0)
|
'@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1)
|
||||||
'@eslint-community/regexpp': 4.11.0
|
'@eslint-community/regexpp': 4.11.0
|
||||||
'@eslint/config-array': 0.17.1
|
'@eslint/config-array': 0.18.0
|
||||||
'@eslint/eslintrc': 3.1.0
|
'@eslint/eslintrc': 3.1.0
|
||||||
'@eslint/js': 9.8.0
|
'@eslint/js': 9.9.1
|
||||||
'@humanwhocodes/module-importer': 1.0.1
|
'@humanwhocodes/module-importer': 1.0.1
|
||||||
'@humanwhocodes/retry': 0.3.0
|
'@humanwhocodes/retry': 0.3.0
|
||||||
'@nodelib/fs.walk': 1.2.8
|
'@nodelib/fs.walk': 1.2.8
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cross-spawn: 7.0.3
|
cross-spawn: 7.0.3
|
||||||
debug: 4.3.4
|
debug: 4.3.6
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 8.0.2
|
eslint-scope: 8.0.2
|
||||||
eslint-visitor-keys: 4.0.0
|
eslint-visitor-keys: 4.0.0
|
||||||
espree: 10.1.0
|
espree: 10.1.0
|
||||||
esquery: 1.5.0
|
esquery: 1.6.0
|
||||||
esutils: 2.0.3
|
esutils: 2.0.3
|
||||||
fast-deep-equal: 3.1.3
|
fast-deep-equal: 3.1.3
|
||||||
file-entry-cache: 8.0.0
|
file-entry-cache: 8.0.0
|
||||||
find-up: 5.0.0
|
find-up: 5.0.0
|
||||||
glob-parent: 6.0.2
|
glob-parent: 6.0.2
|
||||||
ignore: 5.3.1
|
ignore: 5.3.2
|
||||||
imurmurhash: 0.1.4
|
imurmurhash: 0.1.4
|
||||||
is-glob: 4.0.3
|
is-glob: 4.0.3
|
||||||
is-path-inside: 3.0.3
|
is-path-inside: 3.0.3
|
||||||
|
@ -2521,7 +2510,7 @@ snapshots:
|
||||||
lodash.merge: 4.6.2
|
lodash.merge: 4.6.2
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
optionator: 0.9.3
|
optionator: 0.9.4
|
||||||
strip-ansi: 6.0.1
|
strip-ansi: 6.0.1
|
||||||
text-table: 0.2.0
|
text-table: 0.2.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -2535,7 +2524,7 @@ snapshots:
|
||||||
|
|
||||||
esprima@4.0.1: {}
|
esprima@4.0.1: {}
|
||||||
|
|
||||||
esquery@1.5.0:
|
esquery@1.6.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
|
|
||||||
|
@ -2667,7 +2656,7 @@ snapshots:
|
||||||
array-union: 2.1.0
|
array-union: 2.1.0
|
||||||
dir-glob: 3.0.1
|
dir-glob: 3.0.1
|
||||||
fast-glob: 3.3.2
|
fast-glob: 3.3.2
|
||||||
ignore: 5.3.1
|
ignore: 5.3.2
|
||||||
merge2: 1.4.1
|
merge2: 1.4.1
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
|
|
||||||
|
@ -2689,6 +2678,8 @@ snapshots:
|
||||||
|
|
||||||
ignore@5.3.1: {}
|
ignore@5.3.1: {}
|
||||||
|
|
||||||
|
ignore@5.3.2: {}
|
||||||
|
|
||||||
import-fresh@3.3.0:
|
import-fresh@3.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
parent-module: 1.0.1
|
parent-module: 1.0.1
|
||||||
|
@ -2775,7 +2766,7 @@ snapshots:
|
||||||
|
|
||||||
jake@10.9.2:
|
jake@10.9.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
async: 3.2.5
|
async: 3.2.6
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
filelist: 1.0.4
|
filelist: 1.0.4
|
||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
|
@ -2792,7 +2783,7 @@ snapshots:
|
||||||
'@jest/expect': 29.7.0
|
'@jest/expect': 29.7.0
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
co: 4.6.0
|
co: 4.6.0
|
||||||
dedent: 1.5.1
|
dedent: 1.5.1
|
||||||
|
@ -2812,16 +2803,16 @@ snapshots:
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
jest-cli@29.7.0(@types/node@22.0.2):
|
jest-cli@29.7.0(@types/node@22.5.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/core': 29.7.0
|
'@jest/core': 29.7.0
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
create-jest: 29.7.0(@types/node@22.0.2)
|
create-jest: 29.7.0(@types/node@22.5.1)
|
||||||
exit: 0.1.2
|
exit: 0.1.2
|
||||||
import-local: 3.1.0
|
import-local: 3.1.0
|
||||||
jest-config: 29.7.0(@types/node@22.0.2)
|
jest-config: 29.7.0(@types/node@22.5.1)
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
jest-validate: 29.7.0
|
jest-validate: 29.7.0
|
||||||
yargs: 17.7.2
|
yargs: 17.7.2
|
||||||
|
@ -2831,7 +2822,7 @@ snapshots:
|
||||||
- supports-color
|
- supports-color
|
||||||
- ts-node
|
- ts-node
|
||||||
|
|
||||||
jest-config@29.7.0(@types/node@22.0.2):
|
jest-config@29.7.0(@types/node@22.5.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.23.9
|
'@babel/core': 7.23.9
|
||||||
'@jest/test-sequencer': 29.7.0
|
'@jest/test-sequencer': 29.7.0
|
||||||
|
@ -2856,7 +2847,7 @@ snapshots:
|
||||||
slash: 3.0.0
|
slash: 3.0.0
|
||||||
strip-json-comments: 3.1.1
|
strip-json-comments: 3.1.1
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
- supports-color
|
- supports-color
|
||||||
|
@ -2885,7 +2876,7 @@ snapshots:
|
||||||
'@jest/environment': 29.7.0
|
'@jest/environment': 29.7.0
|
||||||
'@jest/fake-timers': 29.7.0
|
'@jest/fake-timers': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
jest-mock: 29.7.0
|
jest-mock: 29.7.0
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
|
|
||||||
|
@ -2895,7 +2886,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/graceful-fs': 4.1.9
|
'@types/graceful-fs': 4.1.9
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
anymatch: 3.1.3
|
anymatch: 3.1.3
|
||||||
fb-watchman: 2.0.2
|
fb-watchman: 2.0.2
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
@ -2934,7 +2925,7 @@ snapshots:
|
||||||
jest-mock@29.7.0:
|
jest-mock@29.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
|
|
||||||
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
|
jest-pnp-resolver@1.2.3(jest-resolve@29.7.0):
|
||||||
|
@ -2969,7 +2960,7 @@ snapshots:
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
emittery: 0.13.1
|
emittery: 0.13.1
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
@ -2997,7 +2988,7 @@ snapshots:
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
cjs-module-lexer: 1.2.3
|
cjs-module-lexer: 1.2.3
|
||||||
collect-v8-coverage: 1.0.2
|
collect-v8-coverage: 1.0.2
|
||||||
|
@ -3036,14 +3027,14 @@ snapshots:
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
natural-compare: 1.4.0
|
natural-compare: 1.4.0
|
||||||
pretty-format: 29.7.0
|
pretty-format: 29.7.0
|
||||||
semver: 7.6.2
|
semver: 7.6.3
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
jest-util@29.7.0:
|
jest-util@29.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
ci-info: 3.9.0
|
ci-info: 3.9.0
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
|
@ -3062,7 +3053,7 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/test-result': 29.7.0
|
'@jest/test-result': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
ansi-escapes: 4.3.2
|
ansi-escapes: 4.3.2
|
||||||
chalk: 4.1.2
|
chalk: 4.1.2
|
||||||
emittery: 0.13.1
|
emittery: 0.13.1
|
||||||
|
@ -3071,17 +3062,17 @@ snapshots:
|
||||||
|
|
||||||
jest-worker@29.7.0:
|
jest-worker@29.7.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 22.0.2
|
'@types/node': 22.5.1
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
merge-stream: 2.0.0
|
merge-stream: 2.0.0
|
||||||
supports-color: 8.1.1
|
supports-color: 8.1.1
|
||||||
|
|
||||||
jest@29.7.0(@types/node@22.0.2):
|
jest@29.7.0(@types/node@22.5.1):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jest/core': 29.7.0
|
'@jest/core': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
import-local: 3.1.0
|
import-local: 3.1.0
|
||||||
jest-cli: 29.7.0(@types/node@22.0.2)
|
jest-cli: 29.7.0(@types/node@22.5.1)
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@types/node'
|
- '@types/node'
|
||||||
- babel-plugin-macros
|
- babel-plugin-macros
|
||||||
|
@ -3204,14 +3195,14 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
mimic-fn: 2.1.0
|
mimic-fn: 2.1.0
|
||||||
|
|
||||||
optionator@0.9.3:
|
optionator@0.9.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@aashutoshrathi/word-wrap': 1.2.6
|
|
||||||
deep-is: 0.1.4
|
deep-is: 0.1.4
|
||||||
fast-levenshtein: 2.0.6
|
fast-levenshtein: 2.0.6
|
||||||
levn: 0.4.1
|
levn: 0.4.1
|
||||||
prelude-ls: 1.2.1
|
prelude-ls: 1.2.1
|
||||||
type-check: 0.4.0
|
type-check: 0.4.0
|
||||||
|
word-wrap: 1.2.5
|
||||||
|
|
||||||
p-limit@2.3.0:
|
p-limit@2.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3315,8 +3306,6 @@ snapshots:
|
||||||
|
|
||||||
semver@6.3.1: {}
|
semver@6.3.1: {}
|
||||||
|
|
||||||
semver@7.6.2: {}
|
|
||||||
|
|
||||||
semver@7.6.3: {}
|
semver@7.6.3: {}
|
||||||
|
|
||||||
shebang-command@2.0.0:
|
shebang-command@2.0.0:
|
||||||
|
@ -3404,12 +3393,12 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
|
|
||||||
ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4):
|
ts-jest@29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.5.1))(typescript@5.5.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
bs-logger: 0.2.6
|
bs-logger: 0.2.6
|
||||||
ejs: 3.1.10
|
ejs: 3.1.10
|
||||||
fast-json-stable-stringify: 2.1.0
|
fast-json-stable-stringify: 2.1.0
|
||||||
jest: 29.7.0(@types/node@22.0.2)
|
jest: 29.7.0(@types/node@22.5.1)
|
||||||
jest-util: 29.7.0
|
jest-util: 29.7.0
|
||||||
json5: 2.2.3
|
json5: 2.2.3
|
||||||
lodash.memoize: 4.1.2
|
lodash.memoize: 4.1.2
|
||||||
|
@ -3433,11 +3422,11 @@ snapshots:
|
||||||
|
|
||||||
type-fest@0.21.3: {}
|
type-fest@0.21.3: {}
|
||||||
|
|
||||||
typescript-eslint@8.0.0(eslint@9.8.0)(typescript@5.5.4):
|
typescript-eslint@8.0.0(eslint@9.9.1)(typescript@5.5.4):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/parser': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
'@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4)
|
'@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
typescript: 5.5.4
|
typescript: 5.5.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
|
@ -3446,7 +3435,7 @@ snapshots:
|
||||||
|
|
||||||
typescript@5.5.4: {}
|
typescript@5.5.4: {}
|
||||||
|
|
||||||
undici-types@6.11.1: {}
|
undici-types@6.19.8: {}
|
||||||
|
|
||||||
update-browserslist-db@1.0.13(browserslist@4.22.3):
|
update-browserslist-db@1.0.13(browserslist@4.22.3):
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -3472,6 +3461,8 @@ snapshots:
|
||||||
dependencies:
|
dependencies:
|
||||||
isexe: 2.0.0
|
isexe: 2.0.0
|
||||||
|
|
||||||
|
word-wrap@1.2.5: {}
|
||||||
|
|
||||||
wrap-ansi@7.0.0:
|
wrap-ansi@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
ansi-styles: 4.3.0
|
ansi-styles: 4.3.0
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
jest.setTimeout(120000);
|
jest.setTimeout(120000);
|
||||||
|
|
||||||
|
import { AddModToCommunity } from "lemmy-js-client/dist/types/AddModToCommunity";
|
||||||
import { CommunityView } from "lemmy-js-client/dist/types/CommunityView";
|
import { CommunityView } from "lemmy-js-client/dist/types/CommunityView";
|
||||||
import {
|
import {
|
||||||
alpha,
|
alpha,
|
||||||
|
@ -9,6 +10,7 @@ import {
|
||||||
resolveCommunity,
|
resolveCommunity,
|
||||||
createCommunity,
|
createCommunity,
|
||||||
deleteCommunity,
|
deleteCommunity,
|
||||||
|
delay,
|
||||||
removeCommunity,
|
removeCommunity,
|
||||||
getCommunity,
|
getCommunity,
|
||||||
followCommunity,
|
followCommunity,
|
||||||
|
@ -533,3 +535,41 @@ test("Content in local-only community doesn't federate", async () => {
|
||||||
Error("couldnt_find_object"),
|
Error("couldnt_find_object"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Remote mods can edit communities", async () => {
|
||||||
|
let communityRes = await createCommunity(alpha);
|
||||||
|
|
||||||
|
let betaCommunity = await resolveCommunity(
|
||||||
|
beta,
|
||||||
|
communityRes.community_view.community.actor_id,
|
||||||
|
);
|
||||||
|
if (!betaCommunity.community) {
|
||||||
|
throw "Missing beta community";
|
||||||
|
}
|
||||||
|
let betaOnAlpha = await resolvePerson(alpha, "lemmy_beta@lemmy-beta:8551");
|
||||||
|
|
||||||
|
let form: AddModToCommunity = {
|
||||||
|
community_id: communityRes.community_view.community.id,
|
||||||
|
person_id: betaOnAlpha.person?.person.id as number,
|
||||||
|
added: true,
|
||||||
|
};
|
||||||
|
alpha.addModToCommunity(form);
|
||||||
|
|
||||||
|
let form2: EditCommunity = {
|
||||||
|
community_id: betaCommunity.community?.community.id as number,
|
||||||
|
description: "Example description",
|
||||||
|
};
|
||||||
|
|
||||||
|
await editCommunity(beta, form2);
|
||||||
|
// give alpha time to get and process the edit
|
||||||
|
await delay(1000);
|
||||||
|
|
||||||
|
let alphaCommunity = await getCommunity(
|
||||||
|
alpha,
|
||||||
|
communityRes.community_view.community.id,
|
||||||
|
);
|
||||||
|
|
||||||
|
await expect(alphaCommunity.community_view.community.description).toBe(
|
||||||
|
"Example description",
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
|
@ -43,3 +43,4 @@ serial_test = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
elementtree = "1.2.3"
|
elementtree = "1.2.3"
|
||||||
pretty_assertions = { workspace = true }
|
pretty_assertions = { workspace = true }
|
||||||
|
lemmy_api_crud = { workspace = true }
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use actix_web::web::{Data, Json};
|
use actix_web::web::{Data, Json};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::{context::LemmyContext, person::ListLoginsResponse};
|
||||||
use lemmy_db_schema::source::login_token::LoginToken;
|
use lemmy_db_schema::source::login_token::LoginToken;
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
@ -7,8 +7,8 @@ use lemmy_utils::error::LemmyResult;
|
||||||
pub async fn list_logins(
|
pub async fn list_logins(
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
local_user_view: LocalUserView,
|
local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<Vec<LoginToken>>> {
|
) -> LemmyResult<Json<ListLoginsResponse>> {
|
||||||
let logins = LoginToken::list(&mut context.pool(), local_user_view.local_user.id).await?;
|
let logins = LoginToken::list(&mut context.pool(), local_user_view.local_user.id).await?;
|
||||||
|
|
||||||
Ok(Json(logins))
|
Ok(Json(ListLoginsResponse { logins }))
|
||||||
}
|
}
|
||||||
|
|
|
@ -135,7 +135,6 @@ pub async fn save_user_settings(
|
||||||
blur_nsfw: data.blur_nsfw,
|
blur_nsfw: data.blur_nsfw,
|
||||||
auto_expand: data.auto_expand,
|
auto_expand: data.auto_expand,
|
||||||
show_bot_accounts: data.show_bot_accounts,
|
show_bot_accounts: data.show_bot_accounts,
|
||||||
show_scores: data.show_scores,
|
|
||||||
default_sort_type,
|
default_sort_type,
|
||||||
default_listing_type,
|
default_listing_type,
|
||||||
theme: data.theme.clone(),
|
theme: data.theme.clone(),
|
||||||
|
|
|
@ -4,6 +4,7 @@ use lemmy_api_common::{
|
||||||
post::{GetSiteMetadata, GetSiteMetadataResponse},
|
post::{GetSiteMetadata, GetSiteMetadataResponse},
|
||||||
request::fetch_link_metadata,
|
request::fetch_link_metadata,
|
||||||
};
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyErrorExt, LemmyResult},
|
error::{LemmyErrorExt, LemmyResult},
|
||||||
LemmyErrorType,
|
LemmyErrorType,
|
||||||
|
@ -14,6 +15,8 @@ use url::Url;
|
||||||
pub async fn get_link_metadata(
|
pub async fn get_link_metadata(
|
||||||
data: Query<GetSiteMetadata>,
|
data: Query<GetSiteMetadata>,
|
||||||
context: Data<LemmyContext>,
|
context: Data<LemmyContext>,
|
||||||
|
// Require an account for this API
|
||||||
|
_local_user_view: LocalUserView,
|
||||||
) -> LemmyResult<Json<GetSiteMetadataResponse>> {
|
) -> LemmyResult<Json<GetSiteMetadataResponse>> {
|
||||||
let url = Url::parse(&data.url).with_lemmy_type(LemmyErrorType::InvalidUrl)?;
|
let url = Url::parse(&data.url).with_lemmy_type(LemmyErrorType::InvalidUrl)?;
|
||||||
let metadata = fetch_link_metadata(&url, &context).await?;
|
let metadata = fetch_link_metadata(&url, &context).await?;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use actix_web::web::{Data, Json};
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
|
site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
|
||||||
|
@ -10,10 +11,13 @@ use lemmy_db_schema::{
|
||||||
registration_application::{RegistrationApplication, RegistrationApplicationUpdateForm},
|
registration_application::{RegistrationApplication, RegistrationApplicationUpdateForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::diesel_string_update,
|
utils::{diesel_string_update, get_conn},
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
|
use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView};
|
||||||
use lemmy_utils::{error::LemmyResult, LemmyErrorType};
|
use lemmy_utils::{
|
||||||
|
error::{LemmyError, LemmyResult},
|
||||||
|
LemmyErrorType,
|
||||||
|
};
|
||||||
|
|
||||||
pub async fn approve_registration_application(
|
pub async fn approve_registration_application(
|
||||||
data: Json<ApproveRegistrationApplication>,
|
data: Json<ApproveRegistrationApplication>,
|
||||||
|
@ -25,34 +29,46 @@ pub async fn approve_registration_application(
|
||||||
// Only let admins do this
|
// Only let admins do this
|
||||||
is_admin(&local_user_view)?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let pool = &mut context.pool();
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
let tx_data = data.clone();
|
||||||
|
let approved_user_id = conn
|
||||||
|
.build_transaction()
|
||||||
|
.run(|conn| {
|
||||||
|
Box::pin(async move {
|
||||||
// Update the registration with reason, admin_id
|
// Update the registration with reason, admin_id
|
||||||
let deny_reason = diesel_string_update(data.deny_reason.as_deref());
|
let deny_reason = diesel_string_update(tx_data.deny_reason.as_deref());
|
||||||
let app_form = RegistrationApplicationUpdateForm {
|
let app_form = RegistrationApplicationUpdateForm {
|
||||||
admin_id: Some(Some(local_user_view.person.id)),
|
admin_id: Some(Some(local_user_view.person.id)),
|
||||||
deny_reason,
|
deny_reason,
|
||||||
};
|
};
|
||||||
|
|
||||||
let registration_application =
|
let registration_application =
|
||||||
RegistrationApplication::update(&mut context.pool(), app_id, &app_form).await?;
|
RegistrationApplication::update(&mut conn.into(), app_id, &app_form).await?;
|
||||||
|
|
||||||
// Update the local_user row
|
// Update the local_user row
|
||||||
let local_user_form = LocalUserUpdateForm {
|
let local_user_form = LocalUserUpdateForm {
|
||||||
accepted_application: Some(data.approve),
|
accepted_application: Some(tx_data.approve),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let approved_user_id = registration_application.local_user_id;
|
let approved_user_id = registration_application.local_user_id;
|
||||||
LocalUser::update(&mut context.pool(), approved_user_id, &local_user_form).await?;
|
LocalUser::update(&mut conn.into(), approved_user_id, &local_user_form).await?;
|
||||||
|
|
||||||
|
Ok::<_, LemmyError>(approved_user_id)
|
||||||
|
}) as _
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
if data.approve {
|
if data.approve {
|
||||||
let approved_local_user_view = LocalUserView::read(&mut context.pool(), approved_user_id)
|
let approved_local_user_view = LocalUserView::read(&mut context.pool(), approved_user_id)
|
||||||
.await?
|
.await?
|
||||||
.ok_or(LemmyErrorType::CouldntFindLocalUser)?;
|
.ok_or(LemmyErrorType::CouldntFindLocalUser)?;
|
||||||
|
|
||||||
if approved_local_user_view.local_user.email.is_some() {
|
if approved_local_user_view.local_user.email.is_some() {
|
||||||
|
// Email sending may fail, but this won't revert the application approval
|
||||||
send_application_approved_email(&approved_local_user_view, context.settings()).await?;
|
send_application_approved_email(&approved_local_user_view, context.settings()).await?;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Read the view
|
// Read the view
|
||||||
let registration_application = RegistrationApplicationView::read(&mut context.pool(), app_id)
|
let registration_application = RegistrationApplicationView::read(&mut context.pool(), app_id)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use actix_web::web::{Data, Json, Query};
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::{Json, Query};
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
|
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
pub mod approve;
|
pub mod approve;
|
||||||
pub mod get;
|
pub mod get;
|
||||||
pub mod list;
|
pub mod list;
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests;
|
||||||
pub mod unread_count;
|
pub mod unread_count;
|
||||||
|
|
428
crates/api/src/site/registration_applications/tests.rs
Normal file
428
crates/api/src/site/registration_applications/tests.rs
Normal file
|
@ -0,0 +1,428 @@
|
||||||
|
use crate::site::registration_applications::{
|
||||||
|
approve::approve_registration_application,
|
||||||
|
list::list_registration_applications,
|
||||||
|
unread_count::get_unread_registration_application_count,
|
||||||
|
};
|
||||||
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::{Json, Query};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
site::{
|
||||||
|
ApproveRegistrationApplication,
|
||||||
|
EditSite,
|
||||||
|
GetUnreadRegistrationApplicationCountResponse,
|
||||||
|
ListRegistrationApplicationsResponse,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use lemmy_api_crud::site::update::update_site;
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
newtypes::InstanceId,
|
||||||
|
source::{
|
||||||
|
instance::Instance,
|
||||||
|
local_site::{LocalSite, LocalSiteInsertForm},
|
||||||
|
local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitInsertForm},
|
||||||
|
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||||
|
person::{Person, PersonInsertForm},
|
||||||
|
registration_application::{RegistrationApplication, RegistrationApplicationInsertForm},
|
||||||
|
site::{Site, SiteInsertForm},
|
||||||
|
},
|
||||||
|
traits::Crud,
|
||||||
|
utils::DbPool,
|
||||||
|
RegistrationMode,
|
||||||
|
};
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::{error::LemmyResult, LemmyErrorType, CACHE_DURATION_API};
|
||||||
|
use serial_test::serial;
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
async fn create_test_site(context: &Data<LemmyContext>) -> LemmyResult<(Instance, LocalUserView)> {
|
||||||
|
let pool = &mut context.pool();
|
||||||
|
|
||||||
|
let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string())
|
||||||
|
.await
|
||||||
|
.expect("Create test instance");
|
||||||
|
|
||||||
|
let admin_person = Person::create(
|
||||||
|
pool,
|
||||||
|
&PersonInsertForm::test_form(inserted_instance.id, "admin"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
LocalUser::create(
|
||||||
|
pool,
|
||||||
|
&LocalUserInsertForm::test_form_admin(admin_person.id),
|
||||||
|
vec![],
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let admin_local_user_view = LocalUserView::read_person(pool, admin_person.id)
|
||||||
|
.await?
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let site_form = SiteInsertForm::builder()
|
||||||
|
.name("test site".to_string())
|
||||||
|
.instance_id(inserted_instance.id)
|
||||||
|
.build();
|
||||||
|
let site = Site::create(pool, &site_form).await.unwrap();
|
||||||
|
|
||||||
|
// Create a local site, since this is necessary for determining if email verification is
|
||||||
|
// required
|
||||||
|
let local_site_form = LocalSiteInsertForm::builder()
|
||||||
|
.site_id(site.id)
|
||||||
|
.require_email_verification(Some(true))
|
||||||
|
.application_question(Some(".".to_string()))
|
||||||
|
.registration_mode(Some(RegistrationMode::RequireApplication))
|
||||||
|
.site_setup(Some(true))
|
||||||
|
.build();
|
||||||
|
let local_site = LocalSite::create(pool, &local_site_form).await.unwrap();
|
||||||
|
|
||||||
|
// Required to have a working local SiteView when updating the site to change email verification
|
||||||
|
// requirement or registration mode
|
||||||
|
let rate_limit_form = LocalSiteRateLimitInsertForm::builder()
|
||||||
|
.local_site_id(local_site.id)
|
||||||
|
.build();
|
||||||
|
LocalSiteRateLimit::create(pool, &rate_limit_form)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Ok((inserted_instance, admin_local_user_view))
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn signup(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
instance_id: InstanceId,
|
||||||
|
name: &str,
|
||||||
|
email: Option<&str>,
|
||||||
|
) -> LemmyResult<(LocalUser, RegistrationApplication)> {
|
||||||
|
let person_insert_form = PersonInsertForm::test_form(instance_id, name);
|
||||||
|
let person = Person::create(pool, &person_insert_form).await?;
|
||||||
|
|
||||||
|
let local_user_insert_form = match email {
|
||||||
|
Some(email) => LocalUserInsertForm {
|
||||||
|
email: Some(email.to_string()),
|
||||||
|
email_verified: Some(false),
|
||||||
|
..LocalUserInsertForm::test_form(person.id)
|
||||||
|
},
|
||||||
|
None => LocalUserInsertForm::test_form(person.id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let local_user = LocalUser::create(pool, &local_user_insert_form, vec![]).await?;
|
||||||
|
|
||||||
|
let application_insert_form = RegistrationApplicationInsertForm {
|
||||||
|
local_user_id: local_user.id,
|
||||||
|
answer: "x".to_string(),
|
||||||
|
};
|
||||||
|
let application = RegistrationApplication::create(pool, &application_insert_form).await?;
|
||||||
|
|
||||||
|
Ok((local_user, application))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
async fn get_application_statuses(
|
||||||
|
context: &Data<LemmyContext>,
|
||||||
|
admin: LocalUserView,
|
||||||
|
) -> LemmyResult<(
|
||||||
|
Json<GetUnreadRegistrationApplicationCountResponse>,
|
||||||
|
Json<ListRegistrationApplicationsResponse>,
|
||||||
|
Json<ListRegistrationApplicationsResponse>,
|
||||||
|
)> {
|
||||||
|
let application_count =
|
||||||
|
get_unread_registration_application_count(context.reset_request_count(), admin.clone()).await?;
|
||||||
|
|
||||||
|
let unread_applications = list_registration_applications(
|
||||||
|
Query::from_query("unread_only=true").unwrap(),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
let all_applications = list_registration_applications(
|
||||||
|
Query::from_query("unread_only=false").unwrap(),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok((application_count, unread_applications, all_applications))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[tokio::test]
|
||||||
|
#[serial]
|
||||||
|
async fn test_application_approval() -> LemmyResult<()> {
|
||||||
|
let context = LemmyContext::init_test_context().await;
|
||||||
|
let pool = &mut context.pool();
|
||||||
|
|
||||||
|
let (instance, admin_local_user_view) = create_test_site(&context).await?;
|
||||||
|
|
||||||
|
// Non-unread counts unfortunately are duplicated due to different types (i64 vs usize)
|
||||||
|
let mut expected_total_applications = 0;
|
||||||
|
let mut expected_unread_applications = 0u8;
|
||||||
|
|
||||||
|
let (local_user_with_email, app_with_email) =
|
||||||
|
signup(pool, instance.id, "user_w_email", Some("lemmy@localhost")).await?;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// When email verification is required and the email is not verified the application should not
|
||||||
|
// be visible to admins
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalUser::update(
|
||||||
|
pool,
|
||||||
|
local_user_with_email.id,
|
||||||
|
&LocalUserUpdateForm {
|
||||||
|
email_verified: Some(true),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
expected_total_applications += 1;
|
||||||
|
expected_unread_applications += 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// When email verification is required and the email is verified the application should be
|
||||||
|
// visible to admins
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
!unread_applications.registration_applications[0]
|
||||||
|
.creator_local_user
|
||||||
|
.accepted_application
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
let approval = approve_registration_application(
|
||||||
|
Json(ApproveRegistrationApplication {
|
||||||
|
id: app_with_email.id,
|
||||||
|
approve: true,
|
||||||
|
deny_reason: None,
|
||||||
|
}),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin_local_user_view.clone(),
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
// Approval should be processed up until email sending is attempted
|
||||||
|
assert!(approval.is_err_and(|e| e.error_type == LemmyErrorType::NoEmailSetup));
|
||||||
|
|
||||||
|
expected_unread_applications -= 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// When the application is approved it should only be returned for unread queries
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
assert!(
|
||||||
|
all_applications.registration_applications[0]
|
||||||
|
.creator_local_user
|
||||||
|
.accepted_application
|
||||||
|
);
|
||||||
|
|
||||||
|
let (_local_user, app_with_email_2) = signup(
|
||||||
|
pool,
|
||||||
|
instance.id,
|
||||||
|
"user_w_email_2",
|
||||||
|
Some("lemmy2@localhost"),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// Email not verified, so application still not visible
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
update_site(
|
||||||
|
Json(EditSite {
|
||||||
|
require_email_verification: Some(false),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin_local_user_view.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO: There is probably a better way to ensure cache invalidation
|
||||||
|
tokio::time::sleep(CACHE_DURATION_API).await;
|
||||||
|
|
||||||
|
expected_total_applications += 1;
|
||||||
|
expected_unread_applications += 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// After disabling email verification the application should now be visible
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
approve_registration_application(
|
||||||
|
Json(ApproveRegistrationApplication {
|
||||||
|
id: app_with_email_2.id,
|
||||||
|
approve: false,
|
||||||
|
deny_reason: None,
|
||||||
|
}),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin_local_user_view.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
expected_unread_applications -= 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// Denied applications should not be marked as unread
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
signup(pool, instance.id, "user_wo_email", None).await?;
|
||||||
|
|
||||||
|
expected_total_applications += 1;
|
||||||
|
expected_unread_applications += 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// New user without email should immediately be visible
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
signup(pool, instance.id, "user_w_email_3", None).await?;
|
||||||
|
|
||||||
|
expected_total_applications += 1;
|
||||||
|
expected_unread_applications += 1;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// New user with email should immediately be visible
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
update_site(
|
||||||
|
Json(EditSite {
|
||||||
|
registration_mode: Some(RegistrationMode::Open),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
context.reset_request_count(),
|
||||||
|
admin_local_user_view.clone(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
// TODO: There is probably a better way to ensure cache invalidation
|
||||||
|
tokio::time::sleep(CACHE_DURATION_API).await;
|
||||||
|
|
||||||
|
let (application_count, unread_applications, all_applications) =
|
||||||
|
get_application_statuses(&context, admin_local_user_view.clone()).await?;
|
||||||
|
|
||||||
|
// TODO: At this time applications do not get approved when switching to open registration, so the
|
||||||
|
// numbers will not change. See https://github.com/LemmyNet/lemmy/issues/4969
|
||||||
|
// expected_application_count = 0;
|
||||||
|
// expected_unread_applications_len = 0;
|
||||||
|
|
||||||
|
// When applications are not required all previous applications should become approved but still
|
||||||
|
// visible
|
||||||
|
assert_eq!(
|
||||||
|
application_count.registration_applications,
|
||||||
|
i64::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
unread_applications.registration_applications.len(),
|
||||||
|
usize::from(expected_unread_applications),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
all_applications.registration_applications.len(),
|
||||||
|
expected_total_applications,
|
||||||
|
);
|
||||||
|
|
||||||
|
LocalSite::delete(pool).await?;
|
||||||
|
// Instance deletion cascades cleanup of all created persons
|
||||||
|
Instance::delete(pool, instance.id).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use actix_web::web::{Data, Json};
|
use activitypub_federation::config::Data;
|
||||||
|
use actix_web::web::Json;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::GetUnreadRegistrationApplicationCountResponse,
|
site::GetUnreadRegistrationApplicationCountResponse,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
||||||
sensitive::SensitiveString,
|
sensitive::SensitiveString,
|
||||||
source::site::Site,
|
source::{login_token::LoginToken, site::Site},
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
|
@ -441,3 +441,10 @@ pub struct ListMedia {
|
||||||
pub struct ListMediaResponse {
|
pub struct ListMediaResponse {
|
||||||
pub images: Vec<LocalImageView>,
|
pub images: Vec<LocalImageView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct ListLoginsResponse {
|
||||||
|
pub logins: Vec<LoginToken>,
|
||||||
|
}
|
||||||
|
|
|
@ -11,10 +11,12 @@ use lemmy_db_schema::{
|
||||||
RegistrationApplicationId,
|
RegistrationApplicationId,
|
||||||
},
|
},
|
||||||
source::{
|
source::{
|
||||||
|
community::Community,
|
||||||
federation_queue_state::FederationQueueState,
|
federation_queue_state::FederationQueueState,
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
language::Language,
|
language::Language,
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
|
person::Person,
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
},
|
},
|
||||||
ListingType,
|
ListingType,
|
||||||
|
@ -33,12 +35,9 @@ use lemmy_db_views::structs::{
|
||||||
SiteView,
|
SiteView,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::structs::{
|
use lemmy_db_views_actor::structs::{
|
||||||
CommunityBlockView,
|
|
||||||
CommunityFollowerView,
|
CommunityFollowerView,
|
||||||
CommunityModeratorView,
|
CommunityModeratorView,
|
||||||
CommunityView,
|
CommunityView,
|
||||||
InstanceBlockView,
|
|
||||||
PersonBlockView,
|
|
||||||
PersonView,
|
PersonView,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_moderator::structs::{
|
use lemmy_db_views_moderator::structs::{
|
||||||
|
@ -337,9 +336,9 @@ pub struct MyUserInfo {
|
||||||
pub local_user_view: LocalUserView,
|
pub local_user_view: LocalUserView,
|
||||||
pub follows: Vec<CommunityFollowerView>,
|
pub follows: Vec<CommunityFollowerView>,
|
||||||
pub moderates: Vec<CommunityModeratorView>,
|
pub moderates: Vec<CommunityModeratorView>,
|
||||||
pub community_blocks: Vec<CommunityBlockView>,
|
pub community_blocks: Vec<Community>,
|
||||||
pub instance_blocks: Vec<InstanceBlockView>,
|
pub instance_blocks: Vec<Instance>,
|
||||||
pub person_blocks: Vec<PersonBlockView>,
|
pub person_blocks: Vec<Person>,
|
||||||
pub discussion_languages: Vec<LanguageId>,
|
pub discussion_languages: Vec<LanguageId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::site::{application_question_check, site_default_post_listing_type_check};
|
use crate::site::{application_question_check, site_default_post_listing_type_check};
|
||||||
use activitypub_federation::http_signatures::generate_actor_keypair;
|
use activitypub_federation::{config::Data, http_signatures::generate_actor_keypair};
|
||||||
use actix_web::web::{Data, Json};
|
use actix_web::web::Json;
|
||||||
use lemmy_api_common::{
|
use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
site::{CreateSite, SiteResponse},
|
site::{CreateSite, SiteResponse},
|
||||||
|
|
|
@ -5,19 +5,15 @@ use lemmy_api_common::{
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
actor_language::{LocalUserLanguage, SiteLanguage},
|
actor_language::{LocalUserLanguage, SiteLanguage},
|
||||||
|
community_block::CommunityBlock,
|
||||||
|
instance_block::InstanceBlock,
|
||||||
language::Language,
|
language::Language,
|
||||||
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
local_site_url_blocklist::LocalSiteUrlBlocklist,
|
||||||
|
person_block::PersonBlock,
|
||||||
tagline::Tagline,
|
tagline::Tagline,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView};
|
use lemmy_db_views::structs::{CustomEmojiView, LocalUserView, SiteView};
|
||||||
use lemmy_db_views_actor::structs::{
|
use lemmy_db_views_actor::structs::{CommunityFollowerView, CommunityModeratorView, PersonView};
|
||||||
CommunityBlockView,
|
|
||||||
CommunityFollowerView,
|
|
||||||
CommunityModeratorView,
|
|
||||||
InstanceBlockView,
|
|
||||||
PersonBlockView,
|
|
||||||
PersonView,
|
|
||||||
};
|
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
error::{LemmyError, LemmyErrorExt, LemmyErrorType, LemmyResult},
|
||||||
CACHE_DURATION_API,
|
CACHE_DURATION_API,
|
||||||
|
@ -81,9 +77,9 @@ pub async fn get_site(
|
||||||
discussion_languages,
|
discussion_languages,
|
||||||
) = lemmy_db_schema::try_join_with_pool!(pool => (
|
) = lemmy_db_schema::try_join_with_pool!(pool => (
|
||||||
|pool| CommunityFollowerView::for_person(pool, person_id),
|
|pool| CommunityFollowerView::for_person(pool, person_id),
|
||||||
|pool| CommunityBlockView::for_person(pool, person_id),
|
|pool| CommunityBlock::for_person(pool, person_id),
|
||||||
|pool| InstanceBlockView::for_person(pool, person_id),
|
|pool| InstanceBlock::for_person(pool, person_id),
|
||||||
|pool| PersonBlockView::for_person(pool, person_id),
|
|pool| PersonBlock::for_person(pool, person_id),
|
||||||
|pool| CommunityModeratorView::for_person(pool, person_id, Some(&local_user_view.local_user)),
|
|pool| CommunityModeratorView::for_person(pool, person_id, Some(&local_user_view.local_user)),
|
||||||
|pool| LocalUserLanguage::read(pool, local_user_id)
|
|pool| LocalUserLanguage::read(pool, local_user_id)
|
||||||
))
|
))
|
||||||
|
|
|
@ -8,6 +8,6 @@
|
||||||
"type": "Block",
|
"type": "Block",
|
||||||
"removeData": true,
|
"removeData": true,
|
||||||
"summary": "spam post",
|
"summary": "spam post",
|
||||||
"expires": "2021-11-01T12:23:50.151874Z",
|
"endTime": "2021-11-01T12:23:50.151874Z",
|
||||||
"id": "http://enterprise.lemmy.ml/activities/block/5d42fffb-0903-4625-86d4-0b39bb344fc2"
|
"id": "http://enterprise.lemmy.ml/activities/block/5d42fffb-0903-4625-86d4-0b39bb344fc2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
"type": "Block",
|
"type": "Block",
|
||||||
"removeData": true,
|
"removeData": true,
|
||||||
"summary": "spam post",
|
"summary": "spam post",
|
||||||
"expires": "2021-11-01T12:23:50.151874Z",
|
"endTime": "2021-11-01T12:23:50.151874Z",
|
||||||
"id": "http://enterprise.lemmy.ml/activities/block/726f43ab-bd0e-4ab3-89c8-627e976f553c"
|
"id": "http://enterprise.lemmy.ml/activities/block/726f43ab-bd0e-4ab3-89c8-627e976f553c"
|
||||||
},
|
},
|
||||||
"cc": ["http://enterprise.lemmy.ml/c/main"],
|
"cc": ["http://enterprise.lemmy.ml/c/main"],
|
||||||
|
|
|
@ -74,7 +74,6 @@ impl BlockUser {
|
||||||
&context.settings().get_protocol_and_hostname(),
|
&context.settings().get_protocol_and_hostname(),
|
||||||
)?,
|
)?,
|
||||||
audience,
|
audience,
|
||||||
expires,
|
|
||||||
end_time: expires,
|
end_time: expires,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -157,7 +156,7 @@ impl ActivityHandler for BlockUser {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
||||||
insert_received_activity(&self.id, context).await?;
|
insert_received_activity(&self.id, context).await?;
|
||||||
let expires = self.expires.or(self.end_time).map(Into::into);
|
let expires = self.end_time.map(Into::into);
|
||||||
let mod_person = self.actor.dereference(context).await?;
|
let mod_person = self.actor.dereference(context).await?;
|
||||||
let blocked_person = self.object.dereference(context).await?;
|
let blocked_person = self.object.dereference(context).await?;
|
||||||
let target = self.target.dereference(context).await?;
|
let target = self.target.dereference(context).await?;
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl ActivityHandler for UndoBlockUser {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
async fn receive(self, context: &Data<LemmyContext>) -> LemmyResult<()> {
|
||||||
insert_received_activity(&self.id, context).await?;
|
insert_received_activity(&self.id, context).await?;
|
||||||
let expires = self.object.expires.or(self.object.end_time).map(Into::into);
|
let expires = self.object.end_time.map(Into::into);
|
||||||
let mod_person = self.actor.dereference(context).await?;
|
let mod_person = self.actor.dereference(context).await?;
|
||||||
let blocked_person = self.object.object.dereference(context).await?;
|
let blocked_person = self.object.object.dereference(context).await?;
|
||||||
match self.object.target.dereference(context).await? {
|
match self.object.target.dereference(context).await? {
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub async fn resolve_object(
|
||||||
// if there's no personId then the JWT was missing or invalid.
|
// if there's no personId then the JWT was missing or invalid.
|
||||||
let is_authenticated = local_user_view.is_some();
|
let is_authenticated = local_user_view.is_some();
|
||||||
|
|
||||||
let res = if is_authenticated {
|
let res = if is_authenticated || cfg!(debug_assertions) {
|
||||||
// user is fully authenticated; allow remote lookups as well.
|
// user is fully authenticated; allow remote lookups as well.
|
||||||
search_query_to_object_id(data.q.clone(), &context).await
|
search_query_to_object_id(data.q.clone(), &context).await
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -122,7 +122,6 @@ pub async fn import_settings(
|
||||||
.settings
|
.settings
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|s| s.send_notifications_to_email),
|
.map(|s| s.send_notifications_to_email),
|
||||||
show_scores: data.settings.as_ref().map(|s| s.show_scores),
|
|
||||||
show_bot_accounts: data.settings.as_ref().map(|s| s.show_bot_accounts),
|
show_bot_accounts: data.settings.as_ref().map(|s| s.show_bot_accounts),
|
||||||
show_read_posts: data.settings.as_ref().map(|s| s.show_read_posts),
|
show_read_posts: data.settings.as_ref().map(|s| s.show_read_posts),
|
||||||
open_links_in_new_tab: data.settings.as_ref().map(|s| s.open_links_in_new_tab),
|
open_links_in_new_tab: data.settings.as_ref().map(|s| s.open_links_in_new_tab),
|
||||||
|
|
|
@ -11,7 +11,6 @@ use activitypub_federation::{
|
||||||
FEDERATION_CONTENT_TYPE,
|
FEDERATION_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
|
use actix_web::{web, web::Bytes, HttpRequest, HttpResponse};
|
||||||
use http::{header::LOCATION, StatusCode};
|
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::DbUrl,
|
newtypes::DbUrl,
|
||||||
|
@ -76,14 +75,14 @@ fn create_apub_tombstone_response<T: Into<Url>>(id: T) -> LemmyResult<HttpRespon
|
||||||
Ok(
|
Ok(
|
||||||
HttpResponse::Gone()
|
HttpResponse::Gone()
|
||||||
.content_type(FEDERATION_CONTENT_TYPE)
|
.content_type(FEDERATION_CONTENT_TYPE)
|
||||||
.status(StatusCode::GONE)
|
.status(actix_web::http::StatusCode::GONE)
|
||||||
.body(json),
|
.body(json),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn redirect_remote_object(url: &DbUrl) -> HttpResponse {
|
fn redirect_remote_object(url: &DbUrl) -> HttpResponse {
|
||||||
let mut res = HttpResponse::PermanentRedirect();
|
let mut res = HttpResponse::PermanentRedirect();
|
||||||
res.insert_header((LOCATION, url.as_str()));
|
res.insert_header((actix_web::http::header::LOCATION, url.as_str()));
|
||||||
res.finish()
|
res.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,11 @@ use lemmy_db_views_actor::structs::CommunityModeratorView;
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
error::{LemmyError, LemmyErrorType, LemmyResult},
|
error::{LemmyError, LemmyErrorType, LemmyResult},
|
||||||
spawn_try_task,
|
spawn_try_task,
|
||||||
utils::{markdown::markdown_to_html, slurs::check_slurs_opt, validation::is_valid_url},
|
utils::{
|
||||||
|
markdown::markdown_to_html,
|
||||||
|
slurs::check_slurs_opt,
|
||||||
|
validation::{is_url_blocked, is_valid_url},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
use stringreader::StringReader;
|
use stringreader::StringReader;
|
||||||
|
@ -180,8 +184,15 @@ impl Object for ApubPost {
|
||||||
let creator = page.creator()?.dereference(context).await?;
|
let creator = page.creator()?.dereference(context).await?;
|
||||||
let community = page.community(context).await?;
|
let community = page.community(context).await?;
|
||||||
if community.posting_restricted_to_mods {
|
if community.posting_restricted_to_mods {
|
||||||
CommunityModeratorView::is_community_moderator(&mut context.pool(), community.id, creator.id)
|
let is_mod = CommunityModeratorView::is_community_moderator(
|
||||||
|
&mut context.pool(),
|
||||||
|
community.id,
|
||||||
|
creator.id,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
if !is_mod {
|
||||||
|
Err(LemmyErrorType::OnlyModsCanPostInCommunity)?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
let mut name = page
|
let mut name = page
|
||||||
.name
|
.name
|
||||||
|
@ -220,14 +231,16 @@ impl Object for ApubPost {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let url_blocklist = get_url_blocklist(context).await?;
|
||||||
|
|
||||||
if let Some(url) = &url {
|
if let Some(url) = &url {
|
||||||
|
is_url_blocked(url, &url_blocklist)?;
|
||||||
is_valid_url(url)?;
|
is_valid_url(url)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let alt_text = first_attachment.cloned().and_then(Attachment::alt_text);
|
let alt_text = first_attachment.cloned().and_then(Attachment::alt_text);
|
||||||
|
|
||||||
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
let slur_regex = &local_site_opt_to_slur_regex(&local_site);
|
||||||
let url_blocklist = get_url_blocklist(context).await?;
|
|
||||||
|
|
||||||
let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source);
|
let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source);
|
||||||
let body = process_markdown_opt(&body, slur_regex, &url_blocklist, context).await?;
|
let body = process_markdown_opt(&body, slur_regex, &url_blocklist, context).await?;
|
||||||
|
|
|
@ -38,8 +38,6 @@ pub struct BlockUser {
|
||||||
pub(crate) remove_data: Option<bool>,
|
pub(crate) remove_data: Option<bool>,
|
||||||
/// block reason, written to mod log
|
/// block reason, written to mod log
|
||||||
pub(crate) summary: Option<String>,
|
pub(crate) summary: Option<String>,
|
||||||
/// TODO: deprecated
|
|
||||||
pub(crate) expires: Option<DateTime<Utc>>,
|
|
||||||
pub(crate) end_time: Option<DateTime<Utc>>,
|
pub(crate) end_time: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
||||||
community_outbox::ApubCommunityOutbox,
|
community_outbox::ApubCommunityOutbox,
|
||||||
},
|
},
|
||||||
local_site_data_cached,
|
local_site_data_cached,
|
||||||
objects::{community::ApubCommunity, read_from_string_or_source_opt, verify_is_remote_object},
|
objects::{community::ApubCommunity, read_from_string_or_source_opt},
|
||||||
protocol::{
|
protocol::{
|
||||||
objects::{Endpoints, LanguageTag},
|
objects::{Endpoints, LanguageTag},
|
||||||
ImageObject,
|
ImageObject,
|
||||||
|
@ -80,7 +80,6 @@ impl Group {
|
||||||
) -> LemmyResult<()> {
|
) -> LemmyResult<()> {
|
||||||
check_apub_id_valid_with_strictness(self.id.inner(), true, context).await?;
|
check_apub_id_valid_with_strictness(self.id.inner(), true, context).await?;
|
||||||
verify_domains_match(expected_domain, self.id.inner())?;
|
verify_domains_match(expected_domain, self.id.inner())?;
|
||||||
verify_is_remote_object(&self.id, context)?;
|
|
||||||
|
|
||||||
let local_site_data = local_site_data_cached(&mut context.pool()).await?;
|
let local_site_data = local_site_data_cached(&mut context.pool()).await?;
|
||||||
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
|
let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site);
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{CommunityId, PersonId},
|
newtypes::{CommunityId, PersonId},
|
||||||
schema::community_block::dsl::{community_block, community_id, person_id},
|
schema::{community, community_block},
|
||||||
source::community_block::{CommunityBlock, CommunityBlockForm},
|
source::{
|
||||||
|
community::Community,
|
||||||
|
community_block::{CommunityBlock, CommunityBlockForm},
|
||||||
|
},
|
||||||
traits::Blockable,
|
traits::Blockable,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
@ -9,6 +12,7 @@ use diesel::{
|
||||||
dsl::{exists, insert_into},
|
dsl::{exists, insert_into},
|
||||||
result::Error,
|
result::Error,
|
||||||
select,
|
select,
|
||||||
|
ExpressionMethods,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
};
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
@ -21,11 +25,27 @@ impl CommunityBlock {
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
select(exists(
|
select(exists(
|
||||||
community_block.find((for_person_id, for_community_id)),
|
community_block::table.find((for_person_id, for_community_id)),
|
||||||
))
|
))
|
||||||
.get_result(conn)
|
.get_result(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn for_person(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
person_id: PersonId,
|
||||||
|
) -> Result<Vec<Community>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
community_block::table
|
||||||
|
.inner_join(community::table)
|
||||||
|
.select(community::all_columns)
|
||||||
|
.filter(community_block::person_id.eq(person_id))
|
||||||
|
.filter(community::deleted.eq(false))
|
||||||
|
.filter(community::removed.eq(false))
|
||||||
|
.order_by(community_block::published)
|
||||||
|
.load::<Community>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -33,9 +53,9 @@ impl Blockable for CommunityBlock {
|
||||||
type Form = CommunityBlockForm;
|
type Form = CommunityBlockForm;
|
||||||
async fn block(pool: &mut DbPool<'_>, community_block_form: &Self::Form) -> Result<Self, Error> {
|
async fn block(pool: &mut DbPool<'_>, community_block_form: &Self::Form) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(community_block)
|
insert_into(community_block::table)
|
||||||
.values(community_block_form)
|
.values(community_block_form)
|
||||||
.on_conflict((person_id, community_id))
|
.on_conflict((community_block::person_id, community_block::community_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(community_block_form)
|
.set(community_block_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -46,7 +66,7 @@ impl Blockable for CommunityBlock {
|
||||||
community_block_form: &Self::Form,
|
community_block_form: &Self::Form,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::delete(community_block.find((
|
diesel::delete(community_block::table.find((
|
||||||
community_block_form.person_id,
|
community_block_form.person_id,
|
||||||
community_block_form.community_id,
|
community_block_form.community_id,
|
||||||
)))
|
)))
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{InstanceId, PersonId},
|
newtypes::{InstanceId, PersonId},
|
||||||
schema::instance_block::dsl::{instance_block, instance_id, person_id},
|
schema::{instance, instance_block},
|
||||||
source::instance_block::{InstanceBlock, InstanceBlockForm},
|
source::{
|
||||||
|
instance::Instance,
|
||||||
|
instance_block::{InstanceBlock, InstanceBlockForm},
|
||||||
|
},
|
||||||
traits::Blockable,
|
traits::Blockable,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
@ -9,6 +12,7 @@ use diesel::{
|
||||||
dsl::{exists, insert_into},
|
dsl::{exists, insert_into},
|
||||||
result::Error,
|
result::Error,
|
||||||
select,
|
select,
|
||||||
|
ExpressionMethods,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
};
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
@ -21,11 +25,25 @@ impl InstanceBlock {
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
select(exists(
|
select(exists(
|
||||||
instance_block.find((for_person_id, for_instance_id)),
|
instance_block::table.find((for_person_id, for_instance_id)),
|
||||||
))
|
))
|
||||||
.get_result(conn)
|
.get_result(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn for_person(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
person_id: PersonId,
|
||||||
|
) -> Result<Vec<Instance>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
instance_block::table
|
||||||
|
.inner_join(instance::table)
|
||||||
|
.select(instance::all_columns)
|
||||||
|
.filter(instance_block::person_id.eq(person_id))
|
||||||
|
.order_by(instance_block::published)
|
||||||
|
.load::<Instance>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -33,9 +51,9 @@ impl Blockable for InstanceBlock {
|
||||||
type Form = InstanceBlockForm;
|
type Form = InstanceBlockForm;
|
||||||
async fn block(pool: &mut DbPool<'_>, instance_block_form: &Self::Form) -> Result<Self, Error> {
|
async fn block(pool: &mut DbPool<'_>, instance_block_form: &Self::Form) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(instance_block)
|
insert_into(instance_block::table)
|
||||||
.values(instance_block_form)
|
.values(instance_block_form)
|
||||||
.on_conflict((person_id, instance_id))
|
.on_conflict((instance_block::person_id, instance_block::instance_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(instance_block_form)
|
.set(instance_block_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -46,7 +64,7 @@ impl Blockable for InstanceBlock {
|
||||||
instance_block_form: &Self::Form,
|
instance_block_form: &Self::Form,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::delete(instance_block.find((
|
diesel::delete(instance_block::table.find((
|
||||||
instance_block_form.person_id,
|
instance_block_form.person_id,
|
||||||
instance_block_form.instance_id,
|
instance_block_form.instance_id,
|
||||||
)))
|
)))
|
||||||
|
|
|
@ -115,11 +115,11 @@ impl LocalUser {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
// Make sure:
|
// Make sure:
|
||||||
// - The deny reason exists
|
// - An admin has interacted with the application
|
||||||
// - The app is older than a week
|
// - The app is older than a week
|
||||||
// - The accepted_application is false
|
// - The accepted_application is false
|
||||||
let old_denied_registrations = registration_application::table
|
let old_denied_registrations = registration_application::table
|
||||||
.filter(registration_application::deny_reason.is_not_null())
|
.filter(registration_application::admin_id.is_not_null())
|
||||||
.filter(registration_application::published.lt(now() - 1.week()))
|
.filter(registration_application::published.lt(now() - 1.week()))
|
||||||
.select(registration_application::local_user_id);
|
.select(registration_application::local_user_id);
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::PersonId,
|
newtypes::PersonId,
|
||||||
schema::person_block::dsl::{person_block, person_id, target_id},
|
schema::{person, person_block},
|
||||||
source::person_block::{PersonBlock, PersonBlockForm},
|
source::{
|
||||||
|
person::Person,
|
||||||
|
person_block::{PersonBlock, PersonBlockForm},
|
||||||
|
},
|
||||||
traits::Blockable,
|
traits::Blockable,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
};
|
};
|
||||||
|
@ -9,6 +12,8 @@ use diesel::{
|
||||||
dsl::{exists, insert_into},
|
dsl::{exists, insert_into},
|
||||||
result::Error,
|
result::Error,
|
||||||
select,
|
select,
|
||||||
|
ExpressionMethods,
|
||||||
|
JoinOnDsl,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
};
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
@ -20,10 +25,32 @@ impl PersonBlock {
|
||||||
for_recipient_id: PersonId,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<bool, Error> {
|
) -> Result<bool, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
select(exists(person_block.find((for_person_id, for_recipient_id))))
|
select(exists(
|
||||||
|
person_block::table.find((for_person_id, for_recipient_id)),
|
||||||
|
))
|
||||||
.get_result(conn)
|
.get_result(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn for_person(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
person_id: PersonId,
|
||||||
|
) -> Result<Vec<Person>, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
let target_person_alias = diesel::alias!(person as person1);
|
||||||
|
|
||||||
|
person_block::table
|
||||||
|
.inner_join(person::table.on(person_block::person_id.eq(person::id)))
|
||||||
|
.inner_join(
|
||||||
|
target_person_alias.on(person_block::target_id.eq(target_person_alias.field(person::id))),
|
||||||
|
)
|
||||||
|
.select(target_person_alias.fields(person::all_columns))
|
||||||
|
.filter(person_block::person_id.eq(person_id))
|
||||||
|
.filter(target_person_alias.field(person::deleted).eq(false))
|
||||||
|
.order_by(person_block::published)
|
||||||
|
.load::<Person>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
|
@ -34,9 +61,9 @@ impl Blockable for PersonBlock {
|
||||||
person_block_form: &PersonBlockForm,
|
person_block_form: &PersonBlockForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(person_block)
|
insert_into(person_block::table)
|
||||||
.values(person_block_form)
|
.values(person_block_form)
|
||||||
.on_conflict((person_id, target_id))
|
.on_conflict((person_block::person_id, person_block::target_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(person_block_form)
|
.set(person_block_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -44,7 +71,9 @@ impl Blockable for PersonBlock {
|
||||||
}
|
}
|
||||||
async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result<usize, Error> {
|
async fn unblock(pool: &mut DbPool<'_>, person_block_form: &Self::Form) -> Result<usize, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::delete(person_block.find((person_block_form.person_id, person_block_form.target_id)))
|
diesel::delete(
|
||||||
|
person_block::table.find((person_block_form.person_id, person_block_form.target_id)),
|
||||||
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
|
@ -446,7 +446,6 @@ diesel::table! {
|
||||||
interface_language -> Varchar,
|
interface_language -> Varchar,
|
||||||
show_avatars -> Bool,
|
show_avatars -> Bool,
|
||||||
send_notifications_to_email -> Bool,
|
send_notifications_to_email -> Bool,
|
||||||
show_scores -> Bool,
|
|
||||||
show_bot_accounts -> Bool,
|
show_bot_accounts -> Bool,
|
||||||
show_read_posts -> Bool,
|
show_read_posts -> Bool,
|
||||||
email_verified -> Bool,
|
email_verified -> Bool,
|
||||||
|
|
|
@ -2,7 +2,6 @@ use anyhow::Context;
|
||||||
use diesel::{connection::SimpleConnection, Connection, PgConnection};
|
use diesel::{connection::SimpleConnection, Connection, PgConnection};
|
||||||
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
|
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
use tracing::info;
|
|
||||||
|
|
||||||
const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
||||||
|
|
||||||
|
@ -34,7 +33,7 @@ pub fn run(db_url: &str) -> Result<(), LemmyError> {
|
||||||
// transaction as `REPLACEABLE_SCHEMA`. This code will be becone less hacky when the conditional
|
// transaction as `REPLACEABLE_SCHEMA`. This code will be becone less hacky when the conditional
|
||||||
// setup of things in `REPLACEABLE_SCHEMA` is done without using the number of pending
|
// setup of things in `REPLACEABLE_SCHEMA` is done without using the number of pending
|
||||||
// migrations.
|
// migrations.
|
||||||
info!("Running Database migrations (This may take a long time)...");
|
println!("Running Database migrations (This may take a long time)...");
|
||||||
let migrations = conn
|
let migrations = conn
|
||||||
.pending_migrations(MIGRATIONS)
|
.pending_migrations(MIGRATIONS)
|
||||||
.map_err(|e| anyhow::anyhow!("Couldn't determine pending migrations: {e}"))?;
|
.map_err(|e| anyhow::anyhow!("Couldn't determine pending migrations: {e}"))?;
|
||||||
|
@ -60,7 +59,7 @@ pub fn run(db_url: &str) -> Result<(), LemmyError> {
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})?;
|
})?;
|
||||||
info!("Database migrations complete.");
|
println!("Database migrations complete.");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,9 +35,6 @@ pub struct LocalUser {
|
||||||
/// Whether to show avatars.
|
/// Whether to show avatars.
|
||||||
pub show_avatars: bool,
|
pub show_avatars: bool,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: bool,
|
||||||
/// Whether to show comment / post scores.
|
|
||||||
// TODO now that there is a vote_display_mode, this can be gotten rid of in future releases.
|
|
||||||
pub show_scores: bool,
|
|
||||||
/// Whether to show bot accounts.
|
/// Whether to show bot accounts.
|
||||||
pub show_bot_accounts: bool,
|
pub show_bot_accounts: bool,
|
||||||
/// Whether to show read posts.
|
/// Whether to show read posts.
|
||||||
|
@ -93,8 +90,6 @@ pub struct LocalUserInsertForm {
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub show_bot_accounts: Option<bool>,
|
pub show_bot_accounts: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub show_scores: Option<bool>,
|
|
||||||
#[new(default)]
|
|
||||||
pub show_read_posts: Option<bool>,
|
pub show_read_posts: Option<bool>,
|
||||||
#[new(default)]
|
#[new(default)]
|
||||||
pub email_verified: Option<bool>,
|
pub email_verified: Option<bool>,
|
||||||
|
@ -138,7 +133,6 @@ pub struct LocalUserUpdateForm {
|
||||||
pub show_avatars: Option<bool>,
|
pub show_avatars: Option<bool>,
|
||||||
pub send_notifications_to_email: Option<bool>,
|
pub send_notifications_to_email: Option<bool>,
|
||||||
pub show_bot_accounts: Option<bool>,
|
pub show_bot_accounts: Option<bool>,
|
||||||
pub show_scores: Option<bool>,
|
|
||||||
pub show_read_posts: Option<bool>,
|
pub show_read_posts: Option<bool>,
|
||||||
pub email_verified: Option<bool>,
|
pub email_verified: Option<bool>,
|
||||||
pub accepted_application: Option<bool>,
|
pub accepted_application: Option<bool>,
|
||||||
|
|
|
@ -20,6 +20,7 @@ use typed_builder::TypedBuilder;
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
/// The vote display settings for your user.
|
/// The vote display settings for your user.
|
||||||
pub struct LocalUserVoteDisplayMode {
|
pub struct LocalUserVoteDisplayMode {
|
||||||
|
#[serde(skip)]
|
||||||
pub local_user_id: LocalUserId,
|
pub local_user_id: LocalUserId,
|
||||||
pub score: bool,
|
pub score: bool,
|
||||||
pub upvotes: bool,
|
pub upvotes: bool,
|
||||||
|
|
|
@ -196,7 +196,7 @@ impl CommentReportView {
|
||||||
queries().read(pool, (report_id, my_person_id)).await
|
queries().read(pool, (report_id, my_person_id)).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the current unresolved post report count for the communities you mod
|
/// Returns the current unresolved comment report count for the communities you mod
|
||||||
pub async fn get_report_count(
|
pub async fn get_report_count(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
my_person_id: PersonId,
|
my_person_id: PersonId,
|
||||||
|
|
|
@ -252,7 +252,6 @@ mod tests {
|
||||||
show_avatars: inserted_sara_local_user.show_avatars,
|
show_avatars: inserted_sara_local_user.show_avatars,
|
||||||
send_notifications_to_email: inserted_sara_local_user.send_notifications_to_email,
|
send_notifications_to_email: inserted_sara_local_user.send_notifications_to_email,
|
||||||
show_bot_accounts: inserted_sara_local_user.show_bot_accounts,
|
show_bot_accounts: inserted_sara_local_user.show_bot_accounts,
|
||||||
show_scores: inserted_sara_local_user.show_scores,
|
|
||||||
show_read_posts: inserted_sara_local_user.show_read_posts,
|
show_read_posts: inserted_sara_local_user.show_read_posts,
|
||||||
email_verified: inserted_sara_local_user.email_verified,
|
email_verified: inserted_sara_local_user.email_verified,
|
||||||
accepted_application: inserted_sara_local_user.accepted_application,
|
accepted_application: inserted_sara_local_user.accepted_application,
|
||||||
|
|
|
@ -1,24 +0,0 @@
|
||||||
use crate::structs::CommunityBlockView;
|
|
||||||
use diesel::{result::Error, ExpressionMethods, QueryDsl};
|
|
||||||
use diesel_async::RunQueryDsl;
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
newtypes::PersonId,
|
|
||||||
schema::{community, community_block, person},
|
|
||||||
utils::{get_conn, DbPool},
|
|
||||||
};
|
|
||||||
|
|
||||||
impl CommunityBlockView {
|
|
||||||
pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<Vec<Self>, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
community_block::table
|
|
||||||
.inner_join(person::table)
|
|
||||||
.inner_join(community::table)
|
|
||||||
.select((person::all_columns, community::all_columns))
|
|
||||||
.filter(community_block::person_id.eq(person_id))
|
|
||||||
.filter(community::deleted.eq(false))
|
|
||||||
.filter(community::removed.eq(false))
|
|
||||||
.order_by(community_block::published)
|
|
||||||
.load::<CommunityBlockView>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,27 +0,0 @@
|
||||||
use crate::structs::InstanceBlockView;
|
|
||||||
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, NullableExpressionMethods, QueryDsl};
|
|
||||||
use diesel_async::RunQueryDsl;
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
newtypes::PersonId,
|
|
||||||
schema::{instance, instance_block, person, site},
|
|
||||||
utils::{get_conn, DbPool},
|
|
||||||
};
|
|
||||||
|
|
||||||
impl InstanceBlockView {
|
|
||||||
pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<Vec<Self>, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
instance_block::table
|
|
||||||
.inner_join(person::table)
|
|
||||||
.inner_join(instance::table)
|
|
||||||
.left_join(site::table.on(site::instance_id.eq(instance::id)))
|
|
||||||
.select((
|
|
||||||
person::all_columns,
|
|
||||||
instance::all_columns,
|
|
||||||
site::all_columns.nullable(),
|
|
||||||
))
|
|
||||||
.filter(instance_block::person_id.eq(person_id))
|
|
||||||
.order_by(instance_block::published)
|
|
||||||
.load::<InstanceBlockView>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,8 +1,6 @@
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod comment_reply_view;
|
pub mod comment_reply_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod community_block_view;
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
pub mod community_follower_view;
|
pub mod community_follower_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod community_moderator_view;
|
pub mod community_moderator_view;
|
||||||
|
@ -11,10 +9,6 @@ pub mod community_person_ban_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod community_view;
|
pub mod community_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod instance_block_view;
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
pub mod person_block_view;
|
|
||||||
#[cfg(feature = "full")]
|
|
||||||
pub mod person_mention_view;
|
pub mod person_mention_view;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
pub mod person_view;
|
pub mod person_view;
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
use crate::structs::PersonBlockView;
|
|
||||||
use diesel::{result::Error, ExpressionMethods, JoinOnDsl, QueryDsl};
|
|
||||||
use diesel_async::RunQueryDsl;
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
newtypes::PersonId,
|
|
||||||
schema::{person, person_block},
|
|
||||||
utils::{get_conn, DbPool},
|
|
||||||
};
|
|
||||||
|
|
||||||
impl PersonBlockView {
|
|
||||||
pub async fn for_person(pool: &mut DbPool<'_>, person_id: PersonId) -> Result<Vec<Self>, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
let target_person_alias = diesel::alias!(person as person1);
|
|
||||||
|
|
||||||
person_block::table
|
|
||||||
.inner_join(person::table.on(person_block::person_id.eq(person::id)))
|
|
||||||
.inner_join(
|
|
||||||
target_person_alias.on(person_block::target_id.eq(target_person_alias.field(person::id))),
|
|
||||||
)
|
|
||||||
.select((
|
|
||||||
person::all_columns,
|
|
||||||
target_person_alias.fields(person::all_columns),
|
|
||||||
))
|
|
||||||
.filter(person_block::person_id.eq(person_id))
|
|
||||||
.filter(target_person_alias.field(person::deleted).eq(false))
|
|
||||||
.order_by(person_block::published)
|
|
||||||
.load::<PersonBlockView>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -6,11 +6,9 @@ use lemmy_db_schema::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
comment_reply::CommentReply,
|
comment_reply::CommentReply,
|
||||||
community::Community,
|
community::Community,
|
||||||
instance::Instance,
|
|
||||||
person::Person,
|
person::Person,
|
||||||
person_mention::PersonMention,
|
person_mention::PersonMention,
|
||||||
post::Post,
|
post::Post,
|
||||||
site::Site,
|
|
||||||
},
|
},
|
||||||
SubscribedType,
|
SubscribedType,
|
||||||
};
|
};
|
||||||
|
@ -19,28 +17,6 @@ use serde_with::skip_serializing_none;
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use ts_rs::TS;
|
use ts_rs::TS;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// A community block.
|
|
||||||
pub struct CommunityBlockView {
|
|
||||||
pub person: Person,
|
|
||||||
pub community: Community,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skip_serializing_none]
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// An instance block by a user.
|
|
||||||
pub struct InstanceBlockView {
|
|
||||||
pub person: Person,
|
|
||||||
pub instance: Instance,
|
|
||||||
pub site: Option<Site>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
@ -83,16 +59,6 @@ pub struct CommunityView {
|
||||||
pub banned_from_community: bool,
|
pub banned_from_community: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
|
||||||
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
|
||||||
#[cfg_attr(feature = "full", ts(export))]
|
|
||||||
/// A person block.
|
|
||||||
pub struct PersonBlockView {
|
|
||||||
pub person: Person,
|
|
||||||
pub target: Person,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[skip_serializing_none]
|
#[skip_serializing_none]
|
||||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||||
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
#[cfg_attr(feature = "full", derive(TS, Queryable))]
|
||||||
|
|
|
@ -32,7 +32,7 @@ serde_json.workspace = true
|
||||||
tokio = { workspace = true, features = ["full"] }
|
tokio = { workspace = true, features = ["full"] }
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
moka.workspace = true
|
moka.workspace = true
|
||||||
tokio-util = "0.7.11"
|
tokio-util = "0.7.12"
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
|
|
|
@ -459,7 +459,6 @@ mod test {
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
};
|
};
|
||||||
use lemmy_utils::error::LemmyResult;
|
use lemmy_utils::error::LemmyResult;
|
||||||
use reqwest::StatusCode;
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
use test_context::{test_context, AsyncTestContext};
|
use test_context::{test_context, AsyncTestContext};
|
||||||
|
@ -688,7 +687,7 @@ mod test {
|
||||||
|inbox_sender: actix_web::web::Data<UnboundedSender<String>>, body: String| async move {
|
|inbox_sender: actix_web::web::Data<UnboundedSender<String>>, body: String| async move {
|
||||||
tracing::debug!("received activity: {:?}", body);
|
tracing::debug!("received activity: {:?}", body);
|
||||||
inbox_sender.send(body.clone()).unwrap();
|
inbox_sender.send(body.clone()).unwrap();
|
||||||
HttpResponse::new(StatusCode::OK)
|
HttpResponse::new(actix_web::http::StatusCode::OK)
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
|
@ -32,5 +32,5 @@ serde = { workspace = true }
|
||||||
url = { workspace = true }
|
url = { workspace = true }
|
||||||
tracing = { workspace = true }
|
tracing = { workspace = true }
|
||||||
tokio = { workspace = true }
|
tokio = { workspace = true }
|
||||||
urlencoding = { workspace = true }
|
http.workspace = true
|
||||||
rss = "2.0.8"
|
rss = "2.0.9"
|
||||||
|
|
|
@ -2,6 +2,7 @@ use actix_web::{
|
||||||
body::BodyStream,
|
body::BodyStream,
|
||||||
http::{
|
http::{
|
||||||
header::{HeaderName, ACCEPT_ENCODING, HOST},
|
header::{HeaderName, ACCEPT_ENCODING, HOST},
|
||||||
|
Method,
|
||||||
StatusCode,
|
StatusCode,
|
||||||
},
|
},
|
||||||
web,
|
web,
|
||||||
|
@ -10,6 +11,7 @@ use actix_web::{
|
||||||
HttpResponse,
|
HttpResponse,
|
||||||
};
|
};
|
||||||
use futures::stream::{Stream, StreamExt};
|
use futures::stream::{Stream, StreamExt};
|
||||||
|
use http::HeaderValue;
|
||||||
use lemmy_api_common::{context::LemmyContext, request::PictrsResponse};
|
use lemmy_api_common::{context::LemmyContext, request::PictrsResponse};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
images::{LocalImage, LocalImageForm, RemoteImage},
|
images::{LocalImage, LocalImageForm, RemoteImage},
|
||||||
|
@ -22,7 +24,6 @@ use reqwest_middleware::{ClientWithMiddleware, RequestBuilder};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use urlencoding::decode;
|
|
||||||
|
|
||||||
pub fn config(
|
pub fn config(
|
||||||
cfg: &mut web::ServiceConfig,
|
cfg: &mut web::ServiceConfig,
|
||||||
|
@ -110,7 +111,7 @@ fn adapt_request(
|
||||||
const INVALID_HEADERS: &[HeaderName] = &[ACCEPT_ENCODING, HOST];
|
const INVALID_HEADERS: &[HeaderName] = &[ACCEPT_ENCODING, HOST];
|
||||||
|
|
||||||
let client_request = client
|
let client_request = client
|
||||||
.request(request.method().clone(), url)
|
.request(convert_method(request.method()), url)
|
||||||
.timeout(REQWEST_TIMEOUT);
|
.timeout(REQWEST_TIMEOUT);
|
||||||
|
|
||||||
request
|
request
|
||||||
|
@ -120,7 +121,8 @@ fn adapt_request(
|
||||||
if INVALID_HEADERS.contains(key) {
|
if INVALID_HEADERS.contains(key) {
|
||||||
client_req
|
client_req
|
||||||
} else {
|
} else {
|
||||||
client_req.header(key, value)
|
// TODO: remove as_str and as_bytes conversions after actix-web upgrades to http 1.0
|
||||||
|
client_req.header(key.as_str(), value.as_bytes())
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -167,7 +169,7 @@ async fn upload(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(HttpResponse::build(status).json(images))
|
Ok(HttpResponse::build(convert_status(status)).json(images))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn full_res(
|
async fn full_res(
|
||||||
|
@ -210,14 +212,14 @@ async fn image(
|
||||||
|
|
||||||
let res = client_req.send().await?;
|
let res = client_req.send().await?;
|
||||||
|
|
||||||
if res.status() == StatusCode::NOT_FOUND {
|
if res.status() == http::StatusCode::NOT_FOUND {
|
||||||
return Ok(HttpResponse::NotFound().finish());
|
return Ok(HttpResponse::NotFound().finish());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut client_res = HttpResponse::build(res.status());
|
let mut client_res = HttpResponse::build(StatusCode::from_u16(res.status().as_u16())?);
|
||||||
|
|
||||||
for (name, value) in res.headers().iter().filter(|(h, _)| *h != "connection") {
|
for (name, value) in res.headers().iter().filter(|(h, _)| *h != "connection") {
|
||||||
client_res.insert_header((name.clone(), value.clone()));
|
client_res.insert_header(convert_header(name, value));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(client_res.body(BodyStream::new(res.bytes_stream())))
|
Ok(client_res.body(BodyStream::new(res.bytes_stream())))
|
||||||
|
@ -246,7 +248,7 @@ async fn delete(
|
||||||
|
|
||||||
LocalImage::delete_by_alias(&mut context.pool(), &file).await?;
|
LocalImage::delete_by_alias(&mut context.pool(), &file).await?;
|
||||||
|
|
||||||
Ok(HttpResponse::build(res.status()).body(BodyStream::new(res.bytes_stream())))
|
Ok(HttpResponse::build(convert_status(res.status())).body(BodyStream::new(res.bytes_stream())))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn image_proxy(
|
pub async fn image_proxy(
|
||||||
|
@ -255,7 +257,7 @@ pub async fn image_proxy(
|
||||||
client: web::Data<ClientWithMiddleware>,
|
client: web::Data<ClientWithMiddleware>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> LemmyResult<HttpResponse> {
|
) -> LemmyResult<HttpResponse> {
|
||||||
let url = Url::parse(&decode(¶ms.url)?)?;
|
let url = Url::parse(¶ms.url)?;
|
||||||
|
|
||||||
// Check that url corresponds to a federated image so that this can't be abused as a proxy
|
// Check that url corresponds to a federated image so that this can't be abused as a proxy
|
||||||
// for arbitrary purposes.
|
// for arbitrary purposes.
|
||||||
|
@ -309,3 +311,14 @@ where
|
||||||
std::pin::Pin::new(&mut self.rx).poll_recv(cx)
|
std::pin::Pin::new(&mut self.rx).poll_recv(cx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove these conversions after actix-web upgrades to http 1.0
|
||||||
|
fn convert_status(status: http::StatusCode) -> StatusCode {
|
||||||
|
StatusCode::from_u16(status.as_u16()).expect("status can be converted")
|
||||||
|
}
|
||||||
|
fn convert_method(method: &Method) -> http::Method {
|
||||||
|
http::Method::from_bytes(method.as_str().as_bytes()).expect("method can be converted")
|
||||||
|
}
|
||||||
|
fn convert_header<'a>(name: &'a http::HeaderName, value: &'a HeaderValue) -> (&'a str, &'a [u8]) {
|
||||||
|
(name.as_str(), value.as_bytes())
|
||||||
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ async fn get_webfinger_response(
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
HttpResponse::Ok()
|
HttpResponse::Ok()
|
||||||
.content_type(&WEBFINGER_CONTENT_TYPE)
|
.content_type(WEBFINGER_CONTENT_TYPE.as_bytes())
|
||||||
.json(json),
|
.json(json),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,6 @@ full = [
|
||||||
"dep:actix-web",
|
"dep:actix-web",
|
||||||
"dep:serde_json",
|
"dep:serde_json",
|
||||||
"dep:anyhow",
|
"dep:anyhow",
|
||||||
"dep:tracing-error",
|
|
||||||
"dep:http",
|
"dep:http",
|
||||||
"dep:deser-hjson",
|
"dep:deser-hjson",
|
||||||
"dep:regex",
|
"dep:regex",
|
||||||
|
@ -53,7 +52,6 @@ full = [
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = { workspace = true, optional = true }
|
regex = { workspace = true, optional = true }
|
||||||
tracing = { workspace = true, optional = true }
|
tracing = { workspace = true, optional = true }
|
||||||
tracing-error = { workspace = true, optional = true }
|
|
||||||
itertools = { workspace = true, optional = true }
|
itertools = { workspace = true, optional = true }
|
||||||
serde = { workspace = true }
|
serde = { workspace = true }
|
||||||
serde_json = { workspace = true, optional = true }
|
serde_json = { workspace = true, optional = true }
|
||||||
|
@ -73,7 +71,7 @@ urlencoding = { workspace = true, optional = true }
|
||||||
html2text = { version = "0.12.5", optional = true }
|
html2text = { version = "0.12.5", optional = true }
|
||||||
deser-hjson = { version = "2.2.4", optional = true }
|
deser-hjson = { version = "2.2.4", optional = true }
|
||||||
smart-default = { version = "0.7.1", optional = true }
|
smart-default = { version = "0.7.1", optional = true }
|
||||||
lettre = { version = "0.11.7", default-features = false, features = [
|
lettre = { version = "0.11.8", default-features = false, features = [
|
||||||
"builder",
|
"builder",
|
||||||
"tokio1",
|
"tokio1",
|
||||||
"tokio1-rustls-tls",
|
"tokio1-rustls-tls",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::fmt::Debug;
|
use std::{backtrace::Backtrace, fmt::Debug};
|
||||||
use strum::{Display, EnumIter};
|
use strum::{Display, EnumIter};
|
||||||
|
|
||||||
#[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, EnumIter, Hash)]
|
#[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, EnumIter, Hash)]
|
||||||
|
@ -186,14 +186,13 @@ pub enum LemmyErrorType {
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(feature = "full")] {
|
if #[cfg(feature = "full")] {
|
||||||
|
|
||||||
use tracing_error::SpanTrace;
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
pub type LemmyResult<T> = Result<T, LemmyError>;
|
pub type LemmyResult<T> = Result<T, LemmyError>;
|
||||||
|
|
||||||
pub struct LemmyError {
|
pub struct LemmyError {
|
||||||
pub error_type: LemmyErrorType,
|
pub error_type: LemmyErrorType,
|
||||||
pub inner: anyhow::Error,
|
pub inner: anyhow::Error,
|
||||||
pub context: SpanTrace,
|
pub context: Backtrace,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]]
|
/// Maximum number of items in an array passed as API parameter. See [[LemmyErrorType::TooManyItems]]
|
||||||
|
@ -208,7 +207,7 @@ cfg_if! {
|
||||||
LemmyError {
|
LemmyError {
|
||||||
error_type: LemmyErrorType::Unknown(format!("{}", &cause)),
|
error_type: LemmyErrorType::Unknown(format!("{}", &cause)),
|
||||||
inner: cause,
|
inner: cause,
|
||||||
context: SpanTrace::capture(),
|
context: Backtrace::capture(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,13 +231,13 @@ cfg_if! {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl actix_web::error::ResponseError for LemmyError {
|
impl actix_web::error::ResponseError for LemmyError {
|
||||||
fn status_code(&self) -> http::StatusCode {
|
fn status_code(&self) -> actix_web::http::StatusCode {
|
||||||
if self.error_type == LemmyErrorType::IncorrectLogin {
|
if self.error_type == LemmyErrorType::IncorrectLogin {
|
||||||
return http::StatusCode::UNAUTHORIZED;
|
return actix_web::http::StatusCode::UNAUTHORIZED;
|
||||||
}
|
}
|
||||||
match self.inner.downcast_ref::<diesel::result::Error>() {
|
match self.inner.downcast_ref::<diesel::result::Error>() {
|
||||||
Some(diesel::result::Error::NotFound) => http::StatusCode::NOT_FOUND,
|
Some(diesel::result::Error::NotFound) => actix_web::http::StatusCode::NOT_FOUND,
|
||||||
_ => http::StatusCode::BAD_REQUEST,
|
_ => actix_web::http::StatusCode::BAD_REQUEST,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +252,7 @@ cfg_if! {
|
||||||
LemmyError {
|
LemmyError {
|
||||||
error_type,
|
error_type,
|
||||||
inner,
|
inner,
|
||||||
context: SpanTrace::capture(),
|
context: Backtrace::capture(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,7 +266,7 @@ cfg_if! {
|
||||||
self.map_err(|error| LemmyError {
|
self.map_err(|error| LemmyError {
|
||||||
error_type,
|
error_type,
|
||||||
inner: error.into(),
|
inner: error.into(),
|
||||||
context: SpanTrace::capture(),
|
context: Backtrace::capture(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ mod tests {
|
||||||
use crate::error::{LemmyError, LemmyErrorType};
|
use crate::error::{LemmyError, LemmyErrorType};
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
error::ErrorInternalServerError,
|
error::ErrorInternalServerError,
|
||||||
|
http::StatusCode,
|
||||||
middleware::ErrorHandlers,
|
middleware::ErrorHandlers,
|
||||||
test,
|
test,
|
||||||
web,
|
web,
|
||||||
|
@ -45,7 +46,6 @@ mod tests {
|
||||||
Handler,
|
Handler,
|
||||||
Responder,
|
Responder,
|
||||||
};
|
};
|
||||||
use http::StatusCode;
|
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
#[actix_web::test]
|
#[actix_web::test]
|
||||||
|
|
|
@ -20,7 +20,7 @@ const ALLOWED_POST_URL_SCHEMES: [&str; 3] = ["http", "https", "magnet"];
|
||||||
|
|
||||||
const BODY_MAX_LENGTH: usize = 10000;
|
const BODY_MAX_LENGTH: usize = 10000;
|
||||||
const POST_BODY_MAX_LENGTH: usize = 50000;
|
const POST_BODY_MAX_LENGTH: usize = 50000;
|
||||||
const BIO_MAX_LENGTH: usize = 300;
|
const BIO_MAX_LENGTH: usize = 1000;
|
||||||
const URL_MAX_LENGTH: usize = 2000;
|
const URL_MAX_LENGTH: usize = 2000;
|
||||||
const ALT_TEXT_MAX_LENGTH: usize = 1500;
|
const ALT_TEXT_MAX_LENGTH: usize = 1500;
|
||||||
const SITE_NAME_MAX_LENGTH: usize = 20;
|
const SITE_NAME_MAX_LENGTH: usize = 20;
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 179f6884398d3536d16382df5dc40da4e47835aa
|
Subproject commit 7adddded581fcd965ab33b91c5fe10e0d7247208
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE local_user
|
||||||
|
ADD COLUMN show_scores boolean NOT NULL DEFAULT TRUE;
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
ALTER TABLE local_user
|
||||||
|
DROP COLUMN show_scores;
|
||||||
|
|
|
@ -6,7 +6,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
source scripts/start_dev_db.sh
|
source scripts/start_dev_db.sh
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
source scripts/start_dev_db.sh
|
source scripts/start_dev_db.sh
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
# Format rust files
|
# Format rust files
|
||||||
cargo +nightly fmt
|
cargo +nightly fmt
|
||||||
|
|
|
@ -8,7 +8,7 @@ third_semver=$(echo $new_tag | cut -d "." -f 3)
|
||||||
|
|
||||||
# Goto the upper route
|
# Goto the upper route
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
# The docker installs should only update for non release-candidates
|
# The docker installs should only update for non release-candidates
|
||||||
# IE, when the third semver is a number, not '2-rc'
|
# IE, when the third semver is a number, not '2-rc'
|
||||||
|
|
|
@ -5,7 +5,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
# Copy the files to a temp dir
|
# Copy the files to a temp dir
|
||||||
TMP_DIR=$(mktemp -d)
|
TMP_DIR=$(mktemp -d)
|
||||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
PACKAGE="$1"
|
PACKAGE="$1"
|
||||||
echo "$PACKAGE"
|
echo "$PACKAGE"
|
||||||
|
|
|
@ -3,7 +3,7 @@ set -e
|
||||||
|
|
||||||
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)"
|
||||||
|
|
||||||
cd $CWD/../
|
cd "$CWD/../"
|
||||||
|
|
||||||
PACKAGE="$1"
|
PACKAGE="$1"
|
||||||
TEST="$2"
|
TEST="$2"
|
||||||
|
|
57
src/lib.rs
57
src/lib.rs
|
@ -1,17 +1,10 @@
|
||||||
pub mod api_routes_http;
|
pub mod api_routes_http;
|
||||||
pub mod code_migrations;
|
pub mod code_migrations;
|
||||||
pub mod prometheus_metrics;
|
pub mod prometheus_metrics;
|
||||||
pub mod root_span_builder;
|
|
||||||
pub mod scheduled_tasks;
|
pub mod scheduled_tasks;
|
||||||
pub mod session_middleware;
|
pub mod session_middleware;
|
||||||
#[cfg(feature = "console")]
|
|
||||||
pub mod telemetry;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{code_migrations::run_advanced_migrations, session_middleware::SessionMiddleware};
|
||||||
code_migrations::run_advanced_migrations,
|
|
||||||
root_span_builder::QuieterRootSpanBuilder,
|
|
||||||
session_middleware::SessionMiddleware,
|
|
||||||
};
|
|
||||||
use activitypub_federation::config::{FederationConfig, FederationMiddleware};
|
use activitypub_federation::config::{FederationConfig, FederationMiddleware};
|
||||||
use actix_cors::Cors;
|
use actix_cors::Cors;
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
|
@ -55,14 +48,9 @@ use prometheus_metrics::serve_prometheus;
|
||||||
use reqwest_middleware::ClientBuilder;
|
use reqwest_middleware::ClientBuilder;
|
||||||
use reqwest_tracing::TracingMiddleware;
|
use reqwest_tracing::TracingMiddleware;
|
||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::{env, ops::Deref, time::Duration};
|
use std::{ops::Deref, time::Duration};
|
||||||
use tokio::signal::unix::SignalKind;
|
use tokio::signal::unix::SignalKind;
|
||||||
use tracing::subscriber::set_global_default;
|
use tracing_actix_web::{DefaultRootSpanBuilder, TracingLogger};
|
||||||
use tracing_actix_web::TracingLogger;
|
|
||||||
use tracing_error::ErrorLayer;
|
|
||||||
use tracing_log::LogTracer;
|
|
||||||
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, Layer, Registry};
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
/// Timeout for HTTP requests while sending activities. A longer timeout provides better
|
/// Timeout for HTTP requests while sending activities. A longer timeout provides better
|
||||||
/// compatibility with other ActivityPub software that might allocate more time for synchronous
|
/// compatibility with other ActivityPub software that might allocate more time for synchronous
|
||||||
|
@ -119,7 +107,7 @@ pub struct CmdArgs {
|
||||||
/// Placing the main function in lib.rs allows other crates to import it and embed Lemmy
|
/// Placing the main function in lib.rs allows other crates to import it and embed Lemmy
|
||||||
pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
||||||
// Print version number to log
|
// Print version number to log
|
||||||
println!("Lemmy v{VERSION}");
|
println!("Starting Lemmy v{VERSION}");
|
||||||
|
|
||||||
// return error 503 while running db migrations and startup tasks
|
// return error 503 while running db migrations and startup tasks
|
||||||
let mut startup_server_handle = None;
|
let mut startup_server_handle = None;
|
||||||
|
@ -318,7 +306,7 @@ fn create_http_server(
|
||||||
))
|
))
|
||||||
.wrap(middleware::Compress::default())
|
.wrap(middleware::Compress::default())
|
||||||
.wrap(cors_config)
|
.wrap(cors_config)
|
||||||
.wrap(TracingLogger::<QuieterRootSpanBuilder>::new())
|
.wrap(TracingLogger::<DefaultRootSpanBuilder>::new())
|
||||||
.wrap(ErrorHandlers::new().default_handler(jsonify_plain_text_errors))
|
.wrap(ErrorHandlers::new().default_handler(jsonify_plain_text_errors))
|
||||||
.app_data(Data::new(context.clone()))
|
.app_data(Data::new(context.clone()))
|
||||||
.app_data(Data::new(rate_limit_cell.clone()))
|
.app_data(Data::new(rate_limit_cell.clone()))
|
||||||
|
@ -373,38 +361,3 @@ fn cors_config(settings: &Settings) -> Cors {
|
||||||
.max_age(3600),
|
.max_age(3600),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn init_logging(opentelemetry_url: &Option<Url>) -> LemmyResult<()> {
|
|
||||||
LogTracer::init()?;
|
|
||||||
|
|
||||||
let log_description = env::var("RUST_LOG").unwrap_or_else(|_| "info".into());
|
|
||||||
|
|
||||||
let targets = log_description
|
|
||||||
.trim()
|
|
||||||
.trim_matches('"')
|
|
||||||
.parse::<Targets>()?;
|
|
||||||
|
|
||||||
let format_layer = {
|
|
||||||
#[cfg(feature = "json-log")]
|
|
||||||
let layer = tracing_subscriber::fmt::layer().with_ansi(false).json();
|
|
||||||
#[cfg(not(feature = "json-log"))]
|
|
||||||
let layer = tracing_subscriber::fmt::layer().with_ansi(false);
|
|
||||||
|
|
||||||
layer.with_filter(targets.clone())
|
|
||||||
};
|
|
||||||
|
|
||||||
let subscriber = Registry::default()
|
|
||||||
.with(format_layer)
|
|
||||||
.with(ErrorLayer::default());
|
|
||||||
|
|
||||||
if let Some(_url) = opentelemetry_url {
|
|
||||||
#[cfg(feature = "console")]
|
|
||||||
telemetry::init_tracing(_url.as_ref(), subscriber, targets)?;
|
|
||||||
#[cfg(not(feature = "console"))]
|
|
||||||
tracing::error!("Feature `console` must be enabled for opentelemetry tracing");
|
|
||||||
} else {
|
|
||||||
set_global_default(subscriber)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
12
src/main.rs
12
src/main.rs
|
@ -1,12 +1,18 @@
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use lemmy_server::{init_logging, start_lemmy_server, CmdArgs};
|
use lemmy_server::{start_lemmy_server, CmdArgs};
|
||||||
use lemmy_utils::{error::LemmyResult, settings::SETTINGS};
|
use lemmy_utils::error::LemmyResult;
|
||||||
|
use tracing::level_filters::LevelFilter;
|
||||||
|
use tracing_subscriber::EnvFilter;
|
||||||
|
|
||||||
pub extern crate rustls;
|
pub extern crate rustls;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
pub async fn main() -> LemmyResult<()> {
|
pub async fn main() -> LemmyResult<()> {
|
||||||
init_logging(&SETTINGS.opentelemetry_url)?;
|
let filter = EnvFilter::builder()
|
||||||
|
.with_default_directive(LevelFilter::INFO.into())
|
||||||
|
.from_env_lossy();
|
||||||
|
tracing_subscriber::fmt().with_env_filter(filter).init();
|
||||||
|
|
||||||
let args = CmdArgs::parse();
|
let args = CmdArgs::parse();
|
||||||
|
|
||||||
rustls::crypto::ring::default_provider()
|
rustls::crypto::ring::default_provider()
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
use actix_web::{http::StatusCode, ResponseError};
|
|
||||||
use tracing::Span;
|
|
||||||
use tracing_actix_web::RootSpanBuilder;
|
|
||||||
|
|
||||||
// Code in this module adapted from DefaultRootSpanBuilder
|
|
||||||
// https://github.com/LukeMathWalker/tracing-actix-web/blob/main/src/root_span_builder.rs
|
|
||||||
// and root_span!
|
|
||||||
// https://github.com/LukeMathWalker/tracing-actix-web/blob/main/src/root_span_macro.rs
|
|
||||||
|
|
||||||
pub struct QuieterRootSpanBuilder;
|
|
||||||
|
|
||||||
impl RootSpanBuilder for QuieterRootSpanBuilder {
|
|
||||||
fn on_request_start(request: &actix_web::dev::ServiceRequest) -> Span {
|
|
||||||
let request_id = tracing_actix_web::root_span_macro::private::get_request_id(request);
|
|
||||||
|
|
||||||
tracing::info_span!(
|
|
||||||
"HTTP request",
|
|
||||||
http.method = %request.method(),
|
|
||||||
http.scheme = request.connection_info().scheme(),
|
|
||||||
http.host = %request.connection_info().host(),
|
|
||||||
http.target = %request.uri().path(),
|
|
||||||
http.status_code = tracing::field::Empty,
|
|
||||||
otel.kind = "server",
|
|
||||||
otel.status_code = tracing::field::Empty,
|
|
||||||
trace_id = tracing::field::Empty,
|
|
||||||
request_id = %request_id,
|
|
||||||
exception.message = tracing::field::Empty,
|
|
||||||
// Not proper OpenTelemetry, but their terminology is fairly exception-centric
|
|
||||||
exception.details = tracing::field::Empty,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn on_request_end<B>(
|
|
||||||
span: tracing::Span,
|
|
||||||
outcome: &Result<actix_web::dev::ServiceResponse<B>, actix_web::Error>,
|
|
||||||
) {
|
|
||||||
match &outcome {
|
|
||||||
Ok(response) => {
|
|
||||||
if let Some(error) = response.response().error() {
|
|
||||||
// use the status code already constructed for the outgoing HTTP response
|
|
||||||
handle_error(span, response.status(), error.as_response_error());
|
|
||||||
} else {
|
|
||||||
let code: i32 = response.response().status().as_u16().into();
|
|
||||||
span.record("http.status_code", code);
|
|
||||||
span.record("otel.status_code", "OK");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Err(error) => {
|
|
||||||
let response_error = error.as_response_error();
|
|
||||||
handle_error(span, response_error.status_code(), response_error);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_error(span: Span, status_code: StatusCode, response_error: &dyn ResponseError) {
|
|
||||||
let code: i32 = status_code.as_u16().into();
|
|
||||||
|
|
||||||
span.record("http.status_code", code);
|
|
||||||
|
|
||||||
if status_code.is_client_error() {
|
|
||||||
span.record("otel.status_code", "OK");
|
|
||||||
} else {
|
|
||||||
span.record("otel.status_code", "ERROR");
|
|
||||||
}
|
|
||||||
|
|
||||||
// pre-formatting errors is a workaround for https://github.com/tokio-rs/tracing/issues/1565
|
|
||||||
let display_error = format!("{response_error}");
|
|
||||||
|
|
||||||
tracing::info_span!(
|
|
||||||
parent: None,
|
|
||||||
"Error encountered while processing the incoming HTTP request"
|
|
||||||
)
|
|
||||||
.in_scope(|| {
|
|
||||||
if status_code.is_client_error() {
|
|
||||||
tracing::warn!("{}", display_error);
|
|
||||||
} else {
|
|
||||||
tracing::error!("{}", display_error);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
span.record("exception.message", tracing::field::display(display_error));
|
|
||||||
}
|
|
|
@ -1,7 +1,7 @@
|
||||||
use actix_web::{
|
use actix_web::{
|
||||||
body::MessageBody,
|
body::MessageBody,
|
||||||
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
|
dev::{forward_ready, Service, ServiceRequest, ServiceResponse, Transform},
|
||||||
http::header::CACHE_CONTROL,
|
http::header::{HeaderValue, CACHE_CONTROL},
|
||||||
Error,
|
Error,
|
||||||
HttpMessage,
|
HttpMessage,
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ use core::future::Ready;
|
||||||
use futures_util::future::LocalBoxFuture;
|
use futures_util::future::LocalBoxFuture;
|
||||||
use lemmy_api::{local_user_view_from_jwt, read_auth_token};
|
use lemmy_api::{local_user_view_from_jwt, read_auth_token};
|
||||||
use lemmy_api_common::context::LemmyContext;
|
use lemmy_api_common::context::LemmyContext;
|
||||||
use reqwest::header::HeaderValue;
|
|
||||||
use std::{future::ready, rc::Rc};
|
use std::{future::ready, rc::Rc};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
use console_subscriber::ConsoleLayer;
|
|
||||||
use lemmy_utils::error::LemmyResult;
|
|
||||||
use opentelemetry::{
|
|
||||||
sdk::{propagation::TraceContextPropagator, Resource},
|
|
||||||
KeyValue,
|
|
||||||
};
|
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
|
||||||
use tracing::{subscriber::set_global_default, Subscriber};
|
|
||||||
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, registry::LookupSpan, Layer};
|
|
||||||
|
|
||||||
pub fn init_tracing<S>(opentelemetry_url: &str, subscriber: S, targets: Targets) -> LemmyResult<()>
|
|
||||||
where
|
|
||||||
S: Subscriber + for<'a> LookupSpan<'a> + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
opentelemetry::global::set_text_map_propagator(TraceContextPropagator::new());
|
|
||||||
|
|
||||||
let console_layer = ConsoleLayer::builder()
|
|
||||||
.with_default_env()
|
|
||||||
.server_addr(([0, 0, 0, 0], 6669))
|
|
||||||
.event_buffer_capacity(1024 * 1024)
|
|
||||||
.spawn();
|
|
||||||
|
|
||||||
let subscriber = subscriber.with(console_layer);
|
|
||||||
|
|
||||||
let tracer = opentelemetry_otlp::new_pipeline()
|
|
||||||
.tracing()
|
|
||||||
.with_trace_config(
|
|
||||||
opentelemetry::sdk::trace::config()
|
|
||||||
.with_resource(Resource::new(vec![KeyValue::new("service.name", "lemmy")])),
|
|
||||||
)
|
|
||||||
.with_exporter(
|
|
||||||
opentelemetry_otlp::new_exporter()
|
|
||||||
.tonic()
|
|
||||||
.with_endpoint(opentelemetry_url),
|
|
||||||
)
|
|
||||||
.install_batch(opentelemetry::runtime::Tokio)?;
|
|
||||||
|
|
||||||
let otel_layer = tracing_opentelemetry::layer()
|
|
||||||
.with_tracer(tracer)
|
|
||||||
.with_filter(targets);
|
|
||||||
|
|
||||||
let subscriber = subscriber.with(otel_layer);
|
|
||||||
|
|
||||||
set_global_default(subscriber)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
Loading…
Reference in a new issue