mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 22e7617362 | |||
| b7b7d3a9e7 | |||
| 1c59b41ff1 | |||
| 2d9bdc0979 | |||
| 5486dbda24 | |||
| 41581c9ae8 | |||
| d3022b4112 | |||
| 6920814da9 | |||
| fe7963d306 | |||
| 84445b8458 | |||
| 9e62076baa | |||
| 0eb9e4f3d2 | |||
| e71138ab6f | |||
| 8e7373c027 | |||
| 576a783a6f | |||
| 21ec255159 | |||
| 3c5bbd4f05 | |||
| 4f8fec7e5a | |||
| fb3020d8da | |||
| ecf20f7ebb | |||
| b3e5d2f683 | |||
| 83126cc667 | |||
| eac713a2a9 | |||
| e8a64bb59d | |||
| 05e65936fa | |||
| e7c3f78377 | |||
| d8b56c9c35 | |||
| 75fb19a5ca | |||
| d98ec6bf46 | |||
| 1b1198771f | |||
| d4561e950b | |||
| 298e2af3d7 | |||
| c5b99fbccd | |||
| 2e6ec2f89c | |||
| b16e26952a | |||
| 9e0530839d | |||
| d85aaabe9e | |||
| 71d2421f55 | |||
| fb793e8315 | |||
| 10947f6f1a | |||
| 93253237e9 | |||
| 0ac1ce9996 | |||
| 3ced2e2f90 | |||
| 70cee36041 | |||
| cacaa6c512 | |||
| 6b92e96582 | |||
| dc599db19c | |||
| 3a95585f0e | |||
| 68d68a0645 | |||
| 773c3d457b | |||
| b91af70e0b | |||
| 538347204f | |||
| 90880e2689 | |||
| f76f669d16 | |||
| dad407fb22 | |||
| 17a04940fc | |||
| 6e5392c2f5 | |||
| 57779df66a | |||
| 35bffa5970 | |||
| 4f9e9174e2 | |||
| 3e54c7e691 | |||
| 57d26dae0d | |||
| e054a56b32 |
@@ -36,9 +36,13 @@ jobs:
|
||||
- name: Prepare static files for deployment
|
||||
run: |
|
||||
mkdir -p ./public/.well-known/matrix
|
||||
mkdir -p ./public/.well-known/continuwuity
|
||||
mkdir -p ./public/schema
|
||||
# Copy the Matrix .well-known files
|
||||
cp ./docs/static/server ./public/.well-known/matrix/server
|
||||
cp ./docs/static/client ./public/.well-known/matrix/client
|
||||
cp ./docs/static/announcements.json ./public/.well-known/continuwuity/announcements
|
||||
cp ./docs/static/announcements.schema.json ./public/schema/announcements.schema.json
|
||||
# Copy the custom headers file
|
||||
cp ./docs/static/_headers ./public/_headers
|
||||
echo "Copied .well-known files and _headers to ./public"
|
||||
|
||||
@@ -89,7 +89,13 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- run: |
|
||||
if ! command -v rustup &> /dev/null ; then
|
||||
curl --proto '=https' --tlsv1.2 --retry 10 --retry-connrefused -fsSL "https://sh.rustup.rs" | sh -s -- --default-toolchain none -y
|
||||
echo "${CARGO_HOME:-$HOME/.cargo}/bin" >> $GITHUB_PATH
|
||||
fi
|
||||
- uses: https://github.com/cargo-bins/cargo-binstall@main
|
||||
- run: cargo binstall timelord-cli@3.0.1
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Set up QEMU
|
||||
@@ -123,6 +129,18 @@ jobs:
|
||||
echo "COMMIT_SHORT_SHA=$calculatedSha" >> $GITHUB_ENV
|
||||
- name: Get Git commit timestamps
|
||||
run: echo "TIMESTAMP=$(git log -1 --pretty=%ct)" >> $GITHUB_ENV
|
||||
- name: Set up timelord
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: /timelord/
|
||||
key: timelord-v0 # Cache is already split per runner
|
||||
- name: Run timelord to set timestamps
|
||||
run: timelord sync --source-dir . --cache-dir /timelord/
|
||||
- name: Save timelord
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: /timelord/
|
||||
key: timelord-v0
|
||||
- name: Build and push Docker image by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
|
||||
Generated
+19
-19
@@ -725,7 +725,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"conduwuit_admin",
|
||||
@@ -754,7 +754,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_admin"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"conduwuit_api",
|
||||
@@ -775,7 +775,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_api"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"axum",
|
||||
@@ -807,7 +807,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_core"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"argon2",
|
||||
"arrayvec",
|
||||
@@ -865,7 +865,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_database"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"async-channel",
|
||||
"conduwuit_core",
|
||||
@@ -883,7 +883,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_macros"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"itertools 0.14.0",
|
||||
"proc-macro2",
|
||||
@@ -893,7 +893,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_router"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-client-ip",
|
||||
@@ -926,7 +926,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "conduwuit_service"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64 0.22.1",
|
||||
@@ -3652,7 +3652,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma"
|
||||
version = "0.10.1"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"assign",
|
||||
"js_int",
|
||||
@@ -3672,7 +3672,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-appservice-api"
|
||||
version = "0.10.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -3684,7 +3684,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-client-api"
|
||||
version = "0.18.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"assign",
|
||||
@@ -3707,7 +3707,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-common"
|
||||
version = "0.13.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"base64 0.22.1",
|
||||
@@ -3739,7 +3739,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-events"
|
||||
version = "0.28.1"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"as_variant",
|
||||
"indexmap 2.8.0",
|
||||
@@ -3764,7 +3764,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-federation-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"headers",
|
||||
@@ -3786,7 +3786,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-identifiers-validation"
|
||||
version = "0.9.5"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"thiserror 2.0.12",
|
||||
@@ -3795,7 +3795,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-identity-service-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -3805,7 +3805,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-macros"
|
||||
version = "0.13.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro-crate",
|
||||
@@ -3820,7 +3820,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-push-gateway-api"
|
||||
version = "0.9.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"js_int",
|
||||
"ruma-common",
|
||||
@@ -3832,7 +3832,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "ruma-signatures"
|
||||
version = "0.15.0"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=920148dca1076454ca0ca5d43b5ce1aa708381d4#920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=fa3c868e5a1c049dc9472310dc4955289a96bb35#fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"ed25519-dalek",
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ license = "Apache-2.0"
|
||||
readme = "README.md"
|
||||
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
||||
rust-version = "1.86.0"
|
||||
version = "0.5.0"
|
||||
version = "0.5.0-rc.5"
|
||||
|
||||
[workspace.metadata.crane]
|
||||
name = "conduwuit"
|
||||
@@ -350,7 +350,7 @@ version = "0.1.2"
|
||||
[workspace.dependencies.ruma]
|
||||
git = "https://forgejo.ellis.link/continuwuation/ruwuma"
|
||||
#branch = "conduwuit-changes"
|
||||
rev = "920148dca1076454ca0ca5d43b5ce1aa708381d4"
|
||||
rev = "fa3c868e5a1c049dc9472310dc4955289a96bb35"
|
||||
features = [
|
||||
"compat",
|
||||
"rand",
|
||||
|
||||
@@ -111,4 +111,3 @@ When incorporating code from other forks:
|
||||
|
||||
|
||||
[continuwuity]: https://forgejo.ellis.link/continuwuation/continuwuity
|
||||
|
||||
|
||||
+26
-3
@@ -112,6 +112,12 @@
|
||||
#
|
||||
#new_user_displayname_suffix = "🏳️⚧️"
|
||||
|
||||
# If enabled, conduwuit will send a simple GET request periodically to
|
||||
# `https://continuwuity.org/.well-known/continuwuity/announcements` for any new
|
||||
# announcements or major updates. This is not an update check endpoint.
|
||||
#
|
||||
#allow_announcements_check =
|
||||
|
||||
# Set this to any float value to multiply conduwuit's in-memory LRU caches
|
||||
# with such as "auth_chain_cache_capacity".
|
||||
#
|
||||
@@ -960,8 +966,8 @@
|
||||
#
|
||||
#rocksdb_compaction_ioprio_idle = true
|
||||
|
||||
# Disables RocksDB compaction. You should never ever have to set this
|
||||
# option to true. If you for some reason find yourself needing to use this
|
||||
# Enables RocksDB compaction. You should never ever have to set this
|
||||
# option to false. If you for some reason find yourself needing to use this
|
||||
# option as part of troubleshooting or a bug, please reach out to us in
|
||||
# the conduwuit Matrix room with information and details.
|
||||
#
|
||||
@@ -1187,16 +1193,33 @@
|
||||
# incoming AND outgoing federation with, and block client room joins /
|
||||
# remote user invites.
|
||||
#
|
||||
# Additionally, it will hide messages from these servers for all users
|
||||
# on this server.
|
||||
#
|
||||
# Note that your messages can still make it to forbidden servers through
|
||||
# backfilling. Events we receive from forbidden servers via backfill will
|
||||
# be stored in the database, but will not be sent to the client.
|
||||
#
|
||||
# This check is applied on the room ID, room alias, sender server name,
|
||||
# sender user's server name, inbound federation X-Matrix origin, and
|
||||
# outbound federation handler.
|
||||
#
|
||||
# Basically "global" ACLs.
|
||||
# You can set this to ["*"] to block all servers by default, and then
|
||||
# use `allowed_remote_server_names` to allow only specific servers.
|
||||
#
|
||||
# example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"]
|
||||
#
|
||||
#forbidden_remote_server_names = []
|
||||
|
||||
# List of allowed server names via regex patterns that we will allow,
|
||||
# regardless of if they match `forbidden_remote_server_names`.
|
||||
#
|
||||
# This option has no effect if `forbidden_remote_server_names` is empty.
|
||||
#
|
||||
# example: ["goodserver\.tld$", "goodphrase"]
|
||||
#
|
||||
#allowed_remote_server_names = []
|
||||
|
||||
# List of forbidden server names via regex patterns that we will block all
|
||||
# outgoing federated room directory requests for. Useful for preventing
|
||||
# our users from wandering into bad servers or spaces.
|
||||
|
||||
@@ -44,15 +44,11 @@ ENV CARGO_SBOM_VERSION=0.9.1
|
||||
# renovate: datasource=crate depName=lddtree
|
||||
ENV LDDTREE_VERSION=0.3.7
|
||||
|
||||
# renovate: datasource=crate depName=timelord-cli
|
||||
ENV TIMELORD_VERSION=3.0.1
|
||||
|
||||
# Install unpackaged tools
|
||||
RUN <<EOF
|
||||
curl --retry 5 -L --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/cargo-bins/cargo-binstall/main/install-from-binstall-release.sh | bash
|
||||
cargo binstall --no-confirm cargo-sbom --version $CARGO_SBOM_VERSION
|
||||
cargo binstall --no-confirm lddtree --version $LDDTREE_VERSION
|
||||
cargo binstall --no-confirm timelord-cli --version $TIMELORD_VERSION
|
||||
EOF
|
||||
|
||||
# Set up xx (cross-compilation scripts)
|
||||
@@ -134,10 +130,6 @@ RUN xx-cargo --print-target-triple
|
||||
# Get source
|
||||
COPY . .
|
||||
|
||||
# Timelord sync
|
||||
RUN --mount=type=cache,target=/timelord/ \
|
||||
timelord sync --source-dir . --cache-dir /timelord/
|
||||
|
||||
# Build the binary
|
||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||
--mount=type=cache,target=/usr/local/cargo/git/db \
|
||||
|
||||
Vendored
+3
@@ -1,3 +1,6 @@
|
||||
/.well-known/matrix/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Type: application/json
|
||||
/.well-known/continuwuity/*
|
||||
Access-Control-Allow-Origin: *
|
||||
Content-Type: application/json
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"$schema": "https://continuwuity.org/schema/announcements.schema.json",
|
||||
"announcements": [
|
||||
{
|
||||
"id": 1,
|
||||
"message": "Welcome to Continuwuity! Important announcements about the project will appear here."
|
||||
}
|
||||
]
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"$id": "https://continwuity.org/schema/announcements.schema.json",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"updates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"date": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"id",
|
||||
"message"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"updates"
|
||||
]
|
||||
}
|
||||
@@ -11,6 +11,8 @@ pub(crate) enum GlobalsCommand {
|
||||
|
||||
CurrentCount,
|
||||
|
||||
LastCheckForAnnouncementsId,
|
||||
|
||||
/// - This returns an empty `Ok(BTreeMap<..>)` when there are no keys found
|
||||
/// for the server.
|
||||
SigningKeysFor {
|
||||
@@ -37,6 +39,16 @@ pub(super) async fn process(subcommand: GlobalsCommand, context: &Context<'_>) -
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
},
|
||||
| GlobalsCommand::LastCheckForAnnouncementsId => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services
|
||||
.announcements
|
||||
.last_check_for_announcements_id()
|
||||
.await;
|
||||
let query_time = timer.elapsed();
|
||||
|
||||
write!(context, "Query completed in {query_time:?}:\n\n```rs\n{results:#?}\n```")
|
||||
},
|
||||
| GlobalsCommand::SigningKeysFor { origin } => {
|
||||
let timer = tokio::time::Instant::now();
|
||||
let results = services.server_keys.verify_keys_for(&origin).await;
|
||||
|
||||
@@ -52,13 +52,8 @@ pub(crate) async fn get_public_rooms_filtered_route(
|
||||
) -> Result<get_public_rooms_filtered::v3::Response> {
|
||||
if let Some(server) = &body.server {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_room_directory_server_names
|
||||
.is_match(server.host())
|
||||
|| services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
.moderation
|
||||
.is_remote_server_room_directory_forbidden(server)
|
||||
{
|
||||
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
|
||||
}
|
||||
@@ -92,15 +87,7 @@ pub(crate) async fn get_public_rooms_route(
|
||||
body: Ruma<get_public_rooms::v3::Request>,
|
||||
) -> Result<get_public_rooms::v3::Response> {
|
||||
if let Some(server) = &body.server {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_room_directory_server_names
|
||||
.is_match(server.host())
|
||||
|| services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,9 +83,8 @@ async fn banned_room_check(
|
||||
if let Some(room_id) = room_id {
|
||||
if services.rooms.metadata.is_banned(room_id).await
|
||||
|| services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(room_id.server_name().expect("legacy room mxid").host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(room_id.server_name().expect("legacy room mxid"))
|
||||
{
|
||||
warn!(
|
||||
"User {user_id} who is not an admin attempted to send an invite for or \
|
||||
|
||||
@@ -274,9 +274,8 @@ pub(crate) async fn is_ignored_pdu(
|
||||
let ignored_type = IGNORED_MESSAGE_TYPES.binary_search(&pdu.kind).is_ok();
|
||||
|
||||
let ignored_server = services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(pdu.sender().server_name().host());
|
||||
.moderation
|
||||
.is_remote_server_forbidden(pdu.sender().server_name());
|
||||
|
||||
if ignored_type
|
||||
&& (ignored_server || services.users.user_is_ignored(&pdu.sender, user_id).await)
|
||||
|
||||
@@ -107,7 +107,6 @@ pub(crate) async fn create_room_route(
|
||||
|
||||
return Err!(Request(Forbidden("Publishing rooms to the room directory is not allowed")));
|
||||
}
|
||||
|
||||
let _short_id = services
|
||||
.rooms
|
||||
.short
|
||||
@@ -606,24 +605,35 @@ fn custom_room_id_check(services: &Services, custom_room_id: &str) -> Result<Own
|
||||
return Err(Error::BadRequest(ErrorKind::Unknown, "Custom room ID is forbidden."));
|
||||
}
|
||||
|
||||
if custom_room_id.contains(':') {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Custom room ID contained `:` which is not allowed. Please note that this expects a \
|
||||
localpart, not the full room ID.",
|
||||
));
|
||||
} else if custom_room_id.contains(char::is_whitespace) {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Custom room ID contained spaces which is not valid.",
|
||||
));
|
||||
}
|
||||
|
||||
let server_name = services.globals.server_name();
|
||||
let full_room_id = format!("!{custom_room_id}:{server_name}");
|
||||
|
||||
OwnedRoomId::parse(full_room_id)
|
||||
let mut room_id = custom_room_id.to_owned();
|
||||
if custom_room_id.contains(':') {
|
||||
if !custom_room_id.starts_with('!') {
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Custom room ID contains an unexpected `:` which is not allowed.",
|
||||
));
|
||||
}
|
||||
} else if custom_room_id.starts_with('!'){
|
||||
return Err(Error::BadRequest(
|
||||
ErrorKind::InvalidParam,
|
||||
"Room ID is prefixed with !, but is not fully qualified. You likely did not want this."));
|
||||
} else {
|
||||
room_id = format!("!{custom_room_id}:{server_name}");
|
||||
}
|
||||
OwnedRoomId::parse(room_id)
|
||||
.map_err(Into::into)
|
||||
.inspect(|full_room_id| debug_info!(?full_room_id, "Full custom room ID"))
|
||||
.and_then(
|
||||
|full_room_id| {
|
||||
if full_room_id.server_name().expect("failed to extract server name from room ID") != server_name {
|
||||
Err(Error::BadRequest(ErrorKind::InvalidParam, "Custom room ID must be on this server."))
|
||||
} else {
|
||||
Ok(full_room_id)
|
||||
}
|
||||
}
|
||||
)
|
||||
.inspect(|full_room_id| {
|
||||
debug_info!(?full_room_id, "Full custom room ID");
|
||||
})
|
||||
.inspect_err(|e| warn!(?e, ?custom_room_id, "Failed to create room with custom room ID",))
|
||||
}
|
||||
|
||||
@@ -121,9 +121,7 @@ where
|
||||
.map(|(key, val)| (key, val.collect()))
|
||||
.collect();
|
||||
|
||||
if populate {
|
||||
rooms.push(summary_to_chunk(summary.clone()));
|
||||
} else {
|
||||
if !populate {
|
||||
children = children
|
||||
.iter()
|
||||
.rev()
|
||||
@@ -146,8 +144,10 @@ where
|
||||
.collect();
|
||||
}
|
||||
|
||||
if queue.is_empty() && children.is_empty() {
|
||||
break;
|
||||
if populate {
|
||||
rooms.push(summary_to_chunk(summary.clone()));
|
||||
} else if queue.is_empty() && children.is_empty() {
|
||||
return Err!(Request(InvalidParam("Room IDs in token were not found.")));
|
||||
}
|
||||
|
||||
parents.insert(current_room.clone());
|
||||
|
||||
@@ -306,7 +306,7 @@ async fn auth_server(
|
||||
}
|
||||
|
||||
fn auth_server_checks(services: &Services, x_matrix: &XMatrix) -> Result<()> {
|
||||
if !services.server.config.allow_federation {
|
||||
if !services.config.allow_federation {
|
||||
return Err!(Config("allow_federation", "Federation is disabled."));
|
||||
}
|
||||
|
||||
@@ -316,11 +316,7 @@ fn auth_server_checks(services: &Services, x_matrix: &XMatrix) -> Result<()> {
|
||||
}
|
||||
|
||||
let origin = &x_matrix.origin;
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(origin.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(origin) {
|
||||
return Err!(Request(Forbidden(debug_warn!(
|
||||
"Federation requests from {origin} denied."
|
||||
))));
|
||||
|
||||
@@ -37,19 +37,14 @@ pub(crate) async fn create_invite_route(
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
|
||||
}
|
||||
}
|
||||
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
warn!(
|
||||
"Received federated/remote invite from banned server {} for room ID {}. Rejecting.",
|
||||
|
||||
@@ -42,9 +42,8 @@ pub(crate) async fn create_join_event_template_route(
|
||||
.await?;
|
||||
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
warn!(
|
||||
"Server {} for remote user {} tried joining room ID {} which has a server name that \
|
||||
@@ -57,11 +56,7 @@ pub(crate) async fn create_join_event_template_route(
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
return Err!(Request(Forbidden(warn!(
|
||||
"Room ID server name {server} is banned on this homeserver."
|
||||
))));
|
||||
|
||||
@@ -33,9 +33,8 @@ pub(crate) async fn create_knock_event_template_route(
|
||||
.await?;
|
||||
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
warn!(
|
||||
"Server {} for remote user {} tried knocking room ID {} which has a server name \
|
||||
@@ -48,11 +47,7 @@ pub(crate) async fn create_knock_event_template_route(
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,9 +268,8 @@ pub(crate) async fn create_join_event_v1_route(
|
||||
body: Ruma<create_join_event::v1::Request>,
|
||||
) -> Result<create_join_event::v1::Response> {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
warn!(
|
||||
"Server {} tried joining room ID {} through us who has a server name that is \
|
||||
@@ -282,11 +281,7 @@ pub(crate) async fn create_join_event_v1_route(
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
warn!(
|
||||
"Server {} tried joining room ID {} through us which has a server name that is \
|
||||
globally forbidden. Rejecting.",
|
||||
@@ -314,19 +309,14 @@ pub(crate) async fn create_join_event_v2_route(
|
||||
body: Ruma<create_join_event::v2::Request>,
|
||||
) -> Result<create_join_event::v2::Response> {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
return Err!(Request(Forbidden("Server is banned on this homeserver.")));
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
warn!(
|
||||
"Server {} tried joining room ID {} through us which has a server name that is \
|
||||
globally forbidden. Rejecting.",
|
||||
|
||||
@@ -26,9 +26,8 @@ pub(crate) async fn create_knock_event_v1_route(
|
||||
body: Ruma<send_knock::v1::Request>,
|
||||
) -> Result<send_knock::v1::Response> {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(body.origin().host())
|
||||
.moderation
|
||||
.is_remote_server_forbidden(body.origin())
|
||||
{
|
||||
warn!(
|
||||
"Server {} tried knocking room ID {} who has a server name that is globally \
|
||||
@@ -40,11 +39,7 @@ pub(crate) async fn create_knock_event_v1_route(
|
||||
}
|
||||
|
||||
if let Some(server) = body.room_id.server_name() {
|
||||
if services
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server.host())
|
||||
{
|
||||
if services.moderation.is_remote_server_forbidden(server) {
|
||||
warn!(
|
||||
"Server {} tried knocking room ID {} which has a server name that is globally \
|
||||
forbidden. Rejecting.",
|
||||
|
||||
+27
-2
@@ -160,6 +160,12 @@ pub struct Config {
|
||||
#[serde(default = "default_new_user_displayname_suffix")]
|
||||
pub new_user_displayname_suffix: String,
|
||||
|
||||
/// If enabled, conduwuit will send a simple GET request periodically to
|
||||
/// `https://continuwuity.org/.well-known/continuwuity/announcements` for any new
|
||||
/// announcements or major updates. This is not an update check endpoint.
|
||||
#[serde(alias = "allow_check_for_updates", default = "true_fn")]
|
||||
pub allow_announcements_check: bool,
|
||||
|
||||
/// Set this to any float value to multiply conduwuit's in-memory LRU caches
|
||||
/// with such as "auth_chain_cache_capacity".
|
||||
///
|
||||
@@ -1364,11 +1370,19 @@ pub struct Config {
|
||||
/// incoming AND outgoing federation with, and block client room joins /
|
||||
/// remote user invites.
|
||||
///
|
||||
/// Additionally, it will hide messages from these servers for all users
|
||||
/// on this server.
|
||||
///
|
||||
/// Note that your messages can still make it to forbidden servers through
|
||||
/// backfilling. Events we receive from forbidden servers via backfill will
|
||||
/// be stored in the database, but will not be sent to the client.
|
||||
///
|
||||
/// This check is applied on the room ID, room alias, sender server name,
|
||||
/// sender user's server name, inbound federation X-Matrix origin, and
|
||||
/// outbound federation handler.
|
||||
///
|
||||
/// Basically "global" ACLs.
|
||||
/// You can set this to ["*"] to block all servers by default, and then
|
||||
/// use `allowed_remote_server_names` to allow only specific servers.
|
||||
///
|
||||
/// example: ["badserver\.tld$", "badphrase", "19dollarfortnitecards"]
|
||||
///
|
||||
@@ -1376,6 +1390,17 @@ pub struct Config {
|
||||
#[serde(default, with = "serde_regex")]
|
||||
pub forbidden_remote_server_names: RegexSet,
|
||||
|
||||
/// List of allowed server names via regex patterns that we will allow,
|
||||
/// regardless of if they match `forbidden_remote_server_names`.
|
||||
///
|
||||
/// This option has no effect if `forbidden_remote_server_names` is empty.
|
||||
///
|
||||
/// example: ["goodserver\.tld$", "goodphrase"]
|
||||
///
|
||||
/// default: []
|
||||
#[serde(default, with = "serde_regex")]
|
||||
pub allowed_remote_server_names: RegexSet,
|
||||
|
||||
/// List of forbidden server names via regex patterns that we will block all
|
||||
/// outgoing federated room directory requests for. Useful for preventing
|
||||
/// our users from wandering into bad servers or spaces.
|
||||
@@ -1944,7 +1969,7 @@ impl Config {
|
||||
let mut addrs = Vec::with_capacity(
|
||||
self.get_bind_hosts()
|
||||
.len()
|
||||
.saturating_add(self.get_bind_ports().len()),
|
||||
.saturating_mul(self.get_bind_ports().len()),
|
||||
);
|
||||
for host in &self.get_bind_hosts() {
|
||||
for port in &self.get_bind_ports() {
|
||||
|
||||
@@ -114,11 +114,11 @@ ruma.workspace = true
|
||||
rustls.workspace = true
|
||||
rustls.optional = true
|
||||
sentry.optional = true
|
||||
sentry.workspace = true
|
||||
sentry-tower.optional = true
|
||||
sentry-tower.workspace = true
|
||||
sentry-tracing.optional = true
|
||||
sentry-tracing.workspace = true
|
||||
sentry.workspace = true
|
||||
serde_json.workspace = true
|
||||
tokio.workspace = true
|
||||
tower.workspace = true
|
||||
|
||||
@@ -0,0 +1,169 @@
|
||||
//! # Announcements service
|
||||
//!
|
||||
//! This service is responsible for checking for announcements and sending them
|
||||
//! to the client.
|
||||
//!
|
||||
//! It is used to send announcements to the admin room and logs.
|
||||
//! Annuncements are stored in /docs/static/announcements right now.
|
||||
//! The highest seen announcement id is stored in the database. When the
|
||||
//! announcement check is run, all announcements with an ID higher than those
|
||||
//! seen before are printed to the console and sent to the admin room.
|
||||
//!
|
||||
//! Old announcements should be deleted to avoid spamming the room on first
|
||||
//! install.
|
||||
//!
|
||||
//! Announcements are displayed as markdown in the admin room, but plain text in
|
||||
//! the console.
|
||||
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use conduwuit::{Result, Server, debug, info, warn};
|
||||
use database::{Deserialized, Map};
|
||||
use ruma::events::room::message::RoomMessageEventContent;
|
||||
use serde::Deserialize;
|
||||
use tokio::{
|
||||
sync::Notify,
|
||||
time::{MissedTickBehavior, interval},
|
||||
};
|
||||
|
||||
use crate::{Dep, admin, client, globals};
|
||||
|
||||
pub struct Service {
|
||||
interval: Duration,
|
||||
interrupt: Notify,
|
||||
db: Arc<Map>,
|
||||
services: Services,
|
||||
}
|
||||
|
||||
struct Services {
|
||||
admin: Dep<admin::Service>,
|
||||
client: Dep<client::Service>,
|
||||
globals: Dep<globals::Service>,
|
||||
server: Arc<Server>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CheckForAnnouncementsResponse {
|
||||
announcements: Vec<CheckForAnnouncementsResponseEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct CheckForAnnouncementsResponseEntry {
|
||||
id: u64,
|
||||
date: Option<String>,
|
||||
message: String,
|
||||
}
|
||||
|
||||
const CHECK_FOR_ANNOUNCEMENTS_URL: &str =
|
||||
"https://continuwuity.org/.well-known/continuwuity/announcements";
|
||||
const CHECK_FOR_ANNOUNCEMENTS_INTERVAL: u64 = 7200; // 2 hours
|
||||
const LAST_CHECK_FOR_ANNOUNCEMENTS_ID: &[u8; 25] = b"last_seen_announcement_id";
|
||||
// In conduwuit, this was under b"a"
|
||||
|
||||
#[async_trait]
|
||||
impl crate::Service for Service {
|
||||
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||
Ok(Arc::new(Self {
|
||||
interval: Duration::from_secs(CHECK_FOR_ANNOUNCEMENTS_INTERVAL),
|
||||
interrupt: Notify::new(),
|
||||
db: args.db["global"].clone(),
|
||||
services: Services {
|
||||
globals: args.depend::<globals::Service>("globals"),
|
||||
admin: args.depend::<admin::Service>("admin"),
|
||||
client: args.depend::<client::Service>("client"),
|
||||
server: args.server.clone(),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all, name = "announcements", level = "debug")]
|
||||
async fn worker(self: Arc<Self>) -> Result<()> {
|
||||
if !self.services.globals.allow_announcements_check() {
|
||||
debug!("Disabling announcements check");
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut i = interval(self.interval);
|
||||
i.set_missed_tick_behavior(MissedTickBehavior::Delay);
|
||||
i.reset_after(self.interval);
|
||||
loop {
|
||||
tokio::select! {
|
||||
() = self.interrupt.notified() => break,
|
||||
_ = i.tick() => (),
|
||||
}
|
||||
|
||||
if let Err(e) = self.check().await {
|
||||
warn!(%e, "Failed to check for announcements");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn interrupt(&self) { self.interrupt.notify_waiters(); }
|
||||
|
||||
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||
}
|
||||
|
||||
impl Service {
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn check(&self) -> Result<()> {
|
||||
debug_assert!(self.services.server.running(), "server must not be shutting down");
|
||||
|
||||
let response = self
|
||||
.services
|
||||
.client
|
||||
.default
|
||||
.get(CHECK_FOR_ANNOUNCEMENTS_URL)
|
||||
.send()
|
||||
.await?
|
||||
.text()
|
||||
.await?;
|
||||
|
||||
let response = serde_json::from_str::<CheckForAnnouncementsResponse>(&response)?;
|
||||
for announcement in &response.announcements {
|
||||
if announcement.id > self.last_check_for_announcements_id().await {
|
||||
self.handle(announcement).await;
|
||||
self.update_check_for_announcements_id(announcement.id);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(skip_all)]
|
||||
async fn handle(&self, announcement: &CheckForAnnouncementsResponseEntry) {
|
||||
if let Some(date) = &announcement.date {
|
||||
info!("[announcements] {date} {:#}", announcement.message);
|
||||
} else {
|
||||
info!("[announcements] {:#}", announcement.message);
|
||||
}
|
||||
|
||||
self.services
|
||||
.admin
|
||||
.send_message(RoomMessageEventContent::text_markdown(format!(
|
||||
"### New announcement{}\n\n{}",
|
||||
announcement
|
||||
.date
|
||||
.as_ref()
|
||||
.map_or_else(String::new, |date| format!(" - `{date}`")),
|
||||
announcement.message
|
||||
)))
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn update_check_for_announcements_id(&self, id: u64) {
|
||||
self.db.raw_put(LAST_CHECK_FOR_ANNOUNCEMENTS_ID, id);
|
||||
}
|
||||
|
||||
pub async fn last_check_for_announcements_id(&self) -> u64 {
|
||||
self.db
|
||||
.get(LAST_CHECK_FOR_ANNOUNCEMENTS_ID)
|
||||
.await
|
||||
.deserialized()
|
||||
.unwrap_or(0_u64)
|
||||
}
|
||||
}
|
||||
@@ -64,13 +64,7 @@ where
|
||||
return Err!(Config("allow_federation", "Federation is disabled."));
|
||||
}
|
||||
|
||||
if self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(dest.host())
|
||||
{
|
||||
if self.services.moderation.is_remote_server_forbidden(dest) {
|
||||
return Err!(Request(Forbidden(debug_warn!("Federation with {dest} is not allowed."))));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use std::sync::Arc;
|
||||
|
||||
use conduwuit::{Result, Server};
|
||||
|
||||
use crate::{Dep, client, resolver, server_keys};
|
||||
use crate::{Dep, client, moderation, resolver, server_keys};
|
||||
|
||||
pub struct Service {
|
||||
services: Services,
|
||||
@@ -15,6 +15,7 @@ struct Services {
|
||||
client: Dep<client::Service>,
|
||||
resolver: Dep<resolver::Service>,
|
||||
server_keys: Dep<server_keys::Service>,
|
||||
moderation: Dep<moderation::Service>,
|
||||
}
|
||||
|
||||
impl crate::Service for Service {
|
||||
@@ -25,6 +26,7 @@ impl crate::Service for Service {
|
||||
client: args.depend::<client::Service>("client"),
|
||||
resolver: args.depend::<resolver::Service>("resolver"),
|
||||
server_keys: args.depend::<server_keys::Service>("server_keys"),
|
||||
moderation: args.depend::<moderation::Service>("moderation"),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -127,6 +127,10 @@ impl Service {
|
||||
&self.server.config.new_user_displayname_suffix
|
||||
}
|
||||
|
||||
pub fn allow_announcements_check(&self) -> bool {
|
||||
self.server.config.allow_announcements_check
|
||||
}
|
||||
|
||||
pub fn trusted_servers(&self) -> &[OwnedServerName] { &self.server.config.trusted_servers }
|
||||
|
||||
pub fn turn_password(&self) -> &String { &self.server.config.turn_password }
|
||||
|
||||
@@ -22,7 +22,7 @@ use tokio::{
|
||||
|
||||
use self::data::{Data, Metadata};
|
||||
pub use self::thumbnail::Dim;
|
||||
use crate::{Dep, client, globals, sending};
|
||||
use crate::{Dep, client, globals, moderation, sending};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FileMeta {
|
||||
@@ -42,6 +42,7 @@ struct Services {
|
||||
client: Dep<client::Service>,
|
||||
globals: Dep<globals::Service>,
|
||||
sending: Dep<sending::Service>,
|
||||
moderation: Dep<moderation::Service>,
|
||||
}
|
||||
|
||||
/// generated MXC ID (`media-id`) length
|
||||
@@ -64,6 +65,7 @@ impl crate::Service for Service {
|
||||
client: args.depend::<client::Service>("client"),
|
||||
globals: args.depend::<globals::Service>("globals"),
|
||||
sending: args.depend::<sending::Service>("sending"),
|
||||
moderation: args.depend::<moderation::Service>("moderation"),
|
||||
},
|
||||
}))
|
||||
}
|
||||
|
||||
@@ -423,16 +423,8 @@ pub async fn fetch_remote_content_legacy(
|
||||
fn check_fetch_authorized(&self, mxc: &Mxc<'_>) -> Result<()> {
|
||||
if self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.prevent_media_downloads_from
|
||||
.is_match(mxc.server_name.host())
|
||||
|| self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(mxc.server_name.host())
|
||||
.moderation
|
||||
.is_remote_server_media_downloads_forbidden(mxc.server_name)
|
||||
{
|
||||
// we'll lie to the client and say the blocked server's media was not found and
|
||||
// log. the client has no way of telling anyways so this is a security bonus.
|
||||
|
||||
@@ -8,6 +8,7 @@ pub mod services;
|
||||
|
||||
pub mod account_data;
|
||||
pub mod admin;
|
||||
pub mod announcements;
|
||||
pub mod appservice;
|
||||
pub mod client;
|
||||
pub mod config;
|
||||
@@ -16,6 +17,7 @@ pub mod federation;
|
||||
pub mod globals;
|
||||
pub mod key_backups;
|
||||
pub mod media;
|
||||
pub mod moderation;
|
||||
pub mod presence;
|
||||
pub mod pusher;
|
||||
pub mod resolver;
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use conduwuit::{Result, Server, implement};
|
||||
use ruma::ServerName;
|
||||
|
||||
pub struct Service {
|
||||
services: Services,
|
||||
}
|
||||
|
||||
struct Services {
|
||||
pub server: Arc<Server>,
|
||||
}
|
||||
|
||||
impl crate::Service for Service {
|
||||
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||
Ok(Arc::new(Self {
|
||||
services: Services { server: args.server.clone() },
|
||||
}))
|
||||
}
|
||||
|
||||
fn name(&self) -> &str { crate::service::make_name(std::module_path!()) }
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
#[must_use]
|
||||
pub fn is_remote_server_forbidden(&self, server_name: &ServerName) -> bool {
|
||||
// We must never block federating with ourselves
|
||||
if server_name == self.services.server.config.server_name {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if server is explicitly allowed
|
||||
if self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.allowed_remote_server_names
|
||||
.is_match(server_name.host())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if server is explicitly forbidden
|
||||
self.services
|
||||
.server
|
||||
.config
|
||||
.forbidden_remote_server_names
|
||||
.is_match(server_name.host())
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
#[must_use]
|
||||
pub fn is_remote_server_room_directory_forbidden(&self, server_name: &ServerName) -> bool {
|
||||
// Forbidden if NOT (allowed is empty OR allowed contains server OR is self)
|
||||
// OR forbidden contains server
|
||||
self.is_remote_server_forbidden(server_name)
|
||||
|| self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.forbidden_remote_room_directory_server_names
|
||||
.is_match(server_name.host())
|
||||
}
|
||||
|
||||
#[implement(Service)]
|
||||
#[must_use]
|
||||
pub fn is_remote_server_media_downloads_forbidden(&self, server_name: &ServerName) -> bool {
|
||||
// Forbidden if NOT (allowed is empty OR allowed contains server OR is self)
|
||||
// OR forbidden contains server
|
||||
self.is_remote_server_forbidden(server_name)
|
||||
|| self
|
||||
.services
|
||||
.server
|
||||
.config
|
||||
.prevent_media_downloads_from
|
||||
.is_match(server_name.host())
|
||||
}
|
||||
@@ -10,9 +10,10 @@ use futures::{Stream, StreamExt, TryStreamExt};
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use crate::{
|
||||
account_data, admin, appservice, client, config, emergency, federation, globals, key_backups,
|
||||
account_data, admin, announcements, appservice, client, config, emergency, federation,
|
||||
globals, key_backups,
|
||||
manager::Manager,
|
||||
media, presence, pusher, resolver, rooms, sending, server_keys, service,
|
||||
media, moderation, presence, pusher, resolver, rooms, sending, server_keys, service,
|
||||
service::{Args, Map, Service},
|
||||
sync, transaction_ids, uiaa, users,
|
||||
};
|
||||
@@ -38,6 +39,8 @@ pub struct Services {
|
||||
pub transaction_ids: Arc<transaction_ids::Service>,
|
||||
pub uiaa: Arc<uiaa::Service>,
|
||||
pub users: Arc<users::Service>,
|
||||
pub moderation: Arc<moderation::Service>,
|
||||
pub announcements: Arc<announcements::Service>,
|
||||
|
||||
manager: Mutex<Option<Arc<Manager>>>,
|
||||
pub(crate) service: Arc<Map>,
|
||||
@@ -104,6 +107,8 @@ impl Services {
|
||||
transaction_ids: build!(transaction_ids::Service),
|
||||
uiaa: build!(uiaa::Service),
|
||||
users: build!(users::Service),
|
||||
moderation: build!(moderation::Service),
|
||||
announcements: build!(announcements::Service),
|
||||
|
||||
manager: Mutex::new(None),
|
||||
service,
|
||||
|
||||
Reference in New Issue
Block a user