mirror of
https://forgejo.ellis.link/continuwuation/continuwuity.git
synced 2026-05-26 20:49:55 +00:00
Compare commits
36 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9d0c89bd04 | |||
| 965db4aa43 | |||
| 472e1fee17 | |||
| 3c6f2d07e0 | |||
| 43254aa396 | |||
| 48ebf86335 | |||
| f1e3b4907e | |||
| 9346a0d05e | |||
| c99faae115 | |||
| a5aa68ee8d | |||
| 8959ac06ac | |||
| 47f7ebfd68 | |||
| 7d91f218b1 | |||
| e5e2db37d9 | |||
| e08ea3b9e5 | |||
| 4f1907abfa | |||
| 92d74c293e | |||
| 3fbdced0e1 | |||
| b70470fa71 | |||
| 703d6a2075 | |||
| 5b75e21810 | |||
| 13b7538785 | |||
| 9745bcba1c | |||
| c9c79fbea6 | |||
| 92e9802340 | |||
| 1d80b7ce0c | |||
| 563b6d4b30 | |||
| e86fc6d9f8 | |||
| 13adea6498 | |||
| 17d0bb6cf6 | |||
| 6dc5051fa6 | |||
| 3034c03ad1 | |||
| fa6f549d39 | |||
| 999217b0f6 | |||
| 74fccff2cc | |||
| 7a56a2462c |
@@ -61,14 +61,16 @@ runs:
|
|||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@v5
|
uses: docker/metadata-action@v5
|
||||||
with:
|
with:
|
||||||
|
flavor: |
|
||||||
|
suffix=${{ inputs.tag_suffix }},onlatest=true
|
||||||
tags: |
|
tags: |
|
||||||
type=semver,pattern={{version}},prefix=v,suffix=${{ inputs.tag_suffix }}
|
type=semver,pattern={{version}},prefix=v
|
||||||
type=semver,pattern={{major}}.{{minor}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.0.') }},prefix=v,suffix=${{ inputs.tag_suffix }}
|
type=semver,pattern={{major}}.{{minor}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.0.') }},prefix=v
|
||||||
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }},prefix=v,suffix=${{ inputs.tag_suffix }}
|
type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/v0.') }},prefix=v
|
||||||
type=ref,event=branch,prefix=${{ format('refs/heads/{0}', github.event.repository.default_branch) != github.ref && 'branch-' || '' }},suffix=${{ inputs.tag_suffix }}
|
type=ref,event=branch,prefix=${{ format('refs/heads/{0}', github.event.repository.default_branch) != github.ref && 'branch-' || '' }},
|
||||||
type=ref,event=pr,suffix=${{ inputs.tag_suffix }}
|
type=ref,event=pr
|
||||||
type=sha,format=short,suffix=${{ inputs.tag_suffix }}
|
type=sha,format=short
|
||||||
type=raw,value=latest${{ inputs.tag_suffix }},enable=${{ startsWith(github.ref, 'refs/tags/v') }}
|
type=raw,value=latest${{ inputs.tag_suffix }},enable=${{ startsWith(github.ref, 'refs/tags/v') }},priority=1100
|
||||||
images: ${{ inputs.images }}
|
images: ${{ inputs.images }}
|
||||||
# default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509
|
# default labels & annotations: https://github.com/docker/metadata-action/blob/master/src/meta.ts#L509
|
||||||
env:
|
env:
|
||||||
@@ -81,6 +83,7 @@ runs:
|
|||||||
env:
|
env:
|
||||||
IMAGES: ${{ inputs.images }}
|
IMAGES: ${{ inputs.images }}
|
||||||
run: |
|
run: |
|
||||||
|
set -o xtrace
|
||||||
IFS=$'\n'
|
IFS=$'\n'
|
||||||
IMAGES_LIST=($IMAGES)
|
IMAGES_LIST=($IMAGES)
|
||||||
ANNOTATIONS_LIST=($DOCKER_METADATA_OUTPUT_ANNOTATIONS)
|
ANNOTATIONS_LIST=($DOCKER_METADATA_OUTPUT_ANNOTATIONS)
|
||||||
@@ -98,6 +101,7 @@ runs:
|
|||||||
env:
|
env:
|
||||||
IMAGES: ${{ inputs.images }}
|
IMAGES: ${{ inputs.images }}
|
||||||
run: |
|
run: |
|
||||||
|
set -o xtrace
|
||||||
IMAGES_LIST=($IMAGES)
|
IMAGES_LIST=($IMAGES)
|
||||||
for REPO in "${IMAGES_LIST[@]}"; do
|
for REPO in "${IMAGES_LIST[@]}"; do
|
||||||
docker buildx imagetools inspect $REPO:${{ steps.meta.outputs.version }}
|
docker buildx imagetools inspect $REPO:${{ steps.meta.outputs.version }}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
name: detect-runner-os
|
|
||||||
description: |
|
|
||||||
Detect the actual OS name and version of the runner.
|
|
||||||
Provides separate outputs for name, version, and a combined slug.
|
|
||||||
|
|
||||||
outputs:
|
|
||||||
name:
|
|
||||||
description: 'OS name (e.g. Ubuntu, Debian)'
|
|
||||||
value: ${{ steps.detect.outputs.name }}
|
|
||||||
version:
|
|
||||||
description: 'OS version (e.g. 22.04, 11)'
|
|
||||||
value: ${{ steps.detect.outputs.version }}
|
|
||||||
slug:
|
|
||||||
description: 'Combined OS slug (e.g. Ubuntu-22.04)'
|
|
||||||
value: ${{ steps.detect.outputs.slug }}
|
|
||||||
node_major:
|
|
||||||
description: 'Major version of Node.js if available (e.g. 22)'
|
|
||||||
value: ${{ steps.detect.outputs.node_major }}
|
|
||||||
node_version:
|
|
||||||
description: 'Full Node.js version if available (e.g. 22.19.0)'
|
|
||||||
value: ${{ steps.detect.outputs.node_version }}
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: composite
|
|
||||||
steps:
|
|
||||||
- name: Detect runner OS
|
|
||||||
id: detect
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
# Detect OS version (try lsb_release first, fall back to /etc/os-release)
|
|
||||||
OS_VERSION=$(lsb_release -rs 2>/dev/null || grep VERSION_ID /etc/os-release | cut -d'"' -f2)
|
|
||||||
|
|
||||||
# Detect OS name and capitalise (try lsb_release first, fall back to /etc/os-release)
|
|
||||||
OS_NAME=$(lsb_release -is 2>/dev/null || grep "^ID=" /etc/os-release | cut -d'=' -f2 | tr -d '"' | sed 's/\b\(.\)/\u\1/g')
|
|
||||||
|
|
||||||
# Create combined slug
|
|
||||||
OS_SLUG="${OS_NAME}-${OS_VERSION}"
|
|
||||||
|
|
||||||
# Detect Node.js version if available
|
|
||||||
if command -v node >/dev/null 2>&1; then
|
|
||||||
NODE_VERSION=$(node --version | sed 's/v//')
|
|
||||||
NODE_MAJOR=$(echo $NODE_VERSION | cut -d. -f1)
|
|
||||||
echo "node_version=${NODE_VERSION}" >> $GITHUB_OUTPUT
|
|
||||||
echo "node_major=${NODE_MAJOR}" >> $GITHUB_OUTPUT
|
|
||||||
echo "🔍 Detected Node.js: v${NODE_VERSION}"
|
|
||||||
else
|
|
||||||
echo "node_version=" >> $GITHUB_OUTPUT
|
|
||||||
echo "node_major=" >> $GITHUB_OUTPUT
|
|
||||||
echo "🔍 Node.js not found"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Set OS outputs
|
|
||||||
echo "name=${OS_NAME}" >> $GITHUB_OUTPUT
|
|
||||||
echo "version=${OS_VERSION}" >> $GITHUB_OUTPUT
|
|
||||||
echo "slug=${OS_SLUG}" >> $GITHUB_OUTPUT
|
|
||||||
|
|
||||||
# Log detection results
|
|
||||||
echo "🔍 Detected Runner OS: ${OS_NAME} ${OS_VERSION}"
|
|
||||||
@@ -121,7 +121,7 @@ runs:
|
|||||||
.cargo/git/checkouts
|
.cargo/git/checkouts
|
||||||
.cargo/registry
|
.cargo/registry
|
||||||
.cargo/registry/src
|
.cargo/registry/src
|
||||||
key: rust-registry-image-${{hashFiles('**/Cargo.lock') }}
|
key: continuwuity-rust-registry-image-${{hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: Cache cargo target
|
- name: Cache cargo target
|
||||||
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
||||||
@@ -130,7 +130,7 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
cargo-target${{ env.CPU_SUFFIX }}-${{ inputs.slug }}-${{ inputs.profile }}
|
cargo-target${{ env.CPU_SUFFIX }}-${{ inputs.slug }}-${{ inputs.profile }}
|
||||||
key: cargo-target${{ env.CPU_SUFFIX }}-${{ inputs.slug }}-${{ inputs.profile }}-${{hashFiles('**/Cargo.lock') }}-${{steps.rust-toolchain.outputs.rustc_version}}
|
key: continuwuity-cargo-target${{ env.CPU_SUFFIX }}-${{ inputs.slug }}-${{ inputs.profile }}-${{hashFiles('**/Cargo.lock') }}-${{steps.rust-toolchain.outputs.rustc_version}}
|
||||||
|
|
||||||
- name: Cache apt cache
|
- name: Cache apt cache
|
||||||
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
||||||
@@ -139,7 +139,7 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
var-cache-apt-${{ inputs.slug }}
|
var-cache-apt-${{ inputs.slug }}
|
||||||
key: var-cache-apt-${{ inputs.slug }}
|
key: continuwuity-var-cache-apt-${{ inputs.slug }}
|
||||||
|
|
||||||
- name: Cache apt lib
|
- name: Cache apt lib
|
||||||
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
||||||
@@ -148,7 +148,7 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
var-lib-apt-${{ inputs.slug }}
|
var-lib-apt-${{ inputs.slug }}
|
||||||
key: var-lib-apt-${{ inputs.slug }}
|
key: continuwuity-var-lib-apt-${{ inputs.slug }}
|
||||||
|
|
||||||
- name: inject cache into docker
|
- name: inject cache into docker
|
||||||
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
if: ${{ env.BUILDKIT_ENDPOINT == '' }}
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ runs:
|
|||||||
!~/.rustup/tmp
|
!~/.rustup/tmp
|
||||||
!~/.rustup/downloads
|
!~/.rustup/downloads
|
||||||
# Requires repo to be cloned if toolchain is not specified
|
# Requires repo to be cloned if toolchain is not specified
|
||||||
key: ${{ runner.os }}-rustup-${{ inputs.toolchain || hashFiles('**/rust-toolchain.toml') }}
|
key: continuwuity-${{ runner.os }}-rustup-${{ inputs.toolchain || hashFiles('**/rust-toolchain.toml') }}
|
||||||
- name: Install Rust toolchain
|
- name: Install Rust toolchain
|
||||||
if: steps.rustup-version.outputs.version == ''
|
if: steps.rustup-version.outputs.version == ''
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ runs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Detect runner OS
|
- name: Detect runner OS
|
||||||
id: runner-os
|
id: runner-os
|
||||||
uses: ./.forgejo/actions/detect-runner-os
|
uses: https://git.tomfos.tr/actions/detect-versions@v1
|
||||||
|
|
||||||
- name: Configure cross-compilation architecture
|
- name: Configure cross-compilation architecture
|
||||||
if: inputs.dpkg-arch != ''
|
if: inputs.dpkg-arch != ''
|
||||||
@@ -69,7 +69,7 @@ runs:
|
|||||||
/usr/lib/x86_64-linux-gnu/libclang*.so*
|
/usr/lib/x86_64-linux-gnu/libclang*.so*
|
||||||
/etc/apt/sources.list.d/archive_uri-*
|
/etc/apt/sources.list.d/archive_uri-*
|
||||||
/etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
/etc/apt/trusted.gpg.d/apt.llvm.org.asc
|
||||||
key: llvm-${{ steps.runner-os.outputs.slug }}-v${{ inputs.llvm-version }}-v3-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }}
|
key: continuwuity-llvm-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-v${{ inputs.llvm-version }}-${{ hashFiles('**/Cargo.lock', 'rust-toolchain.toml') }}
|
||||||
|
|
||||||
- name: End LLVM cache group
|
- name: End LLVM cache group
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ runs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Detect runner OS
|
- name: Detect runner OS
|
||||||
id: runner-os
|
id: runner-os
|
||||||
uses: ./.forgejo/actions/detect-runner-os
|
uses: https://git.tomfos.tr/actions/detect-versions@v1
|
||||||
|
|
||||||
- name: Configure Cargo environment
|
- name: Configure Cargo environment
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -73,9 +73,9 @@ runs:
|
|||||||
.cargo/git/db
|
.cargo/git/db
|
||||||
# Registry cache saved per workflow, restored from any workflow's cache
|
# Registry cache saved per workflow, restored from any workflow's cache
|
||||||
# Each workflow maintains its own registry that accumulates its needed crates
|
# Each workflow maintains its own registry that accumulates its needed crates
|
||||||
key: cargo-registry-${{ steps.runner-os.outputs.slug }}-${{ github.workflow }}
|
key: continuwuity-cargo-registry-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ github.workflow }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
cargo-registry-${{ steps.runner-os.outputs.slug }}-
|
continuwuity-cargo-registry-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-
|
||||||
|
|
||||||
- name: Cache toolchain binaries
|
- name: Cache toolchain binaries
|
||||||
id: toolchain-cache
|
id: toolchain-cache
|
||||||
@@ -86,29 +86,42 @@ runs:
|
|||||||
.rustup/toolchains
|
.rustup/toolchains
|
||||||
.rustup/update-hashes
|
.rustup/update-hashes
|
||||||
# Shared toolchain cache across all Rust versions
|
# Shared toolchain cache across all Rust versions
|
||||||
key: toolchain-${{ steps.runner-os.outputs.slug }}
|
key: continuwuity-toolchain-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}
|
||||||
|
|
||||||
|
|
||||||
- name: Setup sccache
|
- name: Setup sccache
|
||||||
uses: https://git.tomfos.tr/tom/sccache-action@v1
|
uses: https://git.tomfos.tr/tom/sccache-action@v1
|
||||||
|
|
||||||
- name: Cache build artifacts
|
- name: Cache dependencies
|
||||||
id: build-cache
|
id: deps-cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
target/**/deps
|
|
||||||
!target/**/deps/*.rlib
|
|
||||||
target/**/build
|
|
||||||
target/**/.fingerprint
|
target/**/.fingerprint
|
||||||
target/**/incremental
|
target/**/deps
|
||||||
target/**/*.d
|
target/**/*.d
|
||||||
|
target/**/.cargo-lock
|
||||||
|
target/**/CACHEDIR.TAG
|
||||||
|
target/**/.rustc_info.json
|
||||||
/timelord/
|
/timelord/
|
||||||
# Build artifacts - cache per code change, restore from deps when code changes
|
# Dependencies cache - based on Cargo.lock, survives source code changes
|
||||||
key: >-
|
key: >-
|
||||||
build-${{ steps.runner-os.outputs.slug }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }}-${{ hashFiles('**/*.rs', '**/Cargo.toml') }}
|
continuwuity-deps-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
build-${{ steps.runner-os.outputs.slug }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }}-
|
continuwuity-deps-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-
|
||||||
|
|
||||||
|
- name: Cache incremental compilation
|
||||||
|
id: incremental-cache
|
||||||
|
uses: actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
target/**/incremental
|
||||||
|
# Incremental cache - based on source code changes
|
||||||
|
key: >-
|
||||||
|
continuwuity-incremental-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }}-${{ hashFiles('**/*.rs', '**/Cargo.toml') }}
|
||||||
|
restore-keys: |
|
||||||
|
continuwuity-incremental-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-${{ hashFiles('rust-toolchain.toml', '**/Cargo.lock') }}-
|
||||||
|
continuwuity-incremental-${{ steps.runner-os.outputs.slug }}-${{ steps.runner-os.outputs.arch }}-${{ inputs.rust-version }}${{ inputs.cache-key-suffix && format('-{0}', inputs.cache-key-suffix) || '' }}-
|
||||||
|
|
||||||
- name: End cache restore group
|
- name: End cache restore group
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ runs:
|
|||||||
path: |
|
path: |
|
||||||
/usr/share/rust/.cargo/bin
|
/usr/share/rust/.cargo/bin
|
||||||
~/.cargo/bin
|
~/.cargo/bin
|
||||||
key: timelord-binaries-v3
|
key: continuwuity-timelord-binaries
|
||||||
|
|
||||||
- name: Check if binaries need installation
|
- name: Check if binaries need installation
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -82,7 +82,7 @@ runs:
|
|||||||
path: |
|
path: |
|
||||||
/usr/share/rust/.cargo/bin
|
/usr/share/rust/.cargo/bin
|
||||||
~/.cargo/bin
|
~/.cargo/bin
|
||||||
key: timelord-binaries-v3
|
key: continuwuity-timelord-binaries
|
||||||
|
|
||||||
|
|
||||||
- name: Restore timelord cache with fallbacks
|
- name: Restore timelord cache with fallbacks
|
||||||
@@ -92,7 +92,7 @@ runs:
|
|||||||
path: ${{ env.TIMELORD_CACHE_PATH }}
|
path: ${{ env.TIMELORD_CACHE_PATH }}
|
||||||
key: ${{ env.TIMELORD_KEY }}
|
key: ${{ env.TIMELORD_KEY }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
timelord-v1-${{ github.repository }}-
|
continuwuity-timelord-${{ github.repository }}-
|
||||||
|
|
||||||
- name: Initialize timestamps on complete cache miss
|
- name: Initialize timestamps on complete cache miss
|
||||||
if: steps.timelord-restore.outputs.cache-hit != 'true'
|
if: steps.timelord-restore.outputs.cache-hit != 'true'
|
||||||
|
|||||||
@@ -0,0 +1,148 @@
|
|||||||
|
name: Build / Debian DEB
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "build-debian-${{ forge.ref }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*.*.*"
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 0 * * *'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
container: ["ubuntu-latest", "ubuntu-previous", "debian-latest", "debian-oldstable"]
|
||||||
|
container:
|
||||||
|
image: "ghcr.io/tcpipuk/act-runner:${{ matrix.container }}"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Get Debian version
|
||||||
|
id: debian-version
|
||||||
|
run: |
|
||||||
|
VERSION=$(cat /etc/debian_version)
|
||||||
|
DISTRIBUTION=$(lsb_release -sc 2>/dev/null)
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "distribution=$DISTRIBUTION" >> $GITHUB_OUTPUT
|
||||||
|
echo "Debian distribution: $DISTRIBUTION ($VERSION)"
|
||||||
|
|
||||||
|
- name: Checkout repository with full history
|
||||||
|
uses: https://code.forgejo.org/actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Cache Cargo registry
|
||||||
|
uses: https://code.forgejo.org/actions/cache@v4
|
||||||
|
with:
|
||||||
|
path: |
|
||||||
|
~/.cargo/registry
|
||||||
|
~/.cargo/git
|
||||||
|
key: cargo-debian-${{ steps.debian-version.outputs.distribution }}-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
restore-keys: |
|
||||||
|
cargo-debian-${{ steps.debian-version.outputs.distribution }}-
|
||||||
|
|
||||||
|
- name: Setup sccache
|
||||||
|
uses: https://git.tomfos.tr/tom/sccache-action@v1
|
||||||
|
|
||||||
|
- 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: Setup Rust nightly
|
||||||
|
uses: ./.forgejo/actions/setup-rust
|
||||||
|
with:
|
||||||
|
rust-version: nightly
|
||||||
|
github-token: ${{ secrets.GH_PUBLIC_RO }}
|
||||||
|
|
||||||
|
- name: Get package version and component
|
||||||
|
id: package-meta
|
||||||
|
run: |
|
||||||
|
BASE_VERSION=$(cargo metadata --no-deps --format-version 1 | jq -r ".packages[] | select(.name == \"conduwuit\").version" | sed 's/[^a-zA-Z0-9.+]/~/g')
|
||||||
|
# VERSION is the package version, COMPONENT is used in
|
||||||
|
# apt's repository config like a git repo branch
|
||||||
|
if [[ "${{ forge.ref }}" == "refs/tags/"* ]]; then
|
||||||
|
# Use the "stable" component for tagged releases
|
||||||
|
COMPONENT="stable"
|
||||||
|
VERSION=$BASE_VERSION
|
||||||
|
else
|
||||||
|
# Use the "dev" component for development builds
|
||||||
|
SHA=$(echo "${{ forge.sha }}" | cut -c1-7)
|
||||||
|
DATE=$(date +%Y%m%d)
|
||||||
|
if [ "${{ forge.ref_name }}" = "main" ]; then
|
||||||
|
COMPONENT="dev"
|
||||||
|
else
|
||||||
|
# Use the sanitized ref name as the component for feature branches
|
||||||
|
COMPONENT="dev-$(echo '${{ forge.ref_name }}' | sed 's/[^a-zA-Z0-9.+]/-/g' | tr '[:upper:]' '[:lower:]' | cut -c1-30)"
|
||||||
|
fi
|
||||||
|
CLEAN_COMPONENT=$(echo $COMPONENT | sed 's/[^a-zA-Z0-9.+]/~/g')
|
||||||
|
VERSION="$BASE_VERSION~git$DATE.$SHA-$CLEAN_COMPONENT"
|
||||||
|
fi
|
||||||
|
echo "component=$COMPONENT" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
||||||
|
echo "Component: $COMPONENT"
|
||||||
|
echo "Version: $VERSION"
|
||||||
|
|
||||||
|
- name: Install cargo-deb
|
||||||
|
run: |
|
||||||
|
if command -v cargo-deb &> /dev/null; then
|
||||||
|
echo "cargo-deb already available"
|
||||||
|
else
|
||||||
|
echo "Installing cargo-deb"
|
||||||
|
cargo-binstall -y --no-symlinks cargo-deb
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install build dependencies
|
||||||
|
run: |
|
||||||
|
apt-get update -y
|
||||||
|
# Build dependencies for rocksdb
|
||||||
|
apt-get install -y clang liburing-dev
|
||||||
|
|
||||||
|
- name: Run cargo-deb
|
||||||
|
id: cargo-deb
|
||||||
|
run: |
|
||||||
|
DEB_PATH=$(cargo deb --deb-version ${{ steps.package-meta.outputs.version }})
|
||||||
|
echo "path=$DEB_PATH" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Test deb installation
|
||||||
|
run: |
|
||||||
|
echo "Installing: ${{ steps.cargo-deb.outputs.path }}"
|
||||||
|
|
||||||
|
apt-get install -y ${{ steps.cargo-deb.outputs.path }}
|
||||||
|
|
||||||
|
dpkg -s continuwuity
|
||||||
|
|
||||||
|
[ -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: Upload deb artifact
|
||||||
|
uses: https://code.forgejo.org/actions/upload-artifact@v3
|
||||||
|
with:
|
||||||
|
name: continuwuity-${{ steps.debian-version.outputs.distribution }}
|
||||||
|
path: ${{ steps.cargo-deb.outputs.path }}
|
||||||
|
|
||||||
|
- name: Publish to Forgejo package registry
|
||||||
|
if: ${{ forge.event_name == 'push' || forge.event_name == 'workflow_dispatch' }}
|
||||||
|
run: |
|
||||||
|
OWNER="continuwuation"
|
||||||
|
DISTRIBUTION=${{ steps.debian-version.outputs.distribution }}
|
||||||
|
COMPONENT=${{ steps.package-meta.outputs.component }}
|
||||||
|
DEB=${{ steps.cargo-deb.outputs.path }}
|
||||||
|
|
||||||
|
echo "Publishing: $DEB in component $COMPONENT for distribution $DISTRIBUTION"
|
||||||
|
|
||||||
|
curl --fail-with-body \
|
||||||
|
-X PUT \
|
||||||
|
-H "Authorization: token ${{ secrets.BUILTIN_REGISTRY_PASSWORD || secrets.GITHUB_TOKEN }}" \
|
||||||
|
--upload-file "$DEB" \
|
||||||
|
"${{ forge.server_url }}/api/packages/$OWNER/debian/pool/$DISTRIBUTION/$COMPONENT/upload"
|
||||||
@@ -0,0 +1,389 @@
|
|||||||
|
name: Build / Fedora RPM
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: "build-fedora-${{ github.ref }}"
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v*.*.*"
|
||||||
|
# paths:
|
||||||
|
# - 'pkg/fedora/**'
|
||||||
|
# - 'src/**'
|
||||||
|
# - 'Cargo.toml'
|
||||||
|
# - 'Cargo.lock'
|
||||||
|
# - '.forgejo/workflows/build-fedora.yml'
|
||||||
|
workflow_dispatch:
|
||||||
|
schedule:
|
||||||
|
- cron: '30 0 * * *'
|
||||||
|
|
||||||
|
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('pkg/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://git.tomfos.tr/tom/sccache-action@v1
|
||||||
|
|
||||||
|
- 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 \
|
||||||
|
fedora-packager \
|
||||||
|
python3-pip \
|
||||||
|
rpm-sign \
|
||||||
|
rpkg \
|
||||||
|
wget
|
||||||
|
|
||||||
|
- 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}/" \
|
||||||
|
pkg/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}/" \
|
||||||
|
pkg/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}/" \
|
||||||
|
pkg/fedora/continuwuity.spec.rpkg > continuwuity.spec.rpkg
|
||||||
|
fi
|
||||||
|
|
||||||
|
rpkg srpm --outdir "$HOME/rpmbuild/SRPMS"
|
||||||
|
|
||||||
|
ls -la $HOME/rpmbuild/SRPMS/
|
||||||
|
|
||||||
|
|
||||||
|
- 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: 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?sign=true"
|
||||||
|
|
||||||
|
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?sign=true"
|
||||||
|
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?sign=true"
|
||||||
|
|
||||||
|
echo "✅ Published source RPM to group: ${GROUP}-src"
|
||||||
|
fi
|
||||||
@@ -51,7 +51,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Detect runner environment
|
- name: Detect runner environment
|
||||||
id: runner-env
|
id: runner-env
|
||||||
uses: ./.forgejo/actions/detect-runner-os
|
uses: https://git.tomfos.tr/actions/detect-versions@v1
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
if: steps.runner-env.outputs.node_major == '' || steps.runner-env.outputs.node_major < '20'
|
if: steps.runner-env.outputs.node_major == '' || steps.runner-env.outputs.node_major < '20'
|
||||||
@@ -63,9 +63,7 @@ jobs:
|
|||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
with:
|
with:
|
||||||
path: ~/.npm
|
path: ~/.npm
|
||||||
key: ${{ steps.runner-env.outputs.slug }}-node-${{ hashFiles('**/package-lock.json') }}
|
key: continuwuity-${{ steps.runner-env.outputs.slug }}-${{ steps.runner-env.outputs.arch }}-node-${{ steps.runner-env.outputs.node_version }}
|
||||||
restore-keys: |
|
|
||||||
${{ steps.runner-env.outputs.slug }}-node-
|
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: npm install --save-dev wrangler@latest
|
run: npm install --save-dev wrangler@latest
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ on:
|
|||||||
- "renovate.json"
|
- "renovate.json"
|
||||||
- "pkg/**"
|
- "pkg/**"
|
||||||
- "docs/**"
|
- "docs/**"
|
||||||
|
tags:
|
||||||
|
- "v*.*.*"
|
||||||
# Allows you to run this workflow manually from the Actions tab
|
# Allows you to run this workflow manually from the Actions tab
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ jobs:
|
|||||||
name: Renovate
|
name: Renovate
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/renovatebot/renovate:41.115.6@sha256:70c89592d424a54bedf7538c5bea2e43f4d66ce2c8b74d1356d4cf0ee9ed7ec0
|
image: ghcr.io/renovatebot/renovate:41.127.2@sha256:66bc84e2f889025fbb3c9df863500dcc18bc64ac85bcf629d015064377d77f31
|
||||||
options: --tmpfs /tmp:exec
|
options: --tmpfs /tmp:exec
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
@@ -59,27 +59,27 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/renovate/cache/renovate/repository
|
/tmp/renovate/cache/renovate/repository
|
||||||
key: repo-cache-${{ github.run_id }}
|
key: renovate-repo-cache-${{ github.run_id }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
repo-cache-
|
renovate-repo-cache-
|
||||||
|
|
||||||
- name: Restore renovate package cache
|
- name: Restore renovate package cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/renovate/cache/renovate/renovate-cache-sqlite
|
/tmp/renovate/cache/renovate/renovate-cache-sqlite
|
||||||
key: package-cache-${{ github.run_id }}
|
key: renovate-package-cache-${{ github.run_id }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
package-cache-
|
renovate-package-cache-
|
||||||
|
|
||||||
- name: Restore renovate OSV cache
|
- name: Restore renovate OSV cache
|
||||||
uses: actions/cache/restore@v4
|
uses: actions/cache/restore@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/osv
|
/tmp/osv
|
||||||
key: osv-cache-${{ github.run_id }}
|
key: renovate-osv-cache-${{ github.run_id }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
osv-cache-
|
renovate-osv-cache-
|
||||||
|
|
||||||
- name: Self-hosted Renovate
|
- name: Self-hosted Renovate
|
||||||
run: renovate
|
run: renovate
|
||||||
@@ -113,7 +113,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/renovate/cache/renovate/repository
|
/tmp/renovate/cache/renovate/repository
|
||||||
key: repo-cache-${{ github.run_id }}
|
key: renovate-repo-cache-${{ github.run_id }}
|
||||||
|
|
||||||
- name: Save renovate package cache
|
- name: Save renovate package cache
|
||||||
if: always()
|
if: always()
|
||||||
@@ -121,7 +121,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/renovate/cache/renovate/renovate-cache-sqlite
|
/tmp/renovate/cache/renovate/renovate-cache-sqlite
|
||||||
key: package-cache-${{ github.run_id }}
|
key: renovate-package-cache-${{ github.run_id }}
|
||||||
|
|
||||||
- name: Save renovate OSV cache
|
- name: Save renovate OSV cache
|
||||||
if: always()
|
if: always()
|
||||||
@@ -129,4 +129,4 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
/tmp/osv
|
/tmp/osv
|
||||||
key: osv-cache-${{ github.run_id }}
|
key: renovate-osv-cache-${{ github.run_id }}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ jobs:
|
|||||||
submodules: false
|
submodules: false
|
||||||
persist-credentials: false
|
persist-credentials: false
|
||||||
|
|
||||||
- uses: https://github.com/cachix/install-nix-action@56a7bb7b56d9a92d4fd1bc05758de7eea4a370a8 # v31.1.6
|
- uses: https://github.com/cachix/install-nix-action@a809471b5c7c913aa67bec8f459a11a0decc3fce # v31.6.2
|
||||||
with:
|
with:
|
||||||
nix_path: nixpkgs=channel:nixos-unstable
|
nix_path: nixpkgs=channel:nixos-unstable
|
||||||
|
|
||||||
@@ -30,9 +30,9 @@ jobs:
|
|||||||
- name: Detect changed files
|
- name: Detect changed files
|
||||||
id: changes
|
id: changes
|
||||||
run: |
|
run: |
|
||||||
git fetch origin ${{ forgejo.base_ref }} --depth=1 || true
|
git fetch origin ${{ github.base_ref }} --depth=1 || true
|
||||||
if [ -n "${{ forgejo.event.pull_request.base.sha }}" ]; then
|
if [ -n "${{ github.event.pull_request.base.sha }}" ]; then
|
||||||
base=${{ forgejo.event.pull_request.base.sha }}
|
base=${{ github.event.pull_request.base.sha }}
|
||||||
else
|
else
|
||||||
base=$(git rev-parse HEAD~1)
|
base=$(git rev-parse HEAD~1)
|
||||||
fi
|
fi
|
||||||
@@ -97,7 +97,7 @@ jobs:
|
|||||||
git config user.email "renovate@mail.ellis.link"
|
git config user.email "renovate@mail.ellis.link"
|
||||||
git config user.name "renovate"
|
git config user.name "renovate"
|
||||||
|
|
||||||
REF="${{ forgejo.head_ref }}"
|
REF="${{ github.head_ref }}"
|
||||||
|
|
||||||
git fetch origin "$REF"
|
git fetch origin "$REF"
|
||||||
git checkout "$REF"
|
git checkout "$REF"
|
||||||
|
|||||||
Generated
+125
-99
@@ -668,9 +668,9 @@ checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytesize"
|
name = "bytesize"
|
||||||
version = "2.0.1"
|
version = "2.1.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3c8f83209414aacf0eeae3cf730b18d6981697fba62f200fcfb92b9f082acba"
|
checksum = "f5c434ae3cf0089ca203e9019ebe529c47ff45cefe8af7c85ecb734ef541822f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bzip2-sys"
|
name = "bzip2-sys"
|
||||||
@@ -689,14 +689,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
|
checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"toml 0.9.5",
|
"toml 0.9.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.36"
|
version = "1.2.37"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54"
|
checksum = "65193589c6404eb80b450d618eaf9a2cafaaafd57ecce47370519ef674a7bd44"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
"find-msvc-tools",
|
||||||
"jobserver",
|
"jobserver",
|
||||||
@@ -875,7 +875,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit"
|
name = "conduwuit"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"conduwuit_admin",
|
"conduwuit_admin",
|
||||||
@@ -907,7 +907,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_admin"
|
name = "conduwuit_admin"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"conduwuit_api",
|
"conduwuit_api",
|
||||||
@@ -929,7 +929,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_api"
|
name = "conduwuit_api"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -962,14 +962,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_build_metadata"
|
name = "conduwuit_build_metadata"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"built 0.8.0",
|
"built 0.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_core"
|
name = "conduwuit_core"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"argon2",
|
"argon2",
|
||||||
"arrayvec",
|
"arrayvec",
|
||||||
@@ -1021,7 +1021,7 @@ dependencies = [
|
|||||||
"tikv-jemallocator",
|
"tikv-jemallocator",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-metrics",
|
"tokio-metrics",
|
||||||
"toml 0.9.5",
|
"toml 0.9.6",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-core",
|
"tracing-core",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@@ -1030,7 +1030,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_database"
|
name = "conduwuit_database"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-channel",
|
"async-channel",
|
||||||
"conduwuit_core",
|
"conduwuit_core",
|
||||||
@@ -1049,7 +1049,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_macros"
|
name = "conduwuit_macros"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itertools 0.14.0",
|
"itertools 0.14.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -1059,7 +1059,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_router"
|
name = "conduwuit_router"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"axum-client-ip",
|
"axum-client-ip",
|
||||||
@@ -1094,7 +1094,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_service"
|
name = "conduwuit_service"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
@@ -1134,7 +1134,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "conduwuit_web"
|
name = "conduwuit_web"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"askama",
|
"askama",
|
||||||
"axum",
|
"axum",
|
||||||
@@ -1199,9 +1199,9 @@ checksum = "f4d34b8f066904ed7cfa4a6f9ee96c3214aa998cb44b69ca20bd2054f47402ed"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "const_panic"
|
name = "const_panic"
|
||||||
version = "0.2.14"
|
version = "0.2.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb8a602185c3c95b52f86dc78e55a6df9a287a7a93ddbcf012509930880cf879"
|
checksum = "e262cdaac42494e3ae34c43969f9cdeb7da178bdb4b66fa6a1ea2edb4c8ae652"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typewit",
|
"typewit",
|
||||||
]
|
]
|
||||||
@@ -1814,9 +1814,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fs-err"
|
name = "fs-err"
|
||||||
version = "3.1.1"
|
version = "3.1.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "88d7be93788013f265201256d58f04936a8079ad5dc898743aa20525f503b683"
|
checksum = "44f150ffc8782f35521cec2b23727707cb4045706ba3c854e86bef66b3a8cdbd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1974,7 +1974,7 @@ dependencies = [
|
|||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"wasi 0.14.5+wasi-0.2.4",
|
"wasi 0.14.7+wasi-0.2.4",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2012,7 +2012,7 @@ dependencies = [
|
|||||||
"futures-core",
|
"futures-core",
|
||||||
"futures-sink",
|
"futures-sink",
|
||||||
"http",
|
"http",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"slab",
|
"slab",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
@@ -2286,9 +2286,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "humantime"
|
name = "humantime"
|
||||||
version = "2.2.0"
|
version = "2.3.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f"
|
checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper"
|
name = "hyper"
|
||||||
@@ -2522,13 +2522,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "indexmap"
|
name = "indexmap"
|
||||||
version = "2.11.1"
|
version = "2.11.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "206a8042aec68fa4a62e8d3f7aa4ceb508177d9324faf261e1959e495b7a1921"
|
checksum = "92119844f513ffa41556430369ab02c295a3578af21cf945caa3e9e0c2481ac3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"equivalent",
|
||||||
"hashbrown 0.15.5",
|
"hashbrown 0.15.5",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -2642,9 +2643,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "js-sys"
|
name = "js-sys"
|
||||||
version = "0.3.78"
|
version = "0.3.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738"
|
checksum = "6247da8b8658ad4e73a186e747fcc5fc2a29f979d6fe6269127fdb5fd08298d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -3001,9 +3002,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "minicbor-serde"
|
name = "minicbor-serde"
|
||||||
version = "0.6.0"
|
version = "0.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bbf243b8cc68a7a76473b14328d3546fb002ae3d069227794520e9181003de9"
|
checksum = "546cc904f35809921fa57016a84c97e68d9d27c012e87b9dadc28c233705f783"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"minicbor",
|
"minicbor",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -3451,7 +3452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fixedbitset",
|
"fixedbitset",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -3542,12 +3543,12 @@ checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "plist"
|
name = "plist"
|
||||||
version = "1.7.4"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3af6b589e163c5a788fab00ce0c0366f6efbb9959c2f9874b224936af7fce7e1"
|
checksum = "740ebea15c5d1428f910cd1a5f52cebf8d25006245ed8ade92702f4943d91e07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"quick-xml",
|
"quick-xml",
|
||||||
"serde",
|
"serde",
|
||||||
"time",
|
"time",
|
||||||
@@ -3614,11 +3615,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro-crate"
|
name = "proc-macro-crate"
|
||||||
version = "3.3.0"
|
version = "3.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
|
checksum = "219cb19e96be00ab2e37d6e299658a0cfa83e52429179969b0f0121b4ac46983"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"toml_edit",
|
"toml_edit 0.23.5",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4060,8 +4061,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "resolv-conf"
|
name = "resolv-conf"
|
||||||
version = "0.7.4"
|
version = "0.7.5"
|
||||||
source = "git+https://forgejo.ellis.link/continuwuation/resolv-conf?rev=ebbbec1cb965b487a0150f5d007e96c05e3d72af#ebbbec1cb965b487a0150f5d007e96c05e3d72af"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6b3789b30bd25ba102de4beabd95d21ac45b69b1be7d14522bab988c526d6799"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rgb"
|
name = "rgb"
|
||||||
@@ -4170,7 +4172,7 @@ dependencies = [
|
|||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"getrandom 0.2.16",
|
"getrandom 0.2.16",
|
||||||
"http",
|
"http",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"js_int",
|
"js_int",
|
||||||
"konst",
|
"konst",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
@@ -4197,7 +4199,7 @@ version = "0.28.1"
|
|||||||
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d18823471ab3c09e77ff03eea346d4c07e572654#d18823471ab3c09e77ff03eea346d4c07e572654"
|
source = "git+https://forgejo.ellis.link/continuwuation/ruwuma?rev=d18823471ab3c09e77ff03eea346d4c07e572654#d18823471ab3c09e77ff03eea346d4c07e572654"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"as_variant",
|
"as_variant",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"js_int",
|
"js_int",
|
||||||
"js_option",
|
"js_option",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
@@ -4393,7 +4395,7 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"ring 0.17.14",
|
"ring 0.17.14",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"rustls-webpki 0.103.4",
|
"rustls-webpki 0.103.6",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -4462,9 +4464,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
version = "0.103.4"
|
version = "0.103.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
|
checksum = "8572f3c2cb9934231157b45499fc41e1f58c589fdfb81a844ba873265e80f8eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"ring 0.17.14",
|
"ring 0.17.14",
|
||||||
@@ -4585,9 +4587,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "semver"
|
name = "semver"
|
||||||
version = "1.0.26"
|
version = "1.0.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0"
|
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sentry"
|
name = "sentry"
|
||||||
@@ -4724,18 +4726,28 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.219"
|
version = "1.0.225"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
|
checksum = "fd6c24dee235d0da097043389623fb913daddf92c76e9f5a1db88607a0bcbd1d"
|
||||||
|
dependencies = [
|
||||||
|
"serde_core",
|
||||||
|
"serde_derive",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_core"
|
||||||
|
version = "1.0.225"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "659356f9a0cb1e529b24c01e43ad2bdf520ec4ceaf83047b83ddcc2251f96383"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.219"
|
version = "1.0.225"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
|
checksum = "0ea936adf78b1f766949a4977b91d2f5595825bd6ec079aa9543ad2685fc4516"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -4744,37 +4756,39 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_html_form"
|
name = "serde_html_form"
|
||||||
version = "0.2.7"
|
version = "0.2.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9d2de91cf02bbc07cde38891769ccd5d4f073d22a40683aa4bc7a95781aaa2c4"
|
checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"itoa",
|
"itoa",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.143"
|
version = "1.0.145"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
|
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
"ryu",
|
"ryu",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_path_to_error"
|
name = "serde_path_to_error"
|
||||||
version = "0.1.17"
|
version = "0.1.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a"
|
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4798,11 +4812,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "serde_spanned"
|
||||||
version = "1.0.0"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83"
|
checksum = "2789234a13a53fc4be1b51ea1bab45a3c338bdb884862a257d10e5a74ae009e6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -4823,7 +4837,7 @@ version = "0.0.12"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
|
checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"itoa",
|
"itoa",
|
||||||
"libyml",
|
"libyml",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -5428,19 +5442,19 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_spanned 0.6.9",
|
"serde_spanned 0.6.9",
|
||||||
"toml_datetime 0.6.11",
|
"toml_datetime 0.6.11",
|
||||||
"toml_edit",
|
"toml_edit 0.22.27",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.9.5"
|
version = "0.9.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8"
|
checksum = "ae2a4cf385da23d1d53bc15cdfa5c2109e93d8d362393c801e87da2f72f0e201"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"serde",
|
"serde_core",
|
||||||
"serde_spanned 1.0.0",
|
"serde_spanned 1.0.1",
|
||||||
"toml_datetime 0.7.0",
|
"toml_datetime 0.7.1",
|
||||||
"toml_parser",
|
"toml_parser",
|
||||||
"toml_writer",
|
"toml_writer",
|
||||||
"winnow",
|
"winnow",
|
||||||
@@ -5457,11 +5471,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.7.0"
|
version = "0.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3"
|
checksum = "a197c0ec7d131bfc6f7e82c8442ba1595aeab35da7adbf05b6b73cd06a16b6be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde_core",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -5470,7 +5484,7 @@ version = "0.22.27"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.11.1",
|
"indexmap 2.11.3",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_spanned 0.6.9",
|
"serde_spanned 0.6.9",
|
||||||
"toml_datetime 0.6.11",
|
"toml_datetime 0.6.11",
|
||||||
@@ -5478,6 +5492,18 @@ dependencies = [
|
|||||||
"winnow",
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml_edit"
|
||||||
|
version = "0.23.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c2ad0b7ae9cfeef5605163839cb9221f453399f15cfb5c10be9885fcf56611f9"
|
||||||
|
dependencies = [
|
||||||
|
"indexmap 2.11.3",
|
||||||
|
"toml_datetime 0.7.1",
|
||||||
|
"toml_parser",
|
||||||
|
"winnow",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_parser"
|
name = "toml_parser"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -5730,9 +5756,9 @@ checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typewit"
|
name = "typewit"
|
||||||
version = "1.14.1"
|
version = "1.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4c98488b93df24b7c794d6a58c4198d7a2abde676324beaca84f7fb5b39c0811"
|
checksum = "f8c1ae7cc0fdb8b842d65d127cb981574b0d2b249b74d1c7a2986863dc134f71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"typewit_proc_macros",
|
"typewit_proc_macros",
|
||||||
]
|
]
|
||||||
@@ -5932,27 +5958,27 @@ checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.14.5+wasi-0.2.4"
|
version = "0.14.7+wasi-0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4494f6290a82f5fe584817a676a34b9d6763e8d9d18204009fb31dceca98fd4"
|
checksum = "883478de20367e224c0090af9cf5f9fa85bed63a95c1abf3afc5c083ebc06e8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wasip2",
|
"wasip2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasip2"
|
name = "wasip2"
|
||||||
version = "1.0.0+wasi-0.2.4"
|
version = "1.0.1+wasi-0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03fa2761397e5bd52002cd7e73110c71af2109aca4e521a9f40473fe685b0a24"
|
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"wit-bindgen",
|
"wit-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen"
|
name = "wasm-bindgen"
|
||||||
version = "0.2.101"
|
version = "0.2.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b"
|
checksum = "4ad224d2776649cfb4f4471124f8176e54c1cca67a88108e30a0cd98b90e7ad3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -5963,9 +5989,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-backend"
|
name = "wasm-bindgen-backend"
|
||||||
version = "0.2.101"
|
version = "0.2.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb"
|
checksum = "3a1364104bdcd3c03f22b16a3b1c9620891469f5e9f09bc38b2db121e593e732"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"log",
|
"log",
|
||||||
@@ -5977,9 +6003,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-futures"
|
name = "wasm-bindgen-futures"
|
||||||
version = "0.4.51"
|
version = "0.4.52"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe"
|
checksum = "9c0a08ecf5d99d5604a6666a70b3cde6ab7cc6142f5e641a8ef48fc744ce8854"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@@ -5990,9 +6016,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro"
|
name = "wasm-bindgen-macro"
|
||||||
version = "0.2.101"
|
version = "0.2.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d"
|
checksum = "0d7ab4ca3e367bb1ed84ddbd83cc6e41e115f8337ed047239578210214e36c76"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
@@ -6000,9 +6026,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-macro-support"
|
name = "wasm-bindgen-macro-support"
|
||||||
version = "0.2.101"
|
version = "0.2.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa"
|
checksum = "4a518014843a19e2dbbd0ed5dfb6b99b23fb886b14e6192a00803a3e14c552b0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -6013,18 +6039,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasm-bindgen-shared"
|
name = "wasm-bindgen-shared"
|
||||||
version = "0.2.101"
|
version = "0.2.102"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1"
|
checksum = "255eb0aa4cc2eea3662a00c2bbd66e93911b7361d5e0fcd62385acfd7e15dcee"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "web-sys"
|
name = "web-sys"
|
||||||
version = "0.3.78"
|
version = "0.3.79"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12"
|
checksum = "50462a022f46851b81d5441d1a6f5bac0b21a1d72d64bd4906fbdd4bf7230ec7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
@@ -6084,9 +6110,9 @@ checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wildmatch"
|
name = "wildmatch"
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "68ce1ab1f8c62655ebe1350f589c61e505cf94d385bc6a12899442d9081e71fd"
|
checksum = "39b7d07a236abaef6607536ccfaf19b396dbe3f5110ddb73d39f4562902ed382"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
@@ -6499,9 +6525,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wit-bindgen"
|
name = "wit-bindgen"
|
||||||
version = "0.45.1"
|
version = "0.46.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36"
|
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "writeable"
|
name = "writeable"
|
||||||
@@ -6539,7 +6565,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtask"
|
name = "xtask"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -6548,7 +6574,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "xtask-generate-commands"
|
name = "xtask-generate-commands"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap-markdown",
|
"clap-markdown",
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
|
|||||||
+5
-7
@@ -21,7 +21,7 @@ license = "Apache-2.0"
|
|||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
repository = "https://forgejo.ellis.link/continuwuation/continuwuity"
|
||||||
rust-version = "1.86.0"
|
rust-version = "1.86.0"
|
||||||
version = "0.5.0-rc.7"
|
version = "0.5.0-rc.8"
|
||||||
|
|
||||||
[workspace.metadata.crane]
|
[workspace.metadata.crane]
|
||||||
name = "conduwuit"
|
name = "conduwuit"
|
||||||
@@ -381,6 +381,7 @@ features = [
|
|||||||
"unstable-msc4095",
|
"unstable-msc4095",
|
||||||
"unstable-msc4121",
|
"unstable-msc4121",
|
||||||
"unstable-msc4125",
|
"unstable-msc4125",
|
||||||
|
"unstable-msc4155",
|
||||||
"unstable-msc4186",
|
"unstable-msc4186",
|
||||||
"unstable-msc4203", # sending to-device events to appservices
|
"unstable-msc4203", # sending to-device events to appservices
|
||||||
"unstable-msc4210", # remove legacy mentions
|
"unstable-msc4210", # remove legacy mentions
|
||||||
@@ -554,6 +555,9 @@ version = "0.11.5"
|
|||||||
default-features = false
|
default-features = false
|
||||||
features = ["sync", "tls-rustls"]
|
features = ["sync", "tls-rustls"]
|
||||||
|
|
||||||
|
[workspace.dependencies.resolv-conf]
|
||||||
|
version = "0.7.5"
|
||||||
|
|
||||||
#
|
#
|
||||||
# Patches
|
# Patches
|
||||||
#
|
#
|
||||||
@@ -598,12 +602,6 @@ rev = "9c8e51510c35077df888ee72a36b4b05637147da"
|
|||||||
git = "https://forgejo.ellis.link/continuwuation/hyper-util"
|
git = "https://forgejo.ellis.link/continuwuation/hyper-util"
|
||||||
rev = "e4ae7628fe4fcdacef9788c4c8415317a4489941"
|
rev = "e4ae7628fe4fcdacef9788c4c8415317a4489941"
|
||||||
|
|
||||||
# Allows no-aaaa option in resolv.conf
|
|
||||||
# Use 1-indexed line numbers when displaying parse error messages
|
|
||||||
[patch.crates-io.resolv-conf]
|
|
||||||
git = "https://forgejo.ellis.link/continuwuation/resolv-conf"
|
|
||||||
rev = "ebbbec1cb965b487a0150f5d007e96c05e3d72af"
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Our crates
|
# Our crates
|
||||||
#
|
#
|
||||||
|
|||||||
+2
-2
@@ -48,7 +48,7 @@ EOF
|
|||||||
|
|
||||||
# Developer tool versions
|
# Developer tool versions
|
||||||
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
||||||
ENV BINSTALL_VERSION=1.15.4
|
ENV BINSTALL_VERSION=1.15.5
|
||||||
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
||||||
ENV CARGO_SBOM_VERSION=0.9.1
|
ENV CARGO_SBOM_VERSION=0.9.1
|
||||||
# renovate: datasource=crate depName=lddtree
|
# renovate: datasource=crate depName=lddtree
|
||||||
@@ -166,7 +166,7 @@ ARG RUST_PROFILE=release
|
|||||||
# Build the binary
|
# Build the binary
|
||||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
--mount=type=cache,target=/usr/local/cargo/git/db \
|
--mount=type=cache,target=/usr/local/cargo/git/db \
|
||||||
--mount=type=cache,target=/app/target,id=cargo-target-${TARGET_CPU}-${TARGETPLATFORM}-${RUST_PROFILE} \
|
--mount=type=cache,target=/app/target,id=continuwuity-cargo-target-${TARGET_CPU}-${TARGETPLATFORM}-${RUST_PROFILE} \
|
||||||
bash <<'EOF'
|
bash <<'EOF'
|
||||||
set -o allexport
|
set -o allexport
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ RUN --mount=type=cache,target=/etc/apk/cache apk add \
|
|||||||
|
|
||||||
# Developer tool versions
|
# Developer tool versions
|
||||||
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
# renovate: datasource=github-releases depName=cargo-bins/cargo-binstall
|
||||||
ENV BINSTALL_VERSION=1.15.4
|
ENV BINSTALL_VERSION=1.15.5
|
||||||
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
# renovate: datasource=github-releases depName=psastras/sbom-rs
|
||||||
ENV CARGO_SBOM_VERSION=0.9.1
|
ENV CARGO_SBOM_VERSION=0.9.1
|
||||||
# renovate: datasource=crate depName=lddtree
|
# renovate: datasource=crate depName=lddtree
|
||||||
@@ -122,7 +122,7 @@ ARG RUST_PROFILE=release
|
|||||||
# Build the binary
|
# Build the binary
|
||||||
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
RUN --mount=type=cache,target=/usr/local/cargo/registry \
|
||||||
--mount=type=cache,target=/usr/local/cargo/git/db \
|
--mount=type=cache,target=/usr/local/cargo/git/db \
|
||||||
--mount=type=cache,target=/app/target,id=cargo-target-${TARGET_CPU}-${TARGETPLATFORM}-musl-${RUST_PROFILE} \
|
--mount=type=cache,target=/app/target,id=continuwuity-cargo-target-${TARGET_CPU}-${TARGETPLATFORM}-musl-${RUST_PROFILE} \
|
||||||
bash <<'EOF'
|
bash <<'EOF'
|
||||||
set -o allexport
|
set -o allexport
|
||||||
set -o xtrace
|
set -o xtrace
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
- [Kubernetes](deploying/kubernetes.md)
|
- [Kubernetes](deploying/kubernetes.md)
|
||||||
- [Arch Linux](deploying/arch-linux.md)
|
- [Arch Linux](deploying/arch-linux.md)
|
||||||
- [Debian](deploying/debian.md)
|
- [Debian](deploying/debian.md)
|
||||||
|
- [Fedora](deploying/fedora.md)
|
||||||
- [FreeBSD](deploying/freebsd.md)
|
- [FreeBSD](deploying/freebsd.md)
|
||||||
- [TURN](turn.md)
|
- [TURN](turn.md)
|
||||||
- [Appservices](appservices.md)
|
- [Appservices](appservices.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-<version>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
```
|
||||||
Generated
+12
-12
@@ -10,11 +10,11 @@
|
|||||||
"nixpkgs-stable": "nixpkgs-stable"
|
"nixpkgs-stable": "nixpkgs-stable"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1756403898,
|
"lastModified": 1757683818,
|
||||||
"narHash": "sha256-S4SJDmVTtbcXaJkYrMFkcA5SDrpfRHlBbzwp6IRRPAw=",
|
"narHash": "sha256-q7q0pWT+wu5AUU1Qlbwq8Mqb+AzHKhaMCVUq/HNZfo8=",
|
||||||
"owner": "zhaofengli",
|
"owner": "zhaofengli",
|
||||||
"repo": "attic",
|
"repo": "attic",
|
||||||
"rev": "2524dd1c007bc7a0a9e9c863a1b02de8d54b319b",
|
"rev": "7c5d79ad62cda340cb8c80c99b921b7b7ffacf69",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -152,11 +152,11 @@
|
|||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1757400094,
|
"lastModified": 1758004879,
|
||||||
"narHash": "sha256-5Rcs6juMoMTaMJSR1glravl4QB9yLAFBD8s7KLi4kdQ=",
|
"narHash": "sha256-kV7tQzcNbmo58wg2uE2MQ/etaTx+PxBMHeNrLP8vOgk=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "0682b9b518792c9428865c511a4c40c9ad85c243",
|
"rev": "07e5ce53dd020e6b337fdddc934561bee0698fa2",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -370,11 +370,11 @@
|
|||||||
},
|
},
|
||||||
"nix-filter": {
|
"nix-filter": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1731533336,
|
"lastModified": 1757882181,
|
||||||
"narHash": "sha256-oRam5PS1vcrr5UPgALW0eo1m/5/pls27Z/pabHNy2Ms=",
|
"narHash": "sha256-+cCxYIh2UNalTz364p+QYmWHs0P+6wDhiWR4jDIKQIU=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "nix-filter",
|
"repo": "nix-filter",
|
||||||
"rev": "f7653272fd234696ae94229839a99b73c9ab7de0",
|
"rev": "59c44d1909c72441144b93cf0f054be7fe764de5",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -455,11 +455,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs_3": {
|
"nixpkgs_3": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1757034884,
|
"lastModified": 1758029226,
|
||||||
"narHash": "sha256-PgLSZDBEWUHpfTRfFyklmiiLBE1i1aGCtz4eRA3POao=",
|
"narHash": "sha256-TjqVmbpoCqWywY9xIZLTf6ANFvDCXdctCjoYuYPYdMI=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "ca77296380960cd497a765102eeb1356eb80fed0",
|
"rev": "08b8f92ac6354983f5382124fef6006cade4a1c1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -65,10 +65,10 @@
|
|||||||
domain = "forgejo.ellis.link";
|
domain = "forgejo.ellis.link";
|
||||||
owner = "continuwuation";
|
owner = "continuwuation";
|
||||||
repo = "rocksdb";
|
repo = "rocksdb";
|
||||||
rev = "10.4.fb";
|
rev = "10.5.fb";
|
||||||
sha256 = "sha256-/Hvy1yTH/0D5aa7bc+/uqFugCQq4InTdwlRw88vA5IY=";
|
sha256 = "sha256-X4ApGLkHF9ceBtBg77dimEpu720I79ffLoyPa8JMHaU=";
|
||||||
};
|
};
|
||||||
version = "v10.4.fb";
|
version = "v10.5.fb";
|
||||||
cmakeFlags =
|
cmakeFlags =
|
||||||
pkgs.lib.subtractLists [
|
pkgs.lib.subtractLists [
|
||||||
# No real reason to have snappy or zlib, no one uses this
|
# No real reason to have snappy or zlib, no one uses this
|
||||||
|
|||||||
+20
-4
@@ -1,12 +1,28 @@
|
|||||||
# Continuwuity for Debian
|
# Continuwuity for Debian
|
||||||
|
|
||||||
This document provides information about downloading and deploying the Debian package. You can also use this guide for other `apt`-based distributions such as Ubuntu.
|
This document provides information about downloading and deploying the Debian package. You can also use this guide for other deb-based distributions such as Ubuntu.
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
See the [generic deployment guide](../deploying/generic.md) for additional information about using the Debian package.
|
To add the Continuwuation apt repository:
|
||||||
|
```bash
|
||||||
|
# Replace with `"dev"` for bleeding-edge builds at your own risk
|
||||||
|
export COMPONENT="stable"
|
||||||
|
# Import the Continuwuation signing key
|
||||||
|
sudo curl https://forgejo.ellis.link/api/packages/continuwuation/debian/repository.key -o /etc/apt/keyrings/forgejo-continuwuation.asc
|
||||||
|
# Add a new apt source list pointing to the repository
|
||||||
|
echo "deb [signed-by=/etc/apt/keyrings/forgejo-continuwuation.asc] https://forgejo.ellis.link/api/packages/continuwuation/debian $(lsb_release -sc) $COMPONENT" | sudo tee /etc/apt/sources.list.d/continuwuation.list
|
||||||
|
# Update remote package lists
|
||||||
|
sudo apt update
|
||||||
|
```
|
||||||
|
|
||||||
No `apt` repository is currently available. This feature is in development.
|
To install continuwuity:
|
||||||
|
```bash
|
||||||
|
sudo apt install continuwuity
|
||||||
|
```
|
||||||
|
The `continuwuity` package conflicts with the old `conduwuit` package and will remove it automatically when installed.
|
||||||
|
|
||||||
|
See the [generic deployment guide](../deploying/generic.md) for additional information about using the Debian package.
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
@@ -16,7 +32,7 @@ You can customize additional settings by uncommenting and modifying the configur
|
|||||||
|
|
||||||
### Running
|
### Running
|
||||||
|
|
||||||
The package uses the [`conduwuit.service`](../configuration/examples.md#example-systemd-unit-file) systemd unit file to start and stop Continuwuity. The binary installs at `/usr/sbin/conduwuit`.
|
The package uses the [`conduwuit.service`](../configuration/examples.md#example-systemd-unit-file) systemd unit file to start and stop Continuwuity. The binary installs at `/usr/bin/conduwuit`.
|
||||||
|
|
||||||
By default, this package assumes that Continuwuity runs behind a reverse proxy. The default configuration options apply (listening on `localhost` and TCP port `6167`). Matrix federation requires a valid domain name and TLS. To federate properly, you must set up TLS certificates and certificate renewal.
|
By default, this package assumes that Continuwuity runs behind a reverse proxy. The default configuration options apply (listening on `localhost` and TCP port `6167`). Matrix federation requires a valid domain name and TLS. To federate properly, you must set up TLS certificates and certificate renewal.
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
# it requires Internet access and is not suitable for Fedora main repos
|
||||||
# TODO: rpkg-util is no longer maintained, find a replacement
|
|
||||||
|
|
||||||
Name: continuwuity
|
Name: continuwuity
|
||||||
Version: {{{ git_repo_version }}}
|
Version: {{{ git_repo_version }}}
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ use conduwuit::{
|
|||||||
Err, Result, debug_error, err, info,
|
Err, Result, debug_error, err, info,
|
||||||
matrix::{event::gen_event_id_canonical_json, pdu::PduBuilder},
|
matrix::{event::gen_event_id_canonical_json, pdu::PduBuilder},
|
||||||
};
|
};
|
||||||
use futures::{FutureExt, join};
|
use futures::FutureExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
OwnedServerName, RoomId, UserId,
|
OwnedServerName, RoomId, UserId,
|
||||||
api::{client::membership::invite_user, federation::membership::create_invite},
|
api::{client::membership::invite_user, federation::membership::create_invite},
|
||||||
events::room::member::{MembershipState, RoomMemberEventContent},
|
events::{
|
||||||
|
invite_permission_config::FilterLevel,
|
||||||
|
room::member::{MembershipState, RoomMemberEventContent},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use service::Services;
|
use service::Services;
|
||||||
|
|
||||||
@@ -47,22 +50,21 @@ pub(crate) async fn invite_user_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match &body.recipient {
|
match &body.recipient {
|
||||||
| invite_user::v3::InvitationRecipient::UserId { user_id } => {
|
| invite_user::v3::InvitationRecipient::UserId { user_id: recipient_user } => {
|
||||||
let sender_ignored_recipient = services.users.user_is_ignored(sender_user, user_id);
|
let sender_filter_level = services
|
||||||
let recipient_ignored_by_sender =
|
.users
|
||||||
services.users.user_is_ignored(user_id, sender_user);
|
.invite_filter_level(recipient_user, sender_user)
|
||||||
|
.await;
|
||||||
|
|
||||||
let (sender_ignored_recipient, recipient_ignored_by_sender) =
|
if !matches!(sender_filter_level, FilterLevel::Allow) {
|
||||||
join!(sender_ignored_recipient, recipient_ignored_by_sender);
|
// drop invites if the sender has the recipient filtered
|
||||||
|
|
||||||
if sender_ignored_recipient {
|
|
||||||
return Ok(invite_user::v3::Response {});
|
return Ok(invite_user::v3::Response {});
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(target_user_membership) = services
|
if let Ok(target_user_membership) = services
|
||||||
.rooms
|
.rooms
|
||||||
.state_accessor
|
.state_accessor
|
||||||
.get_member(&body.room_id, user_id)
|
.get_member(&body.room_id, recipient_user)
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
if target_user_membership.membership == MembershipState::Ban {
|
if target_user_membership.membership == MembershipState::Ban {
|
||||||
@@ -70,16 +72,27 @@ pub(crate) async fn invite_user_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if recipient_ignored_by_sender {
|
// check for blocked invites if the recipient is a local user.
|
||||||
// silently drop the invite to the recipient if they've been ignored by the
|
if services.globals.user_is_local(recipient_user) {
|
||||||
// sender, pretend it worked
|
let recipient_filter_level = services
|
||||||
return Ok(invite_user::v3::Response {});
|
.users
|
||||||
|
.invite_filter_level(sender_user, recipient_user)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
// ignored invites aren't handled here
|
||||||
|
// since the recipient's membership should still be changed to `invite`.
|
||||||
|
// they're filtered out in the individual /sync handlers.
|
||||||
|
if matches!(recipient_filter_level, FilterLevel::Block) {
|
||||||
|
return Err!(Request(InviteBlocked(
|
||||||
|
"{recipient_user} has blocked invites from you."
|
||||||
|
)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invite_helper(
|
invite_helper(
|
||||||
&services,
|
&services,
|
||||||
sender_user,
|
sender_user,
|
||||||
user_id,
|
recipient_user,
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
body.reason.clone(),
|
body.reason.clone(),
|
||||||
false,
|
false,
|
||||||
@@ -98,7 +111,7 @@ pub(crate) async fn invite_user_route(
|
|||||||
pub(crate) async fn invite_helper(
|
pub(crate) async fn invite_helper(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
sender_user: &UserId,
|
sender_user: &UserId,
|
||||||
user_id: &UserId,
|
recipient_user: &UserId,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
reason: Option<String>,
|
reason: Option<String>,
|
||||||
is_direct: bool,
|
is_direct: bool,
|
||||||
@@ -111,12 +124,12 @@ pub(crate) async fn invite_helper(
|
|||||||
return Err!(Request(Forbidden("Invites are not allowed on this server.")));
|
return Err!(Request(Forbidden("Invites are not allowed on this server.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if !services.globals.user_is_local(user_id) {
|
if !services.globals.user_is_local(recipient_user) {
|
||||||
let (pdu, pdu_json, invite_room_state) = {
|
let (pdu, pdu_json, invite_room_state) = {
|
||||||
let state_lock = services.rooms.state.mutex.lock(room_id).await;
|
let state_lock = services.rooms.state.mutex.lock(room_id).await;
|
||||||
|
|
||||||
let content = RoomMemberEventContent {
|
let content = RoomMemberEventContent {
|
||||||
avatar_url: services.users.avatar_url(user_id).await.ok(),
|
avatar_url: services.users.avatar_url(recipient_user).await.ok(),
|
||||||
is_direct: Some(is_direct),
|
is_direct: Some(is_direct),
|
||||||
reason,
|
reason,
|
||||||
..RoomMemberEventContent::new(MembershipState::Invite)
|
..RoomMemberEventContent::new(MembershipState::Invite)
|
||||||
@@ -126,7 +139,7 @@ pub(crate) async fn invite_helper(
|
|||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
.create_hash_and_sign_event(
|
.create_hash_and_sign_event(
|
||||||
PduBuilder::state(user_id.to_string(), &content),
|
PduBuilder::state(recipient_user.to_string(), &content),
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(room_id),
|
Some(room_id),
|
||||||
&state_lock,
|
&state_lock,
|
||||||
@@ -144,7 +157,7 @@ pub(crate) async fn invite_helper(
|
|||||||
|
|
||||||
let response = services
|
let response = services
|
||||||
.sending
|
.sending
|
||||||
.send_federation_request(user_id.server_name(), create_invite::v2::Request {
|
.send_federation_request(recipient_user.server_name(), create_invite::v2::Request {
|
||||||
room_id: room_id.to_owned(),
|
room_id: room_id.to_owned(),
|
||||||
event_id: (*pdu.event_id).to_owned(),
|
event_id: (*pdu.event_id).to_owned(),
|
||||||
room_version: room_version_id.clone(),
|
room_version: room_version_id.clone(),
|
||||||
@@ -173,7 +186,7 @@ pub(crate) async fn invite_helper(
|
|||||||
return Err!(Request(BadJson(warn!(
|
return Err!(Request(BadJson(warn!(
|
||||||
%pdu.event_id, %event_id,
|
%pdu.event_id, %event_id,
|
||||||
"Server {} sent event with wrong event ID",
|
"Server {} sent event with wrong event ID",
|
||||||
user_id.server_name()
|
recipient_user.server_name()
|
||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,9 +226,9 @@ pub(crate) async fn invite_helper(
|
|||||||
let state_lock = services.rooms.state.mutex.lock(room_id).await;
|
let state_lock = services.rooms.state.mutex.lock(room_id).await;
|
||||||
|
|
||||||
let content = RoomMemberEventContent {
|
let content = RoomMemberEventContent {
|
||||||
displayname: services.users.displayname(user_id).await.ok(),
|
displayname: services.users.displayname(recipient_user).await.ok(),
|
||||||
avatar_url: services.users.avatar_url(user_id).await.ok(),
|
avatar_url: services.users.avatar_url(recipient_user).await.ok(),
|
||||||
blurhash: services.users.blurhash(user_id).await.ok(),
|
blurhash: services.users.blurhash(recipient_user).await.ok(),
|
||||||
is_direct: Some(is_direct),
|
is_direct: Some(is_direct),
|
||||||
reason,
|
reason,
|
||||||
..RoomMemberEventContent::new(MembershipState::Invite)
|
..RoomMemberEventContent::new(MembershipState::Invite)
|
||||||
@@ -225,7 +238,7 @@ pub(crate) async fn invite_helper(
|
|||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
.build_and_append_pdu(
|
.build_and_append_pdu(
|
||||||
PduBuilder::state(user_id.to_string(), &content),
|
PduBuilder::state(recipient_user.to_string(), &content),
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(room_id),
|
Some(room_id),
|
||||||
&state_lock,
|
&state_lock,
|
||||||
|
|||||||
@@ -313,11 +313,14 @@ pub async fn join_room_by_id_helper(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let local_join = server_in_room
|
if !server_in_room && servers.is_empty() {
|
||||||
|| servers.is_empty()
|
return Err!(Request(NotFound(
|
||||||
|| (servers.len() == 1 && services.globals.server_is_ours(&servers[0]));
|
"No servers were provided to assist in joining the room remotely, and we are not \
|
||||||
|
already participating in the room."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
if local_join {
|
if server_in_room {
|
||||||
join_room_by_id_helper_local(
|
join_room_by_id_helper_local(
|
||||||
services,
|
services,
|
||||||
sender_user,
|
sender_user,
|
||||||
@@ -739,6 +742,7 @@ async fn join_room_by_id_helper_local(
|
|||||||
.iter()
|
.iter()
|
||||||
.stream()
|
.stream()
|
||||||
.any(|restriction_room_id| {
|
.any(|restriction_room_id| {
|
||||||
|
trace!("Checking if {sender_user} is joined to {restriction_room_id}");
|
||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
@@ -751,6 +755,7 @@ async fn join_room_by_id_helper_local(
|
|||||||
.state_cache
|
.state_cache
|
||||||
.local_users_in_room(room_id)
|
.local_users_in_room(room_id)
|
||||||
.filter(|user| {
|
.filter(|user| {
|
||||||
|
trace!("Checking if {user} can invite {sender_user} to {room_id}");
|
||||||
services.rooms.state_accessor.user_can_invite(
|
services.rooms.state_accessor.user_can_invite(
|
||||||
room_id,
|
room_id,
|
||||||
user,
|
user,
|
||||||
@@ -763,6 +768,7 @@ async fn join_room_by_id_helper_local(
|
|||||||
.await
|
.await
|
||||||
.map(ToOwned::to_owned)
|
.map(ToOwned::to_owned)
|
||||||
} else {
|
} else {
|
||||||
|
trace!("No restriction rooms are joined by {sender_user}");
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
+46
-13
@@ -30,6 +30,7 @@ use ruma::{
|
|||||||
events::{
|
events::{
|
||||||
AnyStateEvent, StateEventType,
|
AnyStateEvent, StateEventType,
|
||||||
TimelineEventType::{self, *},
|
TimelineEventType::{self, *},
|
||||||
|
invite_permission_config::FilterLevel,
|
||||||
},
|
},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
};
|
};
|
||||||
@@ -267,7 +268,7 @@ pub(crate) async fn ignored_filter(
|
|||||||
pub(crate) async fn is_ignored_pdu<Pdu>(
|
pub(crate) async fn is_ignored_pdu<Pdu>(
|
||||||
services: &Services,
|
services: &Services,
|
||||||
event: &Pdu,
|
event: &Pdu,
|
||||||
user_id: &UserId,
|
recipient_user: &UserId,
|
||||||
) -> bool
|
) -> bool
|
||||||
where
|
where
|
||||||
Pdu: Event + Send + Sync,
|
Pdu: Event + Send + Sync,
|
||||||
@@ -278,20 +279,29 @@ where
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let ignored_type = IGNORED_MESSAGE_TYPES.binary_search(event.kind()).is_ok();
|
let sender_user = event.sender();
|
||||||
|
let type_ignored = IGNORED_MESSAGE_TYPES.binary_search(event.kind()).is_ok();
|
||||||
let ignored_server = services
|
let server_ignored = services
|
||||||
.moderation
|
.moderation
|
||||||
.is_remote_server_ignored(event.sender().server_name());
|
.is_remote_server_ignored(sender_user.server_name());
|
||||||
|
let user_ignored = services
|
||||||
|
.users
|
||||||
|
.user_is_ignored(sender_user, recipient_user)
|
||||||
|
.await;
|
||||||
|
|
||||||
if ignored_type
|
if !type_ignored {
|
||||||
&& (ignored_server
|
// We cannot safely ignore this type
|
||||||
|| (!services.config.send_messages_from_ignored_users_to_client
|
return false;
|
||||||
&& services
|
}
|
||||||
.users
|
|
||||||
.user_is_ignored(event.sender(), user_id)
|
if server_ignored {
|
||||||
.await))
|
// the sender's server is ignored, so ignore this event
|
||||||
{
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if user_ignored && !services.config.send_messages_from_ignored_users_to_client {
|
||||||
|
// the recipient of this PDU has the sender ignored, and we're not
|
||||||
|
// configured to send ignored messages to clients
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -320,6 +330,29 @@ pub(crate) fn event_filter(item: PdusIterItem, filter: &RoomEventFilter) -> Opti
|
|||||||
filter.matches(pdu).then_some(item)
|
filter.matches(pdu).then_some(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub(crate) async fn is_ignored_invite(
|
||||||
|
services: &Services,
|
||||||
|
recipient_user: &UserId,
|
||||||
|
room_id: &RoomId,
|
||||||
|
) -> bool {
|
||||||
|
let Ok(sender_user) = services
|
||||||
|
.rooms
|
||||||
|
.state_cache
|
||||||
|
.invite_sender(recipient_user, room_id)
|
||||||
|
.await
|
||||||
|
else {
|
||||||
|
// the invite may have been sent before the invite_sender table existed.
|
||||||
|
// assume it's not ignored
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
services
|
||||||
|
.users
|
||||||
|
.invite_filter_level(&sender_user, recipient_user)
|
||||||
|
.await == FilterLevel::Ignore
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg_attr(debug_assertions, ctor::ctor)]
|
#[cfg_attr(debug_assertions, ctor::ctor)]
|
||||||
fn _is_sorted() {
|
fn _is_sorted() {
|
||||||
debug_assert!(
|
debug_assert!(
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::{BTreeMap, BTreeSet};
|
||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
@@ -13,6 +13,7 @@ use ruma::{
|
|||||||
api::client::room::{self, create_room},
|
api::client::room::{self, create_room},
|
||||||
events::{
|
events::{
|
||||||
TimelineEventType,
|
TimelineEventType,
|
||||||
|
invite_permission_config::FilterLevel,
|
||||||
room::{
|
room::{
|
||||||
canonical_alias::RoomCanonicalAliasEventContent,
|
canonical_alias::RoomCanonicalAliasEventContent,
|
||||||
create::RoomCreateEventContent,
|
create::RoomCreateEventContent,
|
||||||
@@ -121,6 +122,40 @@ pub(crate) async fn create_room_route(
|
|||||||
return Err!(Request(Forbidden("Publishing rooms to the room directory is not allowed")));
|
return Err!(Request(Forbidden("Publishing rooms to the room directory is not allowed")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut invitees = BTreeSet::new();
|
||||||
|
|
||||||
|
for recipient_user in &body.invite {
|
||||||
|
if !matches!(
|
||||||
|
services
|
||||||
|
.users
|
||||||
|
.invite_filter_level(recipient_user, sender_user)
|
||||||
|
.await,
|
||||||
|
FilterLevel::Allow
|
||||||
|
) {
|
||||||
|
// drop invites if the creator has them blocked
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if the recipient of the invite is local and has the sender blocked, error
|
||||||
|
// out. if the recipient is remote we can't tell yet, and if they're local and
|
||||||
|
// have the sender _ignored_ their invite will be filtered out in
|
||||||
|
// the handlers for the individual /sync endpoints
|
||||||
|
if services.globals.user_is_local(recipient_user)
|
||||||
|
&& matches!(
|
||||||
|
services
|
||||||
|
.users
|
||||||
|
.invite_filter_level(sender_user, recipient_user)
|
||||||
|
.await,
|
||||||
|
FilterLevel::Block
|
||||||
|
) {
|
||||||
|
return Err!(Request(InviteBlocked(
|
||||||
|
"{recipient_user} has blocked invites from you."
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
invitees.insert(recipient_user.clone());
|
||||||
|
}
|
||||||
|
|
||||||
let alias: Option<OwnedRoomAliasId> = match body.room_alias_name.as_ref() {
|
let alias: Option<OwnedRoomAliasId> = match body.room_alias_name.as_ref() {
|
||||||
| Some(alias) =>
|
| Some(alias) =>
|
||||||
Some(room_alias_check(&services, alias, body.appservice_info.as_ref()).await?),
|
Some(room_alias_check(&services, alias, body.appservice_info.as_ref()).await?),
|
||||||
@@ -252,19 +287,11 @@ pub(crate) async fn create_room_route(
|
|||||||
| _ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
| _ => RoomPreset::PrivateChat, // Room visibility should not be custom
|
||||||
});
|
});
|
||||||
|
|
||||||
let mut users = BTreeMap::from_iter([(sender_user.to_owned(), int!(100))]);
|
let mut power_levels_to_grant = BTreeMap::from_iter([(sender_user.to_owned(), int!(100))]);
|
||||||
|
|
||||||
if preset == RoomPreset::TrustedPrivateChat {
|
if preset == RoomPreset::TrustedPrivateChat {
|
||||||
for invite in &body.invite {
|
for recipient_user in &invitees {
|
||||||
if services.users.user_is_ignored(sender_user, invite).await {
|
power_levels_to_grant.insert(recipient_user.clone(), int!(100));
|
||||||
continue;
|
|
||||||
} else if services.users.user_is_ignored(invite, sender_user).await {
|
|
||||||
// silently drop the invite to the recipient if they've been ignored by the
|
|
||||||
// sender, pretend it worked
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
users.insert(invite.clone(), int!(100));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -289,7 +316,7 @@ pub(crate) async fn create_room_route(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
users.insert(sender_user.to_owned(), int!(100));
|
power_levels_to_grant.insert(sender_user.to_owned(), int!(100));
|
||||||
creators.clear(); // If this vec is not empty, default_power_levels_content will
|
creators.clear(); // If this vec is not empty, default_power_levels_content will
|
||||||
// treat this as a v12 room
|
// treat this as a v12 room
|
||||||
}
|
}
|
||||||
@@ -297,7 +324,7 @@ pub(crate) async fn create_room_route(
|
|||||||
let power_levels_content = default_power_levels_content(
|
let power_levels_content = default_power_levels_content(
|
||||||
body.power_level_content_override.as_ref(),
|
body.power_level_content_override.as_ref(),
|
||||||
&body.visibility,
|
&body.visibility,
|
||||||
users,
|
power_levels_to_grant,
|
||||||
creators,
|
creators,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@@ -459,17 +486,9 @@ pub(crate) async fn create_room_route(
|
|||||||
|
|
||||||
// 8. Events implied by invite (and TODO: invite_3pid)
|
// 8. Events implied by invite (and TODO: invite_3pid)
|
||||||
drop(state_lock);
|
drop(state_lock);
|
||||||
for user_id in &body.invite {
|
for recipient_user in &invitees {
|
||||||
if services.users.user_is_ignored(sender_user, user_id).await {
|
|
||||||
continue;
|
|
||||||
} else if services.users.user_is_ignored(user_id, sender_user).await {
|
|
||||||
// silently drop the invite to the recipient if they've been ignored by the
|
|
||||||
// sender, pretend it worked
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Err(e) =
|
if let Err(e) =
|
||||||
invite_helper(&services, sender_user, user_id, &room_id, None, body.is_direct)
|
invite_helper(&services, sender_user, recipient_user, &room_id, None, body.is_direct)
|
||||||
.boxed()
|
.boxed()
|
||||||
.await
|
.await
|
||||||
{
|
{
|
||||||
|
|||||||
+113
-38
@@ -2,7 +2,7 @@ use std::cmp::max;
|
|||||||
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
use conduwuit::{
|
use conduwuit::{
|
||||||
Err, Error, Event, Result, debug, err, info,
|
Err, Error, Event, Result, RoomVersion, debug, err, info,
|
||||||
matrix::{StateKey, pdu::PduBuilder},
|
matrix::{StateKey, pdu::PduBuilder},
|
||||||
};
|
};
|
||||||
use futures::{FutureExt, StreamExt};
|
use futures::{FutureExt, StreamExt};
|
||||||
@@ -68,37 +68,76 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
return Err!(Request(UserSuspended("You cannot perform this action while suspended.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// First, check if the user has permission to upgrade the room (send tombstone
|
||||||
|
// event)
|
||||||
|
let old_room_state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||||
|
|
||||||
|
// Check tombstone permission by attempting to create (but not send) the event
|
||||||
|
// Note that this does internally call the policy server with a fake room ID,
|
||||||
|
// which may not be good?
|
||||||
|
let tombstone_test_result = services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.create_hash_and_sign_event(
|
||||||
|
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||||
|
body: "This room has been replaced".to_owned(),
|
||||||
|
replacement_room: RoomId::new(services.globals.server_name()),
|
||||||
|
}),
|
||||||
|
sender_user,
|
||||||
|
Some(&body.room_id),
|
||||||
|
&old_room_state_lock,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
|
|
||||||
|
if let Err(_e) = tombstone_test_result {
|
||||||
|
return Err!(Request(Forbidden("User does not have permission to upgrade this room.")));
|
||||||
|
}
|
||||||
|
|
||||||
|
drop(old_room_state_lock);
|
||||||
|
|
||||||
// Create a replacement room
|
// Create a replacement room
|
||||||
let replacement_room = RoomId::new(services.globals.server_name());
|
let room_features = RoomVersion::new(&body.new_version)?;
|
||||||
|
let replacement_room: Option<&RoomId> = if room_features.room_ids_as_hashes {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(&RoomId::new(services.globals.server_name()))
|
||||||
|
};
|
||||||
|
let replacement_room_tmp = match replacement_room {
|
||||||
|
| Some(v) => v,
|
||||||
|
| None => &RoomId::new(services.globals.server_name()),
|
||||||
|
};
|
||||||
|
|
||||||
let _short_id = services
|
let _short_id = services
|
||||||
.rooms
|
.rooms
|
||||||
.short
|
.short
|
||||||
.get_or_create_shortroomid(&replacement_room)
|
.get_or_create_shortroomid(replacement_room_tmp)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
// For pre-v12 rooms, send tombstone before creating replacement room
|
||||||
|
let tombstone_event_id = if !room_features.room_ids_as_hashes {
|
||||||
// Send a m.room.tombstone event to the old room to indicate that it is not
|
let state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||||
// intended to be used any further Fail if the sender does not have the required
|
// Send a m.room.tombstone event to the old room to indicate that it is not
|
||||||
// permissions
|
// intended to be used any further
|
||||||
let tombstone_event_id = services
|
let tombstone_event_id = services
|
||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
.build_and_append_pdu(
|
.build_and_append_pdu(
|
||||||
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||||
body: "This room has been replaced".to_owned(),
|
body: "This room has been replaced".to_owned(),
|
||||||
replacement_room: replacement_room.clone(),
|
replacement_room: replacement_room.unwrap().to_owned(),
|
||||||
}),
|
}),
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(&body.room_id),
|
Some(&body.room_id),
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
// Change lock to replacement room
|
||||||
// Change lock to replacement room
|
drop(state_lock);
|
||||||
drop(state_lock);
|
Some(tombstone_event_id)
|
||||||
let state_lock = services.rooms.state.mutex.lock(&replacement_room).await;
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
let state_lock = services.rooms.state.mutex.lock(replacement_room_tmp).await;
|
||||||
|
|
||||||
// Get the old room creation event
|
// Get the old room creation event
|
||||||
let mut create_event_content: CanonicalJsonObject = services
|
let mut create_event_content: CanonicalJsonObject = services
|
||||||
@@ -111,7 +150,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
// Use the m.room.tombstone event as the predecessor
|
// Use the m.room.tombstone event as the predecessor
|
||||||
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
let predecessor = Some(ruma::events::room::create::PreviousRoom::new(
|
||||||
body.room_id.clone(),
|
body.room_id.clone(),
|
||||||
Some(tombstone_event_id),
|
tombstone_event_id,
|
||||||
));
|
));
|
||||||
|
|
||||||
// Send a m.room.create event containing a predecessor field and the applicable
|
// Send a m.room.create event containing a predecessor field and the applicable
|
||||||
@@ -132,6 +171,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
// "creator" key no longer exists in V11 rooms
|
// "creator" key no longer exists in V11 rooms
|
||||||
create_event_content.remove("creator");
|
create_event_content.remove("creator");
|
||||||
},
|
},
|
||||||
|
// TODO(hydra): additional_creators
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -159,7 +199,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
|
return Err(Error::BadRequest(ErrorKind::BadJson, "Error forming creation event"));
|
||||||
}
|
}
|
||||||
|
|
||||||
services
|
let create_event_id = services
|
||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
.build_and_append_pdu(
|
.build_and_append_pdu(
|
||||||
@@ -173,11 +213,18 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
timestamp: None,
|
timestamp: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(&replacement_room),
|
replacement_room,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
.await?;
|
.await?;
|
||||||
|
let create_id = create_event_id.as_str().replace('$', "!");
|
||||||
|
let (replacement_room, state_lock) = if room_features.room_ids_as_hashes {
|
||||||
|
let parsed_room_id = RoomId::parse(&create_id)?;
|
||||||
|
(Some(parsed_room_id), services.rooms.state.mutex.lock(parsed_room_id).await)
|
||||||
|
} else {
|
||||||
|
(replacement_room, state_lock)
|
||||||
|
};
|
||||||
|
|
||||||
// Join the new room
|
// Join the new room
|
||||||
services
|
services
|
||||||
@@ -204,7 +251,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
timestamp: None,
|
timestamp: None,
|
||||||
},
|
},
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(&replacement_room),
|
replacement_room,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
@@ -243,7 +290,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
sender_user,
|
sender_user,
|
||||||
Some(&replacement_room),
|
replacement_room,
|
||||||
&state_lock,
|
&state_lock,
|
||||||
)
|
)
|
||||||
.boxed()
|
.boxed()
|
||||||
@@ -268,7 +315,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
.alias
|
.alias
|
||||||
.set_alias(alias, &replacement_room, sender_user)?;
|
.set_alias(alias, replacement_room.unwrap(), sender_user)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the old room power levels
|
// Get the old room power levels
|
||||||
@@ -310,6 +357,27 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
|
|
||||||
drop(state_lock);
|
drop(state_lock);
|
||||||
|
|
||||||
|
// For v12 rooms, send tombstone AFTER creating replacement room
|
||||||
|
if room_features.room_ids_as_hashes {
|
||||||
|
let old_room_state_lock = services.rooms.state.mutex.lock(&body.room_id).await;
|
||||||
|
// For v12 rooms, no event reference in predecessor due to cyclic dependency -
|
||||||
|
// could best effort one maybe?
|
||||||
|
services
|
||||||
|
.rooms
|
||||||
|
.timeline
|
||||||
|
.build_and_append_pdu(
|
||||||
|
PduBuilder::state(StateKey::new(), &RoomTombstoneEventContent {
|
||||||
|
body: "This room has been replaced".to_owned(),
|
||||||
|
replacement_room: replacement_room.unwrap().to_owned(),
|
||||||
|
}),
|
||||||
|
sender_user,
|
||||||
|
Some(&body.room_id),
|
||||||
|
&old_room_state_lock,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
drop(old_room_state_lock);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if the old room has a space parent, and if so, whether we should update
|
// Check if the old room has a space parent, and if so, whether we should update
|
||||||
// it (m.space.parent, room_id)
|
// it (m.space.parent, room_id)
|
||||||
let parents = services
|
let parents = services
|
||||||
@@ -334,8 +402,9 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
debug!(
|
debug!(
|
||||||
"Updating space {space_id} child event for room {} to {replacement_room}",
|
"Updating space {space_id} child event for room {} to {}",
|
||||||
&body.room_id
|
&body.room_id,
|
||||||
|
replacement_room.unwrap()
|
||||||
);
|
);
|
||||||
// First, drop the space's child event
|
// First, drop the space's child event
|
||||||
let state_lock = services.rooms.state.mutex.lock(space_id).await;
|
let state_lock = services.rooms.state.mutex.lock(space_id).await;
|
||||||
@@ -359,7 +428,10 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
// Now, add a new child event for the replacement room
|
// Now, add a new child event for the replacement room
|
||||||
debug!("Adding space child event for room {replacement_room} in space {space_id}");
|
debug!(
|
||||||
|
"Adding space child event for room {} in space {space_id}",
|
||||||
|
replacement_room.unwrap()
|
||||||
|
);
|
||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
.timeline
|
.timeline
|
||||||
@@ -372,7 +444,7 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
suggested: child.suggested,
|
suggested: child.suggested,
|
||||||
})
|
})
|
||||||
.expect("event is valid, we just created it"),
|
.expect("event is valid, we just created it"),
|
||||||
state_key: Some(replacement_room.as_str().into()),
|
state_key: Some(replacement_room.unwrap().as_str().into()),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
sender_user,
|
sender_user,
|
||||||
@@ -383,12 +455,15 @@ pub(crate) async fn upgrade_room_route(
|
|||||||
.await
|
.await
|
||||||
.ok();
|
.ok();
|
||||||
debug!(
|
debug!(
|
||||||
"Finished updating space {space_id} child event for room {} to {replacement_room}",
|
"Finished updating space {space_id} child event for room {} to {}",
|
||||||
&body.room_id
|
&body.room_id,
|
||||||
|
replacement_room.unwrap()
|
||||||
);
|
);
|
||||||
drop(state_lock);
|
drop(state_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the replacement room id
|
// Return the replacement room id
|
||||||
Ok(upgrade_room::v3::Response { replacement_room })
|
Ok(upgrade_room::v3::Response {
|
||||||
|
replacement_room: replacement_room.unwrap().to_owned(),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,10 @@ use ruma::{
|
|||||||
use service::rooms::short::{ShortEventId, ShortStateKey};
|
use service::rooms::short::{ShortEventId, ShortStateKey};
|
||||||
|
|
||||||
use super::{load_timeline, share_encrypted_room};
|
use super::{load_timeline, share_encrypted_room};
|
||||||
use crate::{Ruma, RumaResponse, client::ignored_filter};
|
use crate::{
|
||||||
|
Ruma, RumaResponse,
|
||||||
|
client::{ignored_filter, is_ignored_invite},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct StateChanges {
|
struct StateChanges {
|
||||||
@@ -238,6 +241,13 @@ pub(crate) async fn build_sync_events(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.rooms_invited(sender_user)
|
.rooms_invited(sender_user)
|
||||||
|
.wide_filter_map(async |(room_id, invite_state)| {
|
||||||
|
if is_ignored_invite(services, sender_user, &room_id).await {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((room_id, invite_state))
|
||||||
|
}
|
||||||
|
})
|
||||||
.fold_default(|mut invited_rooms: BTreeMap<_, _>, (room_id, invite_state)| async move {
|
.fold_default(|mut invited_rooms: BTreeMap<_, _>, (room_id, invite_state)| async move {
|
||||||
let invite_count = services
|
let invite_count = services
|
||||||
.rooms
|
.rooms
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ use conduwuit::{
|
|||||||
utils::{
|
utils::{
|
||||||
BoolExt, IterStream, ReadyExt, TryFutureExtExt,
|
BoolExt, IterStream, ReadyExt, TryFutureExtExt,
|
||||||
math::{ruma_from_usize, usize_from_ruma, usize_from_u64_truncated},
|
math::{ruma_from_usize, usize_from_ruma, usize_from_u64_truncated},
|
||||||
|
stream::WidebandExt,
|
||||||
},
|
},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -39,7 +40,7 @@ use ruma::{
|
|||||||
use super::{load_timeline, share_encrypted_room};
|
use super::{load_timeline, share_encrypted_room};
|
||||||
use crate::{
|
use crate::{
|
||||||
Ruma,
|
Ruma,
|
||||||
client::{DEFAULT_BUMP_TYPES, ignored_filter},
|
client::{DEFAULT_BUMP_TYPES, ignored_filter, is_ignored_invite},
|
||||||
};
|
};
|
||||||
|
|
||||||
type TodoRooms = BTreeMap<OwnedRoomId, (BTreeSet<TypeStateKey>, usize, u64)>;
|
type TodoRooms = BTreeMap<OwnedRoomId, (BTreeSet<TypeStateKey>, usize, u64)>;
|
||||||
@@ -102,6 +103,13 @@ pub(crate) async fn sync_events_v4_route(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.rooms_invited(sender_user)
|
.rooms_invited(sender_user)
|
||||||
|
.wide_filter_map(async |(room_id, invite_state)| {
|
||||||
|
if is_ignored_invite(&services, sender_user, &room_id).await {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((room_id, invite_state))
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(|r| r.0)
|
.map(|r| r.0)
|
||||||
.collect()
|
.collect()
|
||||||
.await;
|
.await;
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ use conduwuit::{
|
|||||||
BoolExt, FutureBoolExt, IterStream, ReadyExt, TryFutureExtExt,
|
BoolExt, FutureBoolExt, IterStream, ReadyExt, TryFutureExtExt,
|
||||||
future::ReadyEqExt,
|
future::ReadyEqExt,
|
||||||
math::{ruma_from_usize, usize_from_ruma},
|
math::{ruma_from_usize, usize_from_ruma},
|
||||||
|
stream::WidebandExt,
|
||||||
},
|
},
|
||||||
warn,
|
warn,
|
||||||
};
|
};
|
||||||
@@ -38,7 +39,7 @@ use ruma::{
|
|||||||
use super::share_encrypted_room;
|
use super::share_encrypted_room;
|
||||||
use crate::{
|
use crate::{
|
||||||
Ruma,
|
Ruma,
|
||||||
client::{DEFAULT_BUMP_TYPES, ignored_filter, sync::load_timeline},
|
client::{DEFAULT_BUMP_TYPES, ignored_filter, is_ignored_invite, sync::load_timeline},
|
||||||
};
|
};
|
||||||
|
|
||||||
type SyncInfo<'a> = (&'a UserId, &'a DeviceId, u64, &'a sync_events::v5::Request);
|
type SyncInfo<'a> = (&'a UserId, &'a DeviceId, u64, &'a sync_events::v5::Request);
|
||||||
@@ -106,6 +107,13 @@ pub(crate) async fn sync_events_v5_route(
|
|||||||
.rooms
|
.rooms
|
||||||
.state_cache
|
.state_cache
|
||||||
.rooms_invited(sender_user)
|
.rooms_invited(sender_user)
|
||||||
|
.wide_filter_map(async |(room_id, invite_state)| {
|
||||||
|
if is_ignored_invite(services, sender_user, &room_id).await {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some((room_id, invite_state))
|
||||||
|
}
|
||||||
|
})
|
||||||
.map(|r| r.0)
|
.map(|r| r.0)
|
||||||
.collect::<Vec<OwnedRoomId>>();
|
.collect::<Vec<OwnedRoomId>>();
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ pub(crate) async fn get_supported_versions_route(
|
|||||||
("us.cloke.msc4175".to_owned(), true), /* Profile field for user time zone (https://github.com/matrix-org/matrix-spec-proposals/pull/4175) */
|
("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) */
|
("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) */
|
("uk.timedout.msc4323".to_owned(), true), /* agnostic suspend (https://github.com/matrix-org/matrix-spec-proposals/pull/4323) */
|
||||||
|
("org.matrix.msc4155".to_owned(), true), /* invite filtering (https://github.com/matrix-org/matrix-spec-proposals/pull/4155) */
|
||||||
]),
|
]),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,13 +61,16 @@ pub(crate) async fn create_invite_route(
|
|||||||
let mut signed_event = utils::to_canonical_object(&body.event)
|
let mut signed_event = utils::to_canonical_object(&body.event)
|
||||||
.map_err(|_| err!(Request(InvalidParam("Invite event is invalid."))))?;
|
.map_err(|_| err!(Request(InvalidParam("Invite event is invalid."))))?;
|
||||||
|
|
||||||
let invited_user: OwnedUserId = signed_event
|
let recipient_user: OwnedUserId = signed_event
|
||||||
.get("state_key")
|
.get("state_key")
|
||||||
.try_into()
|
.try_into()
|
||||||
.map(UserId::to_owned)
|
.map(UserId::to_owned)
|
||||||
.map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?;
|
.map_err(|e| err!(Request(InvalidParam("Invalid state_key property: {e}"))))?;
|
||||||
|
|
||||||
if !services.globals.server_is_ours(invited_user.server_name()) {
|
if !services
|
||||||
|
.globals
|
||||||
|
.server_is_ours(recipient_user.server_name())
|
||||||
|
{
|
||||||
return Err!(Request(InvalidParam("User does not belong to this homeserver.")));
|
return Err!(Request(InvalidParam("User does not belong to this homeserver.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -75,7 +78,7 @@ pub(crate) async fn create_invite_route(
|
|||||||
services
|
services
|
||||||
.rooms
|
.rooms
|
||||||
.event_handler
|
.event_handler
|
||||||
.acl_check(invited_user.server_name(), &body.room_id)
|
.acl_check(recipient_user.server_name(), &body.room_id)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
services
|
services
|
||||||
@@ -89,18 +92,19 @@ pub(crate) async fn create_invite_route(
|
|||||||
// Add event_id back
|
// Add event_id back
|
||||||
signed_event.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.to_string()));
|
signed_event.insert("event_id".to_owned(), CanonicalJsonValue::String(event_id.to_string()));
|
||||||
|
|
||||||
let sender: &UserId = signed_event
|
let sender_user: &UserId = signed_event
|
||||||
.get("sender")
|
.get("sender")
|
||||||
.try_into()
|
.try_into()
|
||||||
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?;
|
.map_err(|e| err!(Request(InvalidParam("Invalid sender property: {e}"))))?;
|
||||||
|
|
||||||
if services.rooms.metadata.is_banned(&body.room_id).await
|
if services.rooms.metadata.is_banned(&body.room_id).await
|
||||||
&& !services.users.is_admin(&invited_user).await
|
&& !services.users.is_admin(&recipient_user).await
|
||||||
{
|
{
|
||||||
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
|
return Err!(Request(Forbidden("This room is banned on this homeserver.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
if services.config.block_non_admin_invites && !services.users.is_admin(&invited_user).await {
|
if services.config.block_non_admin_invites && !services.users.is_admin(&recipient_user).await
|
||||||
|
{
|
||||||
return Err!(Request(Forbidden("This server does not allow room invites.")));
|
return Err!(Request(Forbidden("This server does not allow room invites.")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,9 +135,9 @@ pub(crate) async fn create_invite_route(
|
|||||||
.state_cache
|
.state_cache
|
||||||
.update_membership(
|
.update_membership(
|
||||||
&body.room_id,
|
&body.room_id,
|
||||||
&invited_user,
|
&recipient_user,
|
||||||
RoomMemberEventContent::new(MembershipState::Invite),
|
RoomMemberEventContent::new(MembershipState::Invite),
|
||||||
sender,
|
sender_user,
|
||||||
Some(invite_state),
|
Some(invite_state),
|
||||||
body.via.clone(),
|
body.via.clone(),
|
||||||
true,
|
true,
|
||||||
@@ -141,7 +145,7 @@ pub(crate) async fn create_invite_route(
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
for appservice in services.appservice.read().await.values() {
|
for appservice in services.appservice.read().await.values() {
|
||||||
if appservice.is_user_match(&invited_user) {
|
if appservice.is_user_match(&recipient_user) {
|
||||||
services
|
services
|
||||||
.sending
|
.sending
|
||||||
.send_appservice_request(
|
.send_appservice_request(
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ pub(super) fn bad_request_code(kind: &ErrorKind) -> StatusCode {
|
|||||||
| ThreepidAuthFailed
|
| ThreepidAuthFailed
|
||||||
| UserDeactivated
|
| UserDeactivated
|
||||||
| ThreepidDenied
|
| ThreepidDenied
|
||||||
|
| InviteBlocked
|
||||||
| WrongRoomKeysVersion { .. }
|
| WrongRoomKeysVersion { .. }
|
||||||
| Forbidden { .. } => StatusCode::FORBIDDEN,
|
| Forbidden { .. } => StatusCode::FORBIDDEN,
|
||||||
|
|
||||||
|
|||||||
@@ -727,12 +727,20 @@ where
|
|||||||
let user_joined = user_for_join_auth_membership == &MembershipState::Join;
|
let user_joined = user_for_join_auth_membership == &MembershipState::Join;
|
||||||
let okay_power = is_creator(room_version, &creators, create_room, user_for_join_auth)
|
let okay_power = is_creator(room_version, &creators, create_room, user_for_join_auth)
|
||||||
|| auth_user_pl >= invite_level;
|
|| auth_user_pl >= invite_level;
|
||||||
|
trace!(
|
||||||
|
auth_user_pl=?auth_user_pl,
|
||||||
|
invite_level=?invite_level,
|
||||||
|
user_joined=?user_joined,
|
||||||
|
okay_power=?okay_power,
|
||||||
|
passing=?(user_joined && okay_power),
|
||||||
|
"user for join auth is valid check details"
|
||||||
|
);
|
||||||
user_joined && okay_power
|
user_joined && okay_power
|
||||||
} else {
|
} else {
|
||||||
// No auth user was given
|
// No auth user was given
|
||||||
|
trace!("No auth user given for join auth");
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
|
|
||||||
let sender_creator = is_creator(room_version, &creators, create_room, sender);
|
let sender_creator = is_creator(room_version, &creators, create_room, sender);
|
||||||
let target_creator = is_creator(room_version, &creators, create_room, target_user);
|
let target_creator = is_creator(room_version, &creators, create_room, target_user);
|
||||||
|
|
||||||
@@ -811,9 +819,7 @@ where
|
|||||||
false
|
false
|
||||||
},
|
},
|
||||||
| JoinRule::KnockRestricted(_) => {
|
| JoinRule::KnockRestricted(_) => {
|
||||||
let valid_join = user_for_join_auth_is_valid
|
if membership_allows_join || user_for_join_auth_is_valid {
|
||||||
|| sender_membership == MembershipState::Join;
|
|
||||||
if membership_allows_join || valid_join {
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
@@ -826,16 +832,14 @@ where
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
| JoinRule::Restricted(_) =>
|
| JoinRule::Restricted(_) =>
|
||||||
if !user_for_join_auth_is_valid
|
if membership_allows_join || user_for_join_auth_is_valid {
|
||||||
&& sender_membership != MembershipState::Join
|
true
|
||||||
{
|
} else {
|
||||||
warn!(
|
warn!(
|
||||||
"Join rule is a restricted one but no valid authorising user \
|
"Join rule is a restricted one but no valid authorising user \
|
||||||
was given"
|
was given"
|
||||||
);
|
);
|
||||||
false
|
false
|
||||||
} else {
|
|
||||||
true
|
|
||||||
},
|
},
|
||||||
| JoinRule::Public => true,
|
| JoinRule::Public => true,
|
||||||
| _ => {
|
| _ => {
|
||||||
|
|||||||
+1
-1
@@ -417,7 +417,7 @@ impl<'a, 'de: 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> {
|
|||||||
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
fn deserialize_any<V: Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
|
||||||
debug_assert_eq!(
|
debug_assert_eq!(
|
||||||
conduwuit::debug::type_name::<V>(),
|
conduwuit::debug::type_name::<V>(),
|
||||||
"serde_json::value::de::<impl serde::de::Deserialize for \
|
"serde_json::value::de::<impl serde_core::de::Deserialize for \
|
||||||
serde_json::value::Value>::deserialize::ValueVisitor",
|
serde_json::value::Value>::deserialize::ValueVisitor",
|
||||||
"deserialize_any: type not expected"
|
"deserialize_any: type not expected"
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -434,4 +434,8 @@ pub(super) static MAPS: &[Descriptor] = &[
|
|||||||
name: "userroomid_notificationcount",
|
name: "userroomid_notificationcount",
|
||||||
..descriptor::RANDOM
|
..descriptor::RANDOM
|
||||||
},
|
},
|
||||||
|
Descriptor {
|
||||||
|
name: "userroomid_invitesender",
|
||||||
|
..descriptor::RANDOM_SMALL
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
+5
-3
@@ -22,11 +22,13 @@ crate-type = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[package.metadata.deb]
|
[package.metadata.deb]
|
||||||
name = "conduwuit"
|
name = "continuwuity"
|
||||||
maintainer = "strawberry <strawberry@puppygock.gay>"
|
maintainer = "continuwuity developers <contact@continuwuity.org>"
|
||||||
copyright = "2024, strawberry <strawberry@puppygock.gay>"
|
copyright = "2024, continuwuity developers"
|
||||||
license-file = ["../../LICENSE", "3"]
|
license-file = ["../../LICENSE", "3"]
|
||||||
depends = "$auto, ca-certificates"
|
depends = "$auto, ca-certificates"
|
||||||
|
breaks = ["conduwuit (<<0.5.0)"]
|
||||||
|
replaces = ["conduwuit (<<0.5.0)"]
|
||||||
extended-description = """\
|
extended-description = """\
|
||||||
a cool hard fork of Conduit, a Matrix homeserver written in Rust"""
|
a cool hard fork of Conduit, a Matrix homeserver written in Rust"""
|
||||||
section = "net"
|
section = "net"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use conduwuit::{
|
|||||||
use database::{Deserialized, Ignore, Interfix, Map};
|
use database::{Deserialized, Ignore, Interfix, Map};
|
||||||
use futures::{Stream, StreamExt, future::join5, pin_mut};
|
use futures::{Stream, StreamExt, future::join5, pin_mut};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
OwnedRoomId, RoomId, ServerName, UserId,
|
OwnedRoomId, OwnedUserId, RoomId, ServerName, UserId,
|
||||||
events::{AnyStrippedStateEvent, AnySyncStateEvent, room::member::MembershipState},
|
events::{AnyStrippedStateEvent, AnySyncStateEvent, room::member::MembershipState},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
};
|
};
|
||||||
@@ -49,6 +49,7 @@ struct Data {
|
|||||||
userroomid_joined: Arc<Map>,
|
userroomid_joined: Arc<Map>,
|
||||||
userroomid_leftstate: Arc<Map>,
|
userroomid_leftstate: Arc<Map>,
|
||||||
userroomid_knockedstate: Arc<Map>,
|
userroomid_knockedstate: Arc<Map>,
|
||||||
|
userroomid_invitesender: Arc<Map>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type AppServiceInRoomCache = SyncRwLock<HashMap<OwnedRoomId, HashMap<String, bool>>>;
|
type AppServiceInRoomCache = SyncRwLock<HashMap<OwnedRoomId, HashMap<String, bool>>>;
|
||||||
@@ -83,6 +84,7 @@ impl crate::Service for Service {
|
|||||||
userroomid_joined: args.db["userroomid_joined"].clone(),
|
userroomid_joined: args.db["userroomid_joined"].clone(),
|
||||||
userroomid_leftstate: args.db["userroomid_leftstate"].clone(),
|
userroomid_leftstate: args.db["userroomid_leftstate"].clone(),
|
||||||
userroomid_knockedstate: args.db["userroomid_knockedstate"].clone(),
|
userroomid_knockedstate: args.db["userroomid_knockedstate"].clone(),
|
||||||
|
userroomid_invitesender: args.db["userroomid_invitesender"].clone(),
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
@@ -523,3 +525,14 @@ pub async fn is_left(&self, user_id: &UserId, room_id: &RoomId) -> bool {
|
|||||||
let key = (user_id, room_id);
|
let key = (user_id, room_id);
|
||||||
self.db.userroomid_leftstate.qry(&key).await.is_ok()
|
self.db.userroomid_leftstate.qry(&key).await.is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
#[tracing::instrument(skip(self), level = "trace")]
|
||||||
|
pub async fn invite_sender(&self, user_id: &UserId, room_id: &RoomId) -> Result<OwnedUserId> {
|
||||||
|
let key = (user_id, room_id);
|
||||||
|
self.db
|
||||||
|
.userroomid_invitesender
|
||||||
|
.qry(&key)
|
||||||
|
.await
|
||||||
|
.deserialized()
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use conduwuit::{Result, implement, is_not_empty, utils::ReadyExt, warn};
|
use conduwuit::{Err, Result, implement, is_not_empty, utils::ReadyExt, warn};
|
||||||
use database::{Json, serialize_key};
|
use database::{Json, serialize_key};
|
||||||
use futures::StreamExt;
|
use futures::StreamExt;
|
||||||
use ruma::{
|
use ruma::{
|
||||||
@@ -9,6 +9,7 @@ use ruma::{
|
|||||||
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
|
AnyStrippedStateEvent, AnySyncStateEvent, GlobalAccountDataEventType,
|
||||||
RoomAccountDataEventType, StateEventType,
|
RoomAccountDataEventType, StateEventType,
|
||||||
direct::DirectEvent,
|
direct::DirectEvent,
|
||||||
|
invite_permission_config::FilterLevel,
|
||||||
room::{
|
room::{
|
||||||
create::RoomCreateEventContent,
|
create::RoomCreateEventContent,
|
||||||
member::{MembershipState, RoomMemberEventContent},
|
member::{MembershipState, RoomMemberEventContent},
|
||||||
@@ -121,12 +122,21 @@ pub async fn update_membership(
|
|||||||
self.mark_as_joined(user_id, room_id);
|
self.mark_as_joined(user_id, room_id);
|
||||||
},
|
},
|
||||||
| MembershipState::Invite => {
|
| MembershipState::Invite => {
|
||||||
// We want to know if the sender is ignored by the receiver
|
// return an error for blocked invites. ignored invites aren't handled here
|
||||||
if self.services.users.user_is_ignored(sender, user_id).await {
|
// since the recipient's membership should still be changed to `invite`.
|
||||||
return Ok(());
|
// they're filtered out in the individual /sync handlers
|
||||||
|
if matches!(
|
||||||
|
self.services
|
||||||
|
.users
|
||||||
|
.invite_filter_level(sender, user_id)
|
||||||
|
.await,
|
||||||
|
FilterLevel::Block
|
||||||
|
) {
|
||||||
|
return Err!(Request(InviteBlocked(
|
||||||
|
"{user_id} has blocked invites from {sender}."
|
||||||
|
)));
|
||||||
}
|
}
|
||||||
|
self.mark_as_invited(user_id, room_id, sender, last_state, invite_via)
|
||||||
self.mark_as_invited(user_id, room_id, last_state, invite_via)
|
|
||||||
.await;
|
.await;
|
||||||
},
|
},
|
||||||
| MembershipState::Leave | MembershipState::Ban => {
|
| MembershipState::Leave | MembershipState::Ban => {
|
||||||
@@ -231,6 +241,7 @@ pub fn mark_as_joined(&self, user_id: &UserId, room_id: &RoomId) {
|
|||||||
|
|
||||||
self.db.userroomid_invitestate.remove(&userroom_id);
|
self.db.userroomid_invitestate.remove(&userroom_id);
|
||||||
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
||||||
|
self.db.userroomid_invitesender.remove(&userroom_id);
|
||||||
|
|
||||||
self.db.userroomid_leftstate.remove(&userroom_id);
|
self.db.userroomid_leftstate.remove(&userroom_id);
|
||||||
self.db.roomuserid_leftcount.remove(&roomuser_id);
|
self.db.roomuserid_leftcount.remove(&roomuser_id);
|
||||||
@@ -268,6 +279,7 @@ pub fn mark_as_left(&self, user_id: &UserId, room_id: &RoomId) {
|
|||||||
|
|
||||||
self.db.userroomid_invitestate.remove(&userroom_id);
|
self.db.userroomid_invitestate.remove(&userroom_id);
|
||||||
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
||||||
|
self.db.userroomid_invitesender.remove(&userroom_id);
|
||||||
|
|
||||||
self.db.userroomid_knockedstate.remove(&userroom_id);
|
self.db.userroomid_knockedstate.remove(&userroom_id);
|
||||||
self.db.roomuserid_knockedcount.remove(&roomuser_id);
|
self.db.roomuserid_knockedcount.remove(&roomuser_id);
|
||||||
@@ -304,6 +316,7 @@ pub fn mark_as_knocked(
|
|||||||
|
|
||||||
self.db.userroomid_invitestate.remove(&userroom_id);
|
self.db.userroomid_invitestate.remove(&userroom_id);
|
||||||
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
self.db.roomuserid_invitecount.remove(&roomuser_id);
|
||||||
|
self.db.userroomid_invitesender.remove(&userroom_id);
|
||||||
|
|
||||||
self.db.userroomid_leftstate.remove(&userroom_id);
|
self.db.userroomid_leftstate.remove(&userroom_id);
|
||||||
self.db.roomuserid_leftcount.remove(&roomuser_id);
|
self.db.roomuserid_leftcount.remove(&roomuser_id);
|
||||||
@@ -335,6 +348,7 @@ pub async fn mark_as_invited(
|
|||||||
&self,
|
&self,
|
||||||
user_id: &UserId,
|
user_id: &UserId,
|
||||||
room_id: &RoomId,
|
room_id: &RoomId,
|
||||||
|
sender_user: &UserId,
|
||||||
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
last_state: Option<Vec<Raw<AnyStrippedStateEvent>>>,
|
||||||
invite_via: Option<Vec<OwnedServerName>>,
|
invite_via: Option<Vec<OwnedServerName>>,
|
||||||
) {
|
) {
|
||||||
@@ -350,6 +364,9 @@ pub async fn mark_as_invited(
|
|||||||
self.db
|
self.db
|
||||||
.roomuserid_invitecount
|
.roomuserid_invitecount
|
||||||
.raw_aput::<8, _, _>(&roomuser_id, self.services.globals.next_count().unwrap());
|
.raw_aput::<8, _, _>(&roomuser_id, self.services.globals.next_count().unwrap());
|
||||||
|
self.db
|
||||||
|
.userroomid_invitesender
|
||||||
|
.raw_put(&userroom_id, sender_user);
|
||||||
|
|
||||||
self.db.userroomid_joined.remove(&userroom_id);
|
self.db.userroomid_joined.remove(&userroom_id);
|
||||||
self.db.roomuserid_joined.remove(&roomuser_id);
|
self.db.roomuserid_joined.remove(&roomuser_id);
|
||||||
|
|||||||
@@ -274,8 +274,6 @@ pub async fn create_hash_and_sign_event(
|
|||||||
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(pdu.event_id.clone().into()));
|
pdu_json.insert("event_id".into(), CanonicalJsonValue::String(pdu.event_id.clone().into()));
|
||||||
|
|
||||||
// Check with the policy server
|
// Check with the policy server
|
||||||
// TODO(hydra): Skip this check for create events (why didnt we do this
|
|
||||||
// already?)
|
|
||||||
if room_id.is_some() {
|
if room_id.is_some() {
|
||||||
trace!(
|
trace!(
|
||||||
"Checking event {} in room {} with policy server",
|
"Checking event {} in room {} with policy server",
|
||||||
|
|||||||
@@ -20,7 +20,9 @@ use ruma::{
|
|||||||
api::client::{device::Device, error::ErrorKind, filter::FilterDefinition},
|
api::client::{device::Device, error::ErrorKind, filter::FilterDefinition},
|
||||||
encryption::{CrossSigningKey, DeviceKeys, OneTimeKey},
|
encryption::{CrossSigningKey, DeviceKeys, OneTimeKey},
|
||||||
events::{
|
events::{
|
||||||
AnyToDeviceEvent, GlobalAccountDataEventType, ignored_user_list::IgnoredUserListEvent,
|
AnyToDeviceEvent, GlobalAccountDataEventType,
|
||||||
|
ignored_user_list::IgnoredUserListEvent,
|
||||||
|
invite_permission_config::{FilterLevel, InvitePermissionConfigEvent},
|
||||||
},
|
},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
};
|
};
|
||||||
@@ -139,6 +141,26 @@ impl Service {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the recipient's filter level for an invite from the sender.
|
||||||
|
pub async fn invite_filter_level(
|
||||||
|
&self,
|
||||||
|
sender_user: &UserId,
|
||||||
|
recipient_user: &UserId,
|
||||||
|
) -> FilterLevel {
|
||||||
|
if self.user_is_ignored(sender_user, recipient_user).await {
|
||||||
|
FilterLevel::Ignore
|
||||||
|
} else {
|
||||||
|
self.services
|
||||||
|
.account_data
|
||||||
|
.get_global(recipient_user, GlobalAccountDataEventType::InvitePermissionConfig)
|
||||||
|
.await
|
||||||
|
.map(|config: InvitePermissionConfigEvent| {
|
||||||
|
config.content.user_filter_level(sender_user)
|
||||||
|
})
|
||||||
|
.unwrap_or(FilterLevel::Allow)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if a user is an admin
|
/// Check if a user is an admin
|
||||||
#[inline]
|
#[inline]
|
||||||
pub async fn is_admin(&self, user_id: &UserId) -> bool {
|
pub async fn is_admin(&self, user_id: &UserId) -> bool {
|
||||||
|
|||||||
Reference in New Issue
Block a user