Compare commits

...

3 commits

Author SHA1 Message Date
magmaus3
73854e42a3 add initial alpine packaging
notes:
- to build the package, you must use the cargo version from the edge branch
  (by building on edge or by installing it manually)
- building from git requires some work (abuild supports snapshots for getting
  the release from git, but the version number would remain unchanged)
- the apkbuild doesn't include any packaging tests (as i don't know what to include)
2025-05-26 17:47:27 +00:00
Jade Ellis
2e0bb01595 feat: For knock_restricted rooms, automatically join rooms we meet
Some checks failed
Documentation / Build and Deploy Documentation (push) Failing after 41s
Release Docker Image / define-variables (push) Failing after 1s
Release Docker Image / build-image (linux/amd64, linux-amd64) (push) Has been skipped
Release Docker Image / build-image (linux/arm64, linux-arm64) (push) Has been skipped
Release Docker Image / merge (push) Has been skipped
Rust Checks / Format (push) Failing after 1s
Rust Checks / Clippy (push) Failing after 10s
Rust Checks / Cargo Test (push) Failing after 8s
restrictions for rather than knocking
2025-05-26 16:23:20 +00:00
Jade Ellis
d9d8e0acfd fix: Allow joining via invite for knock_restricted rooms 2025-05-26 16:23:20 +00:00
7 changed files with 206 additions and 1 deletions

63
alpine/APKBUILD Normal file
View file

@ -0,0 +1,63 @@
# Contributor: magmaus3 <maia@magmaus3.eu.org>
# Maintainer: magmaus3 <maia@magmaus3.eu.org>
pkgname=continuwuity
# abuild doesn't like the format of v0.5.0-rc.5, so i had to change it
# see https://wiki.alpinelinux.org/wiki/Package_policies
pkgver=0.5.0_rc5
pkgrel=0
pkgdesc="a continuwuation of a very cool, featureful fork of conduit"
url="https://continuwuity.org/"
arch="all"
license="Apache-2.0"
depends="liburing"
# cargo version on alpine v3.21 is too old to use the 2024 edition
# i recommend either building everything on edge, or adding
# the edge repo as a tag
makedepends="cargo liburing-dev clang-dev linux-headers"
checkdepends=""
install="$pkgname.pre-install"
subpackages="$pkgname-openrc"
source="https://forgejo.ellis.link/continuwuation/continuwuity/archive/v0.5.0-rc.5.tar.gz
continuwuity.initd
continuwuity.confd
"
builddir="$srcdir/continuwuity"
options="net !check"
prepare() {
default_prepare
cd $srcdir/continuwuity
# add the default database path to the config (commented out)
cat conduwuit-example.toml \
| sed '/#database_path/ s:$: "/var/lib/continuwuity":' \
> "$srcdir"/continuwuity.toml
cargo fetch --target="$CTARGET" --locked
}
build() {
cargo build --frozen --release --all-features
}
check() {
# TODO: make sure the tests work
#cargo test --frozen
return
}
package() {
cd $srcdir
install -Dm755 continuwuity/target/release/conduwuit "$pkgdir"/usr/bin/continuwuity
install -Dm644 "$srcdir"/continuwuity.toml -t "$pkgdir"/etc/continuwuity
install -Dm755 "$srcdir"/continuwuity.initd "$pkgdir"/etc/init.d/continuwuity
install -Dm644 "$srcdir"/continuwuity.confd "$pkgdir"/etc/conf.d/continuwuity
}
sha512sums="
66f6da5e98b6f7bb8c1082500101d5c87b1b79955c139b44c6ef5123919fb05feb0dffc669a3af1bc8d571ddb9f3576660f08dc10a6b19eab6db9e391175436a v0.5.0-rc.5.tar.gz
0482674be24740496d70da256d4121c5a5e3b749f2445d2bbe0e8991f1449de052724f8427da21a6f55574bc53eac9ca1e47e5012b4c13049b2b39044734d80d continuwuity.initd
38e2576278b450d16ba804dd8f4a128f18cd793e6c3ce55aedee1e186905755b31ee23baaa6586b1ab0e25a1f29bf1ea86bfaae4185b0cb1a29203726a199426 continuwuity.confd
"

7
alpine/README.md Normal file
View file

