add: request-to-join communities

add: private joined communities setting
add: "void" community
add: ability to delete communities
This commit is contained in:
trisua 2025-04-01 15:03:56 -04:00
parent 3a8af17154
commit d0c1fbcf9a
20 changed files with 669 additions and 122 deletions

View file

@ -11,26 +11,12 @@ use tetratto_core::model::{
Error,
auth::User,
communities::{Community, CommunityReadAccess},
communities_permissions::CommunityPermission,
};
macro_rules! check_permissions {
($community:ident, $jar:ident, $data:ident, $user:ident) => {
match $community.read_access {
CommunityReadAccess::Private => {
if let Some(ref ua) = $user {
if ua.id != $community.owner {
return Err(Html(
render_error(Error::NotAllowed, &$jar, &$data, &$user).await,
));
}
} else {
return Err(Html(
render_error(Error::NotAllowed, &$jar, &$data, &$user).await,
));
}
}
_ => (),
};
($community:ident, $jar:ident, $data:ident, $user:ident) => {{
let mut is_member: bool = false;
if let Some(ref ua) = $user {
if let Ok(membership) = $data
@ -42,30 +28,54 @@ macro_rules! check_permissions {
return Err(Html(
render_error(Error::NotAllowed, &$jar, &$data, &$user).await,
));
} else if membership.role.check_member() {
is_member = true;
}
}
}
};
match $community.read_access {
CommunityReadAccess::Joined => {
if !is_member {
false
} else {
true
}
}
_ => true,
}
}};
}
macro_rules! community_context_bools {
($data:ident, $user:ident, $community:ident) => {{
let membership = if let Some(ref ua) = $user {
match $data
.0
.get_membership_by_owner_community(ua.id, $community.id)
.await
{
Ok(m) => Some(m),
Err(_) => None,
}
} else {
None
};
let is_owner = if let Some(ref ua) = $user {
ua.id == $community.owner
} else {
false
};
let is_joined = if let Some(ref ua) = $user {
if let Ok(membership) = $data
.0
.get_membership_by_owner_community(ua.id, $community.id)
.await
{
membership.role.check_member()
} else {
false
}
let is_joined = if let Some(ref membership) = membership {
membership.role.check_member()
} else {
false
};
let is_pending = if let Some(ref membership) = membership {
membership.role.check(CommunityPermission::REQUESTED)
} else {
false
};
@ -76,7 +86,7 @@ macro_rules! community_context_bools {
false
};
(is_owner, is_joined, can_post)
(is_owner, is_joined, is_pending, can_post)
}};
}
@ -120,12 +130,16 @@ pub fn community_context(
community: &Community,
is_owner: bool,
is_joined: bool,
is_pending: bool,
can_post: bool,
can_read: bool,
) {
context.insert("community", &community);
context.insert("is_owner", &is_owner);
context.insert("is_joined", &is_joined);
context.insert("is_pending", &is_pending);
context.insert("can_post", &can_post);
context.insert("can_read", &can_read);
}
/// `/community/{title}`
@ -143,8 +157,21 @@ pub async fn feed_request(
Err(e) => return Err(Html(render_error(e, &jar, &data, &user).await)),
};
if community.id == 0 {
// don't show page for void community
return Err(Html(
render_error(
Error::GeneralNotFound("community".to_string()),
&jar,
&data,
&user,
)
.await,
));
}
// check permissions
check_permissions!(community, jar, data, user);
let can_read = check_permissions!(community, jar, data, user);
// ...
let feed = match data
@ -163,10 +190,19 @@ pub async fn feed_request(
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0, lang, &user).await;
let (is_owner, is_joined, can_post) = community_context_bools!(data, user, community);
let (is_owner, is_joined, is_pending, can_post) =
community_context_bools!(data, user, community);
context.insert("feed", &feed);
community_context(&mut context, &community, is_owner, is_joined, can_post);
community_context(
&mut context,
&community,
is_owner,
is_joined,
is_pending,
can_post,
can_read,
);
// return
Ok(Html(
@ -242,7 +278,7 @@ pub async fn post_request(
};
// check permissions
check_permissions!(community, jar, data, user);
let can_read = check_permissions!(community, jar, data, user);
// ...
let feed = match data.0.get_post_comments(post.id, 12, props.page).await {
@ -257,7 +293,8 @@ pub async fn post_request(
let lang = get_lang!(jar, data.0);
let mut context = initial_context(&data.0.0, lang, &user).await;
let (is_owner, is_joined, can_post) = community_context_bools!(data, user, community);
let (is_owner, is_joined, is_pending, can_post) =
community_context_bools!(data, user, community);
context.insert("post", &post);
context.insert("replies", &feed);
@ -269,7 +306,15 @@ pub async fn post_request(
.await
.unwrap_or(User::deleted()),
);
community_context(&mut context, &community, is_owner, is_joined, can_post);
community_context(
&mut context,
&community,
is_owner,
is_joined,
is_pending,
can_post,
can_read,
);
// return
Ok(Html(