diff --git a/.forgejo/workflows/build-fedora.yml b/.forgejo/workflows/build-fedora.yml new file mode 100644 index 00000000..c101ed04 --- /dev/null +++ b/.forgejo/workflows/build-fedora.yml @@ -0,0 +1,469 @@ +name: Build / Fedora RPM + +concurrency: + group: "build-fedora-${{ github.ref }}" + cancel-in-progress: true + +on: + push: + branches: + - '**' + tags: + - 'v*' + paths: + - 'fedora/**' + - 'src/**' + - 'Cargo.toml' + - 'Cargo.lock' + - '.forgejo/workflows/build-fedora.yml' + workflow_dispatch: + +jobs: + build: + runs-on: fedora-latest + steps: + - name: Detect Fedora version + id: fedora + run: | + VERSION=$(rpm -E %fedora) + echo "version=$VERSION" >> $GITHUB_OUTPUT + echo "Fedora version: $VERSION" + + - name: Checkout repository with full history + uses: https://code.forgejo.org/actions/checkout@v4 + with: + fetch-depth: 0 + + + - name: Cache DNF packages + uses: https://code.forgejo.org/actions/cache@v4 + with: + path: | + /var/cache/dnf + /var/cache/yum + key: dnf-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('fedora/continuwuity.spec.rpkg') }}-v1 + restore-keys: | + dnf-fedora${{ steps.fedora.outputs.version }}- + + - name: Cache Cargo registry + uses: https://code.forgejo.org/actions/cache@v4 + with: + path: | + ~/.cargo/registry + ~/.cargo/git + key: cargo-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + cargo-fedora${{ steps.fedora.outputs.version }}- + + - name: Cache Rust build dependencies + uses: https://code.forgejo.org/actions/cache@v4 + with: + path: | + ~/rpmbuild/BUILD/*/target/release/deps + ~/rpmbuild/BUILD/*/target/release/build + ~/rpmbuild/BUILD/*/target/release/.fingerprint + ~/rpmbuild/BUILD/*/target/release/incremental + key: rust-deps-fedora${{ steps.fedora.outputs.version }}-${{ hashFiles('**/Cargo.lock') }} + restore-keys: | + rust-deps-fedora${{ steps.fedora.outputs.version }}- + + - name: Setup sccache + uses: https://github.com/mozilla-actions/sccache-action@v0.0.9 + with: + token: ${{ secrets.GH_PUBLIC_RO }} + + - name: Configure sccache environment + run: | + echo "RUSTC_WRAPPER=sccache" >> $GITHUB_ENV + echo "CMAKE_C_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV + echo "CMAKE_CXX_COMPILER_LAUNCHER=sccache" >> $GITHUB_ENV + echo "SCCACHE_CACHE_SIZE=10G" >> $GITHUB_ENV + # Aggressive GC since cache restores don't increment counter + echo "CARGO_INCREMENTAL_GC_TRIGGER=5" >> $GITHUB_ENV + + - name: Install base RPM tools + run: | + dnf install -y --setopt=keepcache=1 \ + wget \ + rpm-build \ + rpm-sign \ + rpmdevtools \ + rpkg \ + cargo-rpm-macros \ + systemd-rpm-macros \ + python3-pip + + - name: Setup build environment and build SRPM + run: | + git config --global --add safe.directory "$GITHUB_WORKSPACE" + git config --global user.email "ci@continuwuity.org" + git config --global user.name "Continuwuity" + + rpmdev-setuptree + + cd "$GITHUB_WORKSPACE" + + # Determine release suffix and version based on ref type and branch + if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + # Tags get clean version numbers for stable releases + RELEASE_SUFFIX="" + TAG_NAME="${{ github.ref_name }}" + # Extract version from tag (remove v prefix if present) + TAG_VERSION=$(echo "$TAG_NAME" | sed 's/^v//') + + # Create spec file with tag version + sed -e "s/^Version:.*$/Version: $TAG_VERSION/" \ + -e "s/^Release:.*$/Release: 1%{?dist}/" \ + fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg + elif [ "${{ github.ref_name }}" = "main" ]; then + # Main branch gets .dev suffix + RELEASE_SUFFIX=".dev" + + # Replace the Release line to include our suffix + sed "s/^Release:.*$/Release: 1${RELEASE_SUFFIX}%{?dist}/" \ + fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg + else + # Other branches get sanitized branch name as suffix + SAFE_BRANCH=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/_/g' | cut -c1-20) + RELEASE_SUFFIX=".${SAFE_BRANCH}" + + # Replace the Release line to include our suffix + sed "s/^Release:.*$/Release: 1${RELEASE_SUFFIX}%{?dist}/" \ + fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg + fi + + rpkg srpm --outdir "$HOME/rpmbuild/SRPMS" + + ls -la $HOME/rpmbuild/SRPMS/ + + - name: Setup GPG for RPM signing + run: | + # Skip if no signing key is configured + if [ -z "${{ secrets.RPM_SIGNING_KEY }}" ]; then + echo "No RPM signing key configured - skipping signing setup" + exit 0 + fi + + echo "${{ secrets.RPM_SIGNING_KEY }}" | gpg --batch --import + + # Get the key ID (look for the sec line, not the uid line) + KEY_ID=$(gpg --list-secret-keys --keyid-format=long | grep "^sec" | head -1 | awk '{print $2}' | cut -d'/' -f2) + echo "Using GPG key: $KEY_ID" + + cat > ~/.rpmmacros << EOF + %_signature gpg + %_gpg_name $KEY_ID + %__gpg /usr/bin/gpg + EOF + + - name: Install build dependencies from SRPM + run: | + SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1) + + if [ -z "$SRPM" ]; then + echo "Error: No SRPM file found" + exit 1 + fi + + echo "Installing build dependencies from: $(basename $SRPM)" + dnf builddep -y "$SRPM" + + - name: Build RPM from SRPM + run: | + SRPM=$(find "$HOME/rpmbuild/SRPMS" -name "*.src.rpm" | head -1) + + if [ -z "$SRPM" ]; then + echo "Error: No SRPM file found" + exit 1 + fi + + echo "Building from SRPM: $SRPM" + + rpmbuild --rebuild "$SRPM" \ + --define "_topdir $HOME/rpmbuild" \ + --define "_sourcedir $GITHUB_WORKSPACE" \ + --nocheck # Skip %check section to avoid test dependencies + + - name: Sign RPM packages + run: | + # Skip if no signing key is configured + if [ -z "${{ secrets.RPM_SIGNING_KEY }}" ]; then + echo "No RPM signing key configured - skipping package signing" + exit 0 + fi + + # Export GPG_TTY to avoid terminal warnings + export GPG_TTY=/dev/null + + for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do + echo "Signing: $(basename $rpm)" + + # Use expect or provide empty passphrase via stdin for batch signing + if ! echo "" | rpmsign --addsign "$rpm" 2>&1; then + echo "ERROR: Failed to sign $rpm" + exit 1 + fi + done + + echo "Successfully signed all RPMs" + + - name: Verify RPM signatures + run: | + # Skip if no signing key is configured + if [ -z "${{ secrets.RPM_SIGNING_KEY }}" ]; then + echo "No RPM signing key configured - skipping signature verification" + exit 0 + fi + + echo "Importing GPG public key for verification..." + rpm --import fedora/RPM-GPG-KEY-continuwuity.asc + + FAILED_COUNT=0 + TOTAL_COUNT=0 + + for rpm in $(find "$HOME/rpmbuild" -name "*.rpm" -type f); do + echo -n "Verifying $(basename $rpm): " + TOTAL_COUNT=$((TOTAL_COUNT + 1)) + + if rpm --checksig "$rpm"; then + echo " ✓" + else + echo " ✗ FAILED" + FAILED_COUNT=$((FAILED_COUNT + 1)) + fi + done + + # Fail if any RPMs failed verification + if [ "$FAILED_COUNT" -gt 0 ]; then + echo "ERROR: $FAILED_COUNT out of $TOTAL_COUNT RPMs failed signature verification" + exit 1 + fi + + echo "Successfully verified all $TOTAL_COUNT RPM signatures" + + - name: Test RPM installation + run: | + # Find the main binary RPM (exclude debug and source RPMs) + RPM=$(find "$HOME/rpmbuild/RPMS" -name "continuwuity-*.rpm" \ + ! -name "*debuginfo*" \ + ! -name "*debugsource*" \ + ! -name "*.src.rpm" | head -1) + + if [ -z "$RPM" ]; then + echo "Error: No binary RPM file found" + exit 1 + fi + + echo "Testing installation of: $RPM" + + # Dry run first + rpm -qpi "$RPM" + echo "" + rpm -qpl "$RPM" + + # Actually install it + dnf install -y "$RPM" + + # Verify installation + rpm -qa | grep continuwuity + + # Check that the binary exists + [ -f /usr/bin/conduwuit ] && echo "✅ Binary installed successfully" + [ -f /usr/lib/systemd/system/conduwuit.service ] && echo "✅ Systemd service installed" + [ -f /etc/conduwuit/conduwuit.toml ] && echo "✅ Config file installed" + + - name: List built packages + run: | + echo "Binary RPMs:" + find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec ls -la {} \; + + echo "" + echo "Source RPMs:" + find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec ls -la {} \; + + - name: Collect artifacts + run: | + mkdir -p artifacts + + find "$HOME/rpmbuild/RPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \; + find "$HOME/rpmbuild/SRPMS" -name "*.rpm" -type f -exec cp {} artifacts/ \; + + cd artifacts + echo "Build Information:" > BUILD_INFO.txt + echo "==================" >> BUILD_INFO.txt + echo "Git commit: ${{ github.sha }}" >> BUILD_INFO.txt + echo "Git branch: ${{ github.ref_name }}" >> BUILD_INFO.txt + echo "Build date: $(date -u +%Y-%m-%d_%H:%M:%S_UTC)" >> BUILD_INFO.txt + echo "" >> BUILD_INFO.txt + echo "Package contents:" >> BUILD_INFO.txt + echo "-----------------" >> BUILD_INFO.txt + for rpm in *.rpm; do + echo "" >> BUILD_INFO.txt + echo "File: $rpm" >> BUILD_INFO.txt + rpm -qpi "$rpm" 2>/dev/null | grep -E "^(Name|Version|Release|Architecture|Size)" >> BUILD_INFO.txt + done + + ls -la + + - name: Upload binary RPM artifact + run: | + # Find the main binary RPM (exclude debug and source RPMs) + BIN_RPM=$(find artifacts -name "continuwuity-*.rpm" \ + ! -name "*debuginfo*" \ + ! -name "*debugsource*" \ + ! -name "*.src.rpm" \ + -type f) + + mkdir -p upload-bin + cp $BIN_RPM upload-bin/ + + - name: Upload binary RPM + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: continuwuity + path: upload-bin/ + + - name: Upload debug RPM artifact + uses: https://code.forgejo.org/actions/upload-artifact@v3 + with: + name: continuwuity-debug + path: artifacts/*debuginfo*.rpm + + - name: Publish to RPM Package Registry + if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }} + run: | + # Find the main binary RPM (exclude debug and source RPMs) + RPM=$(find artifacts -name "continuwuity-*.rpm" \ + ! -name "*debuginfo*" \ + ! -name "*debugsource*" \ + ! -name "*.src.rpm" \ + -type f | head -1) + + if [ -z "$RPM" ]; then + echo "No binary RPM found to publish" + exit 0 + fi + + RPM_BASENAME=$(basename "$RPM") + echo "Publishing: $RPM_BASENAME" + + # Determine the group based on ref type and branch + if [[ "${{ github.ref }}" == "refs/tags/"* ]]; then + GROUP="stable" + # For tags, extract the tag name for version info + TAG_NAME="${{ github.ref_name }}" + elif [ "${{ github.ref_name }}" = "main" ]; then + GROUP="dev" + else + # Use sanitized branch name as group for feature branches + GROUP=$(echo "${{ github.ref_name }}" | sed 's/[^a-zA-Z0-9]/-/g' | tr '[:upper:]' '[:lower:]' | cut -c1-30) + fi + + PACKAGE_INFO=$(rpm -qpi "$RPM" 2>/dev/null) + PACKAGE_NAME=$(echo "$PACKAGE_INFO" | grep "^Name" | awk '{print $3}') + PACKAGE_VERSION=$(echo "$PACKAGE_INFO" | grep "^Version" | awk '{print $3}') + PACKAGE_RELEASE=$(echo "$PACKAGE_INFO" | grep "^Release" | awk '{print $3}') + PACKAGE_ARCH=$(echo "$PACKAGE_INFO" | grep "^Architecture" | awk '{print $2}') + + # Full version includes release + FULL_VERSION="${PACKAGE_VERSION}-${PACKAGE_RELEASE}" + + # Forgejo's RPM registry cannot overwrite existing packages, so we must delete first + # 404 is OK if package doesn't exist yet + echo "Removing any existing package: $PACKAGE_NAME-$FULL_VERSION.$PACKAGE_ARCH" + RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/package/$PACKAGE_NAME/$FULL_VERSION/$PACKAGE_ARCH") + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + + if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then + echo "ERROR: Failed to delete package (HTTP $HTTP_CODE)" + echo "$RESPONSE" | head -n -1 + exit 1 + fi + + curl --fail-with-body \ + -X PUT \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/x-rpm" \ + -T "$RPM" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/$GROUP/upload" + + echo "" + echo "✅ Published binary RPM to: https://forgejo.ellis.link/continuwuation/-/packages/rpm/continuwuity/" + echo "Group: $GROUP" + + # Upload debug RPMs to separate group + DEBUG_RPMS=$(find artifacts -name "*debuginfo*.rpm") + if [ -n "$DEBUG_RPMS" ]; then + echo "" + echo "Publishing debug RPMs to group: ${GROUP}-debug" + + for DEBUG_RPM in $DEBUG_RPMS; do + echo "Publishing: $(basename "$DEBUG_RPM")" + + DEBUG_INFO=$(rpm -qpi "$DEBUG_RPM" 2>/dev/null) + DEBUG_NAME=$(echo "$DEBUG_INFO" | grep "^Name" | awk '{print $3}') + DEBUG_VERSION=$(echo "$DEBUG_INFO" | grep "^Version" | awk '{print $3}') + DEBUG_RELEASE=$(echo "$DEBUG_INFO" | grep "^Release" | awk '{print $3}') + DEBUG_ARCH=$(echo "$DEBUG_INFO" | grep "^Architecture" | awk '{print $2}') + DEBUG_FULL_VERSION="${DEBUG_VERSION}-${DEBUG_RELEASE}" + + # Must delete existing package first (Forgejo limitation) + RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/package/$DEBUG_NAME/$DEBUG_FULL_VERSION/$DEBUG_ARCH") + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + + if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then + echo "ERROR: Failed to delete debug package (HTTP $HTTP_CODE)" + echo "$RESPONSE" | head -n -1 + exit 1 + fi + + curl --fail-with-body \ + -X PUT \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/x-rpm" \ + -T "$DEBUG_RPM" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-debug/upload" + done + + echo "✅ Published debug RPMs to group: ${GROUP}-debug" + fi + + # Also upload the SRPM to separate group + SRPM=$(find artifacts -name "*.src.rpm" | head -1) + if [ -n "$SRPM" ]; then + echo "" + echo "Publishing source RPM: $(basename "$SRPM")" + echo "Publishing to group: ${GROUP}-src" + + SRPM_INFO=$(rpm -qpi "$SRPM" 2>/dev/null) + SRPM_NAME=$(echo "$SRPM_INFO" | grep "^Name" | awk '{print $3}') + SRPM_VERSION=$(echo "$SRPM_INFO" | grep "^Version" | awk '{print $3}') + SRPM_RELEASE=$(echo "$SRPM_INFO" | grep "^Release" | awk '{print $3}') + SRPM_FULL_VERSION="${SRPM_VERSION}-${SRPM_RELEASE}" + + # Must delete existing SRPM first (Forgejo limitation) + echo "Removing any existing SRPM: $SRPM_NAME-$SRPM_FULL_VERSION.src" + RESPONSE=$(curl -s -w "\n%{http_code}" -X DELETE \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/package/$SRPM_NAME/$SRPM_FULL_VERSION/src") + HTTP_CODE=$(echo "$RESPONSE" | tail -n1) + + if [ "$HTTP_CODE" != "204" ] && [ "$HTTP_CODE" != "404" ]; then + echo "ERROR: Failed to delete SRPM (HTTP $HTTP_CODE)" + echo "$RESPONSE" | head -n -1 + exit 1 + fi + + curl --fail-with-body \ + -X PUT \ + -H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \ + -H "Content-Type: application/x-rpm" \ + -T "$SRPM" \ + "https://forgejo.ellis.link/api/packages/continuwuation/rpm/${GROUP}-src/upload" + + echo "✅ Published source RPM to group: ${GROUP}-src" + fi diff --git a/.mailmap b/.mailmap index fa267e13..7c25737d 100644 --- a/.mailmap +++ b/.mailmap @@ -13,3 +13,4 @@ Rudi Floren Tamara Schmitz <15906939+tamara-schmitz@users.noreply.github.com> Timo Kösters x4u <14617923-x4u@users.noreply.gitlab.com> +Ginger <75683114+gingershaped@users.noreply.github.com> diff --git a/Cargo.lock b/Cargo.lock index 2b044a1f..a3962c31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4058,7 +4058,7 @@ checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" [[package]] name = "ruma" version = "0.10.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "assign", "js_int", @@ -4078,7 +4078,7 @@ dependencies = [ [[package]] name = "ruma-appservice-api" version = "0.10.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4090,7 +4090,7 @@ dependencies = [ [[package]] name = "ruma-client-api" version = "0.18.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", "assign", @@ -4113,7 +4113,7 @@ dependencies = [ [[package]] name = "ruma-common" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", "base64 0.22.1", @@ -4145,7 +4145,7 @@ dependencies = [ [[package]] name = "ruma-events" version = "0.28.1" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "as_variant", "indexmap 2.10.0", @@ -4170,7 +4170,7 @@ dependencies = [ [[package]] name = "ruma-federation-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "bytes", "headers", @@ -4192,7 +4192,7 @@ dependencies = [ [[package]] name = "ruma-identifiers-validation" version = "0.9.5" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "thiserror 2.0.12", @@ -4201,7 +4201,7 @@ dependencies = [ [[package]] name = "ruma-identity-service-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4211,7 +4211,7 @@ dependencies = [ [[package]] name = "ruma-macros" version = "0.13.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "cfg-if", "proc-macro-crate", @@ -4226,7 +4226,7 @@ dependencies = [ [[package]] name = "ruma-push-gateway-api" version = "0.9.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "js_int", "ruma-common", @@ -4238,7 +4238,7 @@ dependencies = [ [[package]] name = "ruma-signatures" version = "0.15.0" -source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=b753738047d1f443aca870896ef27ecaacf027da#b753738047d1f443aca870896ef27ecaacf027da" +source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd#8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" dependencies = [ "base64 0.22.1", "ed25519-dalek", diff --git a/Cargo.toml b/Cargo.toml index 9452066c..e2af2d94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -352,7 +352,7 @@ version = "0.1.2" [workspace.dependencies.ruma] git = "https://forgejo.ellis.link/continuwuation/ruwuma" #branch = "conduwuit-changes" -rev = "b753738047d1f443aca870896ef27ecaacf027da" +rev = "8fb268fa2771dfc3a1c8075ef1246e7c9a0a53fd" features = [ "compat", "rand", diff --git a/arch/conduwuit.service b/arch/conduwuit.service index 34c3995e..18c34f33 100644 --- a/arch/conduwuit.service +++ b/arch/conduwuit.service @@ -20,6 +20,7 @@ StandardError=journal+console Environment="CONTINUWUITY_LOG_TO_JOURNALD=true" Environment="CONTINUWUITY_JOURNALD_IDENTIFIER=%N" +Environment="CONTINUWUITY_DATABASE_PATH=/var/lib/conduwuit" TTYReset=yes # uncomment to allow buffer to be cleared every restart diff --git a/conduwuit-example.toml b/conduwuit-example.toml index f0e510b4..fa65cbf2 100644 --- a/conduwuit-example.toml +++ b/conduwuit-example.toml @@ -79,9 +79,11 @@ # This is the only directory where continuwuity will save its data, # including media. Note: this was previously "/var/lib/matrix-conduit". # -# YOU NEED TO EDIT THIS. +# YOU NEED TO EDIT THIS, UNLESS you are running continuwuity as a `systemd` service. +# The service file sets it to `/var/lib/conduwuit` using an environment variable +# and also grants write access. # -# example: "/var/lib/continuwuity" +# example: "/var/lib/conduwuit" # #database_path = diff --git a/debian/conduwuit.service b/debian/conduwuit.service index da78f09f..ec2505b5 100644 --- a/debian/conduwuit.service +++ b/debian/conduwuit.service @@ -16,6 +16,7 @@ Environment="CONTINUWUITY_CONFIG=/etc/conduwuit/conduwuit.toml" Environment="CONTINUWUITY_LOG_TO_JOURNALD=true" Environment="CONTINUWUITY_JOURNALD_IDENTIFIER=%N" +Environment="CONTINUWUITY_DATABASE_PATH=/var/lib/conduwuit" ExecStart=/usr/sbin/conduwuit diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fa097238..8936a1ef 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -10,6 +10,7 @@ - [Kubernetes](deploying/kubernetes.md) - [Arch Linux](deploying/arch-linux.md) - [Debian](deploying/debian.md) + - [Fedora](deploying/fedora.md) - [FreeBSD](deploying/freebsd.md) - [TURN](turn.md) - [Appservices](appservices.md) diff --git a/docs/admin_reference.md b/docs/admin_reference.md index 18e039e4..1c9d4fb0 100644 --- a/docs/admin_reference.md +++ b/docs/admin_reference.md @@ -21,6 +21,7 @@ This document contains the help content for the `admin` command-line program. * [`admin users list-joined-rooms`↴](#admin-users-list-joined-rooms) * [`admin users force-join-room`↴](#admin-users-force-join-room) * [`admin users force-leave-room`↴](#admin-users-force-leave-room) +* [`admin users force-leave-remote-room`↴](#admin-users-force-leave-remote-room) * [`admin users force-demote`↴](#admin-users-force-demote) * [`admin users make-user-admin`↴](#admin-users-make-user-admin) * [`admin users put-room-tag`↴](#admin-users-put-room-tag) @@ -295,6 +296,7 @@ You can find the ID using the `list-appservices` command. * `list-joined-rooms` — - Lists all the rooms (local and remote) that the specified user is joined in * `force-join-room` — - Manually join a local user to a room * `force-leave-room` — - Manually leave a local user from a room +* `force-leave-remote-room` — - Manually leave a remote room for a local user * `force-demote` — - Forces the specified user to drop their power levels to the room default, if their permissions allow and the auth check permits * `make-user-admin` — - Grant server-admin privileges to a user * `put-room-tag` — - Puts a room tag for the specified user and room ID @@ -449,6 +451,19 @@ Reverses the effects of the `suspend` command, allowing the user to send message +## `admin users force-leave-remote-room` + +- Manually leave a remote room for a local user + +**Usage:** `admin users force-leave-remote-room ` + +###### **Arguments:** + +* `` +* `` + + + ## `admin users force-demote` - Forces the specified user to drop their power levels to the room default, if their permissions allow and the auth check permits diff --git a/docs/deploying/fedora.md b/docs/deploying/fedora.md new file mode 100644 index 00000000..0130809b --- /dev/null +++ b/docs/deploying/fedora.md @@ -0,0 +1,201 @@ +# RPM Installation Guide + +Continuwuity is available as RPM packages for Fedora, RHEL, and compatible distributions. + +The RPM packaging files are maintained in the `fedora/` directory: +- `continuwuity.spec.rpkg` - RPM spec file using rpkg macros for building from git +- `continuwuity.service` - Systemd service file for the server +- `RPM-GPG-KEY-continuwuity.asc` - GPG public key for verifying signed packages + +RPM packages built by CI are signed with our GPG key (Ed25519, ID: `5E0FF73F411AAFCA`). + +```bash +# Import the signing key +sudo rpm --import https://forgejo.ellis.link/continuwuation/continuwuity/raw/branch/main/fedora/RPM-GPG-KEY-continuwuity.asc + +# Verify a downloaded package +rpm --checksig continuwuity-*.rpm +``` + +## Installation methods + +**Stable releases** (recommended) + +```bash +# Add the repository and install +sudo dnf config-manager addrepo --from-repofile=https://forgejo.ellis.link/api/packages/continuwuation/rpm/stable/continuwuation.repo +sudo dnf install continuwuity +``` + +**Development builds** from main branch + +```bash +# Add the dev repository and install +sudo dnf config-manager addrepo --from-repofile=https://forgejo.ellis.link/api/packages/continuwuation/rpm/dev/continuwuation.repo +sudo dnf install continuwuity +``` + +**Feature branch builds** (example: `tom/new-feature`) + +```bash +# Branch names are sanitized (slashes become hyphens, lowercase only) +sudo dnf config-manager addrepo --from-repofile=https://forgejo.ellis.link/api/packages/continuwuation/rpm/tom-new-feature/continuwuation.repo +sudo dnf install continuwuity +``` + +**Direct installation** without adding repository + +```bash +# Latest stable release +sudo dnf install https://forgejo.ellis.link/api/packages/continuwuation/rpm/stable/continuwuity + +# Latest development build +sudo dnf install https://forgejo.ellis.link/api/packages/continuwuation/rpm/dev/continuwuity + +# Specific feature branch +sudo dnf install https://forgejo.ellis.link/api/packages/continuwuation/rpm/branch-name/continuwuity +``` + +**Manual repository configuration** (alternative method) + +```bash +cat << 'EOF' | sudo tee /etc/yum.repos.d/continuwuity.repo +[continuwuity] +name=Continuwuity - Matrix homeserver +baseurl=https://forgejo.ellis.link/api/packages/continuwuation/rpm/stable +enabled=1 +gpgcheck=1 +gpgkey=https://forgejo.ellis.link/continuwuation/continuwuity/raw/branch/main/fedora/RPM-GPG-KEY-continuwuity.asc +EOF + +sudo dnf install continuwuity +``` + +## Package management + +**Automatic updates** with DNF Automatic + +```bash +# Install and configure +sudo dnf install dnf-automatic +sudo nano /etc/dnf/automatic.conf # Set: apply_updates = yes +sudo systemctl enable --now dnf-automatic.timer +``` + +**Manual updates** + +```bash +# Check for updates +sudo dnf check-update continuwuity + +# Update to latest version +sudo dnf update continuwuity +``` + +**Switching channels** (stable/dev/feature branches) + +```bash +# List enabled repositories +dnf repolist | grep continuwuation + +# Disable current repository +sudo dnf config-manager --set-disabled continuwuation-stable # or -dev, or branch name + +# Enable desired repository +sudo dnf config-manager --set-enabled continuwuation-dev # or -stable, or branch name + +# Update to the new channel's version +sudo dnf update continuwuity +``` + +**Verifying installation** + +```bash +# Check installed version +rpm -q continuwuity + +# View package information +rpm -qi continuwuity + +# List installed files +rpm -ql continuwuity + +# Verify package integrity +rpm -V continuwuity +``` + +## Service management and removal + +**Systemd service commands** + +```bash +# Start the service +sudo systemctl start conduwuit + +# Enable on boot +sudo systemctl enable conduwuit + +# Check status +sudo systemctl status conduwuit + +# View logs +sudo journalctl -u conduwuit -f +``` + +**Uninstallation** + +```bash +# Stop and disable the service +sudo systemctl stop conduwuit +sudo systemctl disable conduwuit + +# Remove the package +sudo dnf remove continuwuity + +# Remove the repository (optional) +sudo rm /etc/yum.repos.d/continuwuation-*.repo +``` + +## Troubleshooting + +**GPG key errors**: Temporarily disable GPG checking + +```bash +sudo dnf --nogpgcheck install continuwuity +``` + +**Repository metadata issues**: Clear and rebuild cache + +```bash +sudo dnf clean all +sudo dnf makecache +``` + +**Finding specific versions** + +```bash +# List all available versions +dnf --showduplicates list continuwuity + +# Install a specific version +sudo dnf install continuwuity- +``` + +## Building locally + +Build the RPM locally using rpkg: + +```bash +# Install dependencies +sudo dnf install rpkg rpm-build cargo-rpm-macros systemd-rpm-macros + +# Clone the repository +git clone https://forgejo.ellis.link/continuwuation/continuwuity.git +cd continuwuity + +# Build SRPM +rpkg srpm + +# Build RPM +rpmbuild --rebuild *.src.rpm +``` diff --git a/fedora/RPM-GPG-KEY-continuwuity.asc b/fedora/RPM-GPG-KEY-continuwuity.asc new file mode 100644 index 00000000..031128ac --- /dev/null +++ b/fedora/RPM-GPG-KEY-continuwuity.asc @@ -0,0 +1,16 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mDMEaLM5LhYJKwYBBAHaRw8BAQdAlnMcp/fMzYfwqeExDsEx2qfZg8NjamGh0slC +9bkUpQW0O0NvbnRpbnV3dWl0eSBDSSAoUlBNIFBhY2thZ2UgU2lnbmluZykgPGNp +QGNvbnRpbnV3dWl0eS5vcmc+iJYEExYIAD4WIQShcq3anZQUJ0FNTm1eD/c/QRqv +ygUCaLM5LgIbAwUJA8JnAAULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRBeD/c/ +QRqvyk3QAQCjurJLpDANckZflsEVRwxDOUCrED4LdyWpbOuVmhGikwD/fGwkpdUa +ngP1l+bhlprJN5J1P5UOeNZtKce0vFZaBwC4MwRoszkuFgkrBgEEAdpHDwEBB0CJ +RpQlzJt/TdYx8AOkNIYan6qbxijjjpZWDIbZp95CfIj1BBgWCAAmFiEEoXKt2p2U +FCdBTU5tXg/3P0Ear8oFAmizOS4CGwIFCQPCZwAAgQkQXg/3P0Ear8p2IAQZFggA +HRYhBN/tBNmxKe70FHf4CRoGaPIa/K9qBQJoszkuAAoJEBoGaPIa/K9qf7EBAJ9D +pdKRji4gy9LWR3w9Ha7Tekmw7kSPGYLZlkDqjiuCAQCCupMGB9r2XPc2/G/KIV+7 +HpWfIANhPsCn1Q9kcloCCIv9AQCy+xDsdtkOw7JnB4g1EKfPlPhN6j3Cjk1vlG2N +WN/p2AEAkozKVDAbvWEi/s7W9DNWckXm1SS0Og/sv5nGV8okIg4= +=dxDr +-----END PGP PUBLIC KEY BLOCK----- diff --git a/fedora/conduwuit.service b/fedora/conduwuit.service index 6ab2af46..f37c7798 100644 --- a/fedora/conduwuit.service +++ b/fedora/conduwuit.service @@ -15,6 +15,7 @@ Environment="CONTINUWUITY_CONFIG=/etc/conduwuit/conduwuit.toml" Environment="CONTINUWUITY_LOG_TO_JOURNALD=true" Environment="CONTINUWUITY_JOURNALD_IDENTIFIER=%N" +Environment="CONTINUWUITY_DATABASE_PATH=/var/lib/conduwuit" ExecStart=/usr/bin/conduwuit diff --git a/fedora/continuwuity.spec.rpkg b/fedora/continuwuity.spec.rpkg index f2efa383..4ff7dbe6 100644 --- a/fedora/continuwuity.spec.rpkg +++ b/fedora/continuwuity.spec.rpkg @@ -1,6 +1,5 @@ -# This should be run using rpkg-util: https://docs.pagure.org/rpkg-util +# This should be run using rpkg: https://docs.pagure.org/rpkg # it requires Internet access and is not suitable for Fedora main repos -# TODO: rpkg-util is no longer maintained, find a replacement Name: continuwuity Version: {{{ git_repo_version }}} diff --git a/src/admin/user/commands.rs b/src/admin/user/commands.rs index 56864a32..37ab030c 100644 --- a/src/admin/user/commands.rs +++ b/src/admin/user/commands.rs @@ -1,8 +1,8 @@ use std::{collections::BTreeMap, fmt::Write as _}; use api::client::{ - full_user_deactivate, join_room_by_id_helper, leave_all_rooms, leave_room, update_avatar_url, - update_displayname, + full_user_deactivate, join_room_by_id_helper, leave_all_rooms, leave_room, remote_leave_room, + update_avatar_url, update_displayname, }; use conduwuit::{ Err, Result, debug, debug_warn, error, info, is_equal_to, @@ -926,3 +926,29 @@ pub(super) async fn redact_event(&self, event_id: OwnedEventId) -> Result { )) .await } + +#[admin_command] +pub(super) async fn force_leave_remote_room( + &self, + user_id: String, + room_id: OwnedRoomOrAliasId, +) -> Result { + let user_id = parse_local_user_id(self.services, &user_id)?; + let (room_id, _) = self + .services + .rooms + .alias + .resolve_with_servers(&room_id, None) + .await?; + + assert!( + self.services.globals.user_is_local(&user_id), + "Parsed user_id must be a local user" + ); + remote_leave_room(self.services, &user_id, &room_id, None) + .boxed() + .await?; + + self.write_str(&format!("{user_id} has been joined to {room_id}.",)) + .await +} diff --git a/src/admin/user/mod.rs b/src/admin/user/mod.rs index 656cacaf..366f7dd5 100644 --- a/src/admin/user/mod.rs +++ b/src/admin/user/mod.rs @@ -103,6 +103,12 @@ pub enum UserCommand { room_id: OwnedRoomOrAliasId, }, + /// - Manually leave a remote room for a local user. + ForceLeaveRemoteRoom { + user_id: String, + room_id: OwnedRoomOrAliasId, + }, + /// - Forces the specified user to drop their power levels to the room /// default, if their permissions allow and the auth check permits ForceDemote { diff --git a/src/api/client/admin/mod.rs b/src/api/client/admin/mod.rs new file mode 100644 index 00000000..8355a600 --- /dev/null +++ b/src/api/client/admin/mod.rs @@ -0,0 +1,3 @@ +mod suspend; + +pub(crate) use self::suspend::*; diff --git a/src/api/client/admin/suspend.rs b/src/api/client/admin/suspend.rs new file mode 100644 index 00000000..bab1cb5a --- /dev/null +++ b/src/api/client/admin/suspend.rs @@ -0,0 +1,89 @@ +use axum::extract::State; +use conduwuit::{Err, Result}; +use futures::future::{join, join3}; +use ruma::api::client::admin::{get_suspended, set_suspended}; + +use crate::Ruma; + +/// # `GET /_matrix/client/v1/admin/suspend/{userId}` +/// +/// Check the suspension status of a target user +pub(crate) async fn get_suspended_status( + State(services): State, + body: Ruma, +) -> Result { + let sender_user = body.sender_user(); + + let (admin, active) = + join(services.users.is_admin(sender_user), services.users.is_active(&body.user_id)).await; + if !admin { + return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); + } + if !services.globals.user_is_local(&body.user_id) { + return Err!(Request(InvalidParam("Can only check the suspended status of local users"))); + } + if !active { + return Err!(Request(NotFound("Unknown user"))); + } + Ok(get_suspended::v1::Response::new( + services.users.is_suspended(&body.user_id).await?, + )) +} + +/// # `PUT /_matrix/client/v1/admin/suspend/{userId}` +/// +/// Set the suspension status of a target user +pub(crate) async fn put_suspended_status( + State(services): State, + body: Ruma, +) -> Result { + let sender_user = body.sender_user(); + + let (sender_admin, active, target_admin) = join3( + services.users.is_admin(sender_user), + services.users.is_active(&body.user_id), + services.users.is_admin(&body.user_id), + ) + .await; + + if !sender_admin { + return Err!(Request(Forbidden("Only server administrators can use this endpoint"))); + } + if !services.globals.user_is_local(&body.user_id) { + return Err!(Request(InvalidParam("Can only set the suspended status of local users"))); + } + if !active { + return Err!(Request(NotFound("Unknown user"))); + } + if body.user_id == *sender_user { + return Err!(Request(Forbidden("You cannot suspend yourself"))); + } + if target_admin { + return Err!(Request(Forbidden("You cannot suspend another server administrator"))); + } + if services.users.is_suspended(&body.user_id).await? == body.suspended { + // No change + return Ok(set_suspended::v1::Response::new(body.suspended)); + } + + let action = if body.suspended { + services + .users + .suspend_account(&body.user_id, sender_user) + .await; + "suspended" + } else { + services.users.unsuspend_account(&body.user_id).await; + "unsuspended" + }; + + if services.config.admin_room_notices { + // Notify the admin room that an account has been un/suspended + services + .admin + .send_text(&format!("{} has been {} by {}.", body.user_id, action, sender_user)) + .await; + } + + Ok(set_suspended::v1::Response::new(body.suspended)) +} diff --git a/src/api/client/capabilities.rs b/src/api/client/capabilities.rs index c42c6dfd..afa61498 100644 --- a/src/api/client/capabilities.rs +++ b/src/api/client/capabilities.rs @@ -19,7 +19,7 @@ use crate::Ruma; /// of this server. pub(crate) async fn get_capabilities_route( State(services): State, - _body: Ruma, + body: Ruma, ) -> Result { let available: BTreeMap = Server::available_room_versions().collect(); @@ -45,5 +45,14 @@ pub(crate) async fn get_capabilities_route( json!({"enabled": services.config.forget_forced_upon_leave}), )?; + if services + .users + .is_admin(body.sender_user.as_ref().unwrap()) + .await + { + // Advertise suspension API + capabilities.set("uk.timedout.msc4323", json!({"suspend":true, "lock": false}))?; + } + Ok(get_capabilities::v3::Response { capabilities }) } diff --git a/src/api/client/membership/join.rs b/src/api/client/membership/join.rs index dc170cbf..f3434bf5 100644 --- a/src/api/client/membership/join.rs +++ b/src/api/client/membership/join.rs @@ -156,31 +156,34 @@ pub(crate) async fn join_room_by_id_or_alias_route( .await?; let mut servers = body.via.clone(); - servers.extend( - services - .rooms - .state_cache - .servers_invite_via(&room_id) - .map(ToOwned::to_owned) - .collect::>() - .await, - ); + if servers.is_empty() { + debug!("No via servers provided for join, injecting some."); + servers.extend( + services + .rooms + .state_cache + .servers_invite_via(&room_id) + .map(ToOwned::to_owned) + .collect::>() + .await, + ); - servers.extend( - services - .rooms - .state_cache - .invite_state(sender_user, &room_id) - .await - .unwrap_or_default() - .iter() - .filter_map(|event| event.get_field("sender").ok().flatten()) - .filter_map(|sender: &str| UserId::parse(sender).ok()) - .map(|user| user.server_name().to_owned()), - ); + servers.extend( + services + .rooms + .state_cache + .invite_state(sender_user, &room_id) + .await + .unwrap_or_default() + .iter() + .filter_map(|event| event.get_field("sender").ok().flatten()) + .filter_map(|sender: &str| UserId::parse(sender).ok()) + .map(|user| user.server_name().to_owned()), + ); - if let Some(server) = room_id.server_name() { - servers.push(server.to_owned()); + if let Some(server) = room_id.server_name() { + servers.push(server.to_owned()); + } } servers.sort_unstable(); diff --git a/src/api/client/membership/leave.rs b/src/api/client/membership/leave.rs index f4f1666b..0aadd833 100644 --- a/src/api/client/membership/leave.rs +++ b/src/api/client/membership/leave.rs @@ -215,7 +215,7 @@ pub async fn leave_room( Ok(()) } -async fn remote_leave_room( +pub async fn remote_leave_room( services: &Services, user_id: &UserId, room_id: &RoomId, diff --git a/src/api/client/membership/mod.rs b/src/api/client/membership/mod.rs index 7a6f19ad..691419f6 100644 --- a/src/api/client/membership/mod.rs +++ b/src/api/client/membership/mod.rs @@ -29,7 +29,7 @@ pub(crate) use self::{ }; pub use self::{ join::join_room_by_id_helper, - leave::{leave_all_rooms, leave_room}, + leave::{leave_all_rooms, leave_room, remote_leave_room}, }; use crate::{Ruma, client::full_user_deactivate}; diff --git a/src/api/client/mod.rs b/src/api/client/mod.rs index e4be20b7..c8ca7757 100644 --- a/src/api/client/mod.rs +++ b/src/api/client/mod.rs @@ -1,5 +1,6 @@ pub(super) mod account; pub(super) mod account_data; +pub(super) mod admin; pub(super) mod alias; pub(super) mod appservice; pub(super) mod backup; @@ -43,6 +44,7 @@ pub(super) mod well_known; pub use account::full_user_deactivate; pub(super) use account::*; pub(super) use account_data::*; +pub(super) use admin::*; pub(super) use alias::*; pub(super) use appservice::*; pub(super) use backup::*; @@ -55,7 +57,7 @@ pub(super) use keys::*; pub(super) use media::*; pub(super) use media_legacy::*; pub(super) use membership::*; -pub use membership::{join_room_by_id_helper, leave_all_rooms, leave_room}; +pub use membership::{join_room_by_id_helper, leave_all_rooms, leave_room, remote_leave_room}; pub(super) use message::*; pub(super) use openid::*; pub(super) use presence::*; diff --git a/src/api/client/unversioned.rs b/src/api/client/unversioned.rs index a4136d1a..7f19bc94 100644 --- a/src/api/client/unversioned.rs +++ b/src/api/client/unversioned.rs @@ -58,6 +58,7 @@ pub(crate) async fn get_supported_versions_route( ("uk.tcpip.msc4133".to_owned(), true), /* Extending User Profile API with Key:Value Pairs (https://github.com/matrix-org/matrix-spec-proposals/pull/4133) */ ("us.cloke.msc4175".to_owned(), true), /* Profile field for user time zone (https://github.com/matrix-org/matrix-spec-proposals/pull/4175) */ ("org.matrix.simplified_msc3575".to_owned(), true), /* Simplified Sliding sync (https://github.com/matrix-org/matrix-spec-proposals/pull/4186) */ + ("uk.timedout.msc4323".to_owned(), true), /* agnostic suspend (https://github.com/matrix-org/matrix-spec-proposals/pull/4323) */ ]), }; diff --git a/src/api/router.rs b/src/api/router.rs index 8072fa5b..42934f70 100644 --- a/src/api/router.rs +++ b/src/api/router.rs @@ -184,6 +184,8 @@ pub fn build(router: Router, server: &Server) -> Router { "/_matrix/client/unstable/im.nheko.summary/rooms/:room_id_or_alias/summary", get(client::get_room_summary_legacy) ) + .ruma_route(&client::get_suspended_status) + .ruma_route(&client::put_suspended_status) .ruma_route(&client::well_known_support) .ruma_route(&client::well_known_client) .route("/_conduwuit/server_version", get(client::conduwuit_server_version)) diff --git a/src/core/config/mod.rs b/src/core/config/mod.rs index e8518ed4..58a39a75 100644 --- a/src/core/config/mod.rs +++ b/src/core/config/mod.rs @@ -126,9 +126,11 @@ pub struct Config { /// This is the only directory where continuwuity will save its data, /// including media. Note: this was previously "/var/lib/matrix-conduit". /// - /// YOU NEED TO EDIT THIS. + /// YOU NEED TO EDIT THIS, UNLESS you are running continuwuity as a `systemd` service. + /// The service file sets it to `/var/lib/conduwuit` using an environment variable + /// and also grants write access. /// - /// example: "/var/lib/continuwuity" + /// example: "/var/lib/conduwuit" pub database_path: PathBuf, /// continuwuity supports online database backups using RocksDB's Backup