@ -0,0 +1,7 @@
# building
1. [set up your build
environment](https://wiki.alpinelinux.org/wiki/Include:Setup_your_system_and_account_for_building_packages)
2. run `abuild` (or `abuild -K` if you want to keep the source directory to make
rebuilding faster)

View file

@ -0,0 +1,3 @@
supervisor=supervise-daemon
export CONTINUWUITY_CONFIG=/etc/continuwuity/continuwuity.toml

19
alpine/continuwuity.initd Normal file
View file

@ -0,0 +1,19 @@
#!/sbin/openrc-run
command="/usr/bin/continuwuity"
command_user="continuwuity:continuwuity"
command_args="--config ${CONTINUWUITY_CONFIG=/etc/continuwuity/continuwuity.toml}"
command_background=true
pidfile="/run/$RC_SVCNAME.pid"
output_log="/var/log/continuwuity.log"
error_log="/var/log/continuwuity.log"
depend() {
need net
}
start_pre() {
checkpath -d -m 0755 -o "$command_user" /var/lib/continuwuity
checkpath -f -m 0644 -o "$command_user" "$output_log"
}

View file

@ -0,0 +1,4 @@
#!/bin/sh
addgroup -S continuwuity 2>/dev/null
adduser -S -D -H -h /var/lib/continuwuity -s /sbin/nologin -G continuwuity -g continuwuity continuwuity 2>/dev/null
exit 0

View file

@ -2162,6 +2162,109 @@ async fn knock_room_by_id_helper(
}
}
// For knock_restricted rooms, check if the user meets the restricted conditions
// If they do, attempt to join instead of knock
// This is not mentioned in the spec, but should be allowable (we're allowed to
// auto-join invites to knocked rooms)
let join_rule = services.rooms.state_accessor.get_join_rules(room_id).await;
if let JoinRule::KnockRestricted(restricted) = &join_rule {
let restriction_rooms: Vec<_> = restricted
.allow
.iter()
.filter_map(|a| match a {
| AllowRule::RoomMembership(r) => Some(&r.room_id),
| _ => None,
})
.collect();
// Check if the user is in any of the allowed rooms
let mut user_meets_restrictions = false;
for restriction_room_id in &restriction_rooms {
if services
.rooms
.state_cache
.is_joined(sender_user, restriction_room_id)
.await
{
user_meets_restrictions = true;
break;
}
}
// If the user meets the restrictions, try joining instead
if user_meets_restrictions {
debug_info!(
"{sender_user} meets the restricted criteria in knock_restricted room \
{room_id}, attempting to join instead of knock"
);
// For this case, we need to drop the state lock and get a new one in
// join_room_by_id_helper We need to release the lock here and let
// join_room_by_id_helper acquire it again
drop(state_lock);
match join_room_by_id_helper(
services,
sender_user,
room_id,
reason.clone(),
servers,
None,
&None,
)
.await
{
| Ok(_) => return Ok(knock_room::v3::Response::new(room_id.to_owned())),
| Err(e) => {
debug_warn!(
"Failed to convert knock to join for {sender_user} in {room_id}: {e:?}"
);
// Get a new state lock for the remaining knock logic
let new_state_lock = services.rooms.state.mutex.lock(room_id).await;
let server_in_room = services
.rooms
.state_cache
.server_in_room(services.globals.server_name(), room_id)
.await;
let local_knock = server_in_room
|| servers.is_empty()
|| (servers.len() == 1 && services.globals.server_is_ours(&servers[0]));
if local_knock {
knock_room_helper_local(
services,
sender_user,
room_id,
reason,
servers,
new_state_lock,
)
.boxed()
.await?;
} else {
knock_room_helper_remote(
services,
sender_user,
room_id,
reason,
servers,
new_state_lock,
)
.boxed()
.await?;
}
return Ok(knock_room::v3::Response::new(room_id.to_owned()));
},
}
}
} else if !matches!(join_rule, JoinRule::Knock | JoinRule::KnockRestricted(_)) {
debug_warn!(
"{sender_user} attempted to knock on room {room_id} but its join rule is \
{join_rule:?}, not knock or knock_restricted"
);
}
let server_in_room = services
.rooms
.state_cache
@ -2209,6 +2312,12 @@ async fn knock_room_helper_local(
return Err!(Request(Forbidden("This room does not support knocking.")));
}
// Verify that this room has a valid knock or knock_restricted join rule
let join_rule = services.rooms.state_accessor.get_join_rules(room_id).await;
if !matches!(join_rule, JoinRule::Knock | JoinRule::KnockRestricted(_)) {
return Err!(Request(Forbidden("This room's join rule does not allow knocking.")));
}
let content = RoomMemberEventContent {
displayname: services.users.displayname(sender_user).await.ok(),
avatar_url: services.users.avatar_url(sender_user).await.ok(),

View file

@ -638,7 +638,7 @@ fn valid_membership_change(
warn!(?target_user_membership_event_id, "Banned user can't join");
false
} else if (join_rules == JoinRule::Invite
|| room_version.allow_knocking && join_rules == JoinRule::Knock)
|| room_version.allow_knocking && (join_rules == JoinRule::Knock || matches!(join_rules, JoinRule::KnockRestricted(_))))
// If the join_rule is invite then allow if membership state is invite or join
&& (target_user_current_membership == MembershipState::Join
|| target_user_current_membership == MembershipState::Invite)