diff --git a/crates/app/src/assets.rs b/crates/app/src/assets.rs index df26836..1fbf106 100644 --- a/crates/app/src/assets.rs +++ b/crates/app/src/assets.rs @@ -57,6 +57,7 @@ pub const PROFILE_FOLLOWERS: &str = include_str!("./public/html/profile/follower pub const PROFILE_WARNING: &str = include_str!("./public/html/profile/warning.html"); pub const PROFILE_PRIVATE: &str = include_str!("./public/html/profile/private.html"); pub const PROFILE_BLOCKED: &str = include_str!("./public/html/profile/blocked.html"); +pub const PROFILE_BANNED: &str = include_str!("./public/html/profile/banned.html"); pub const COMMUNITIES_LIST: &str = include_str!("./public/html/communities/list.html"); pub const COMMUNITIES_BASE: &str = include_str!("./public/html/communities/base.html"); @@ -257,6 +258,7 @@ pub(crate) async fn write_assets(config: &Config) -> PathBufD { write_template!(html_path->"profile/warning.html"(crate::assets::PROFILE_WARNING) --config=config); write_template!(html_path->"profile/private.html"(crate::assets::PROFILE_PRIVATE) --config=config); write_template!(html_path->"profile/blocked.html"(crate::assets::PROFILE_BLOCKED) --config=config); + write_template!(html_path->"profile/banned.html"(crate::assets::PROFILE_BANNED) --config=config); write_template!(html_path->"communities/list.html"(crate::assets::COMMUNITIES_LIST) -d "communities" --config=config); write_template!(html_path->"communities/base.html"(crate::assets::COMMUNITIES_BASE) --config=config); diff --git a/crates/app/src/langs/en-US.toml b/crates/app/src/langs/en-US.toml index 4d5e9ab..cfb4088 100644 --- a/crates/app/src/langs/en-US.toml +++ b/crates/app/src/langs/en-US.toml @@ -69,6 +69,8 @@ version = "1.0.0" "auth:label.blocked_profile" = "You're blocked" "auth:label.blocked_profile_message" = "This user has blocked you." "auth:action.message" = "Message" +"auth:label.banned" = "Banned" +"auth:label.banned_message" = "This user has been banned for breaking the site's rules." "communities:action.create" = "Create" "communities:action.select" = "Select" diff --git a/crates/app/src/macros.rs b/crates/app/src/macros.rs index c7410a0..2b87228 100644 --- a/crates/app/src/macros.rs +++ b/crates/app/src/macros.rs @@ -98,6 +98,17 @@ macro_rules! get_lang { #[macro_export] macro_rules! check_user_blocked_or_private { ($user:ident, $other_user:ident, $data:ident, $jar:ident) => { + // check if other user is banned + if $other_user.permissions.check_banned() { + let lang = get_lang!($jar, $data.0); + let mut context = initial_context(&$data.0.0, lang, &$user).await; + context.insert("profile", &$other_user); + + return Ok(Html( + $data.1.render("profile/banned.html", &context).unwrap(), + )); + } + // check if we're blocked if let Some(ref ua) = $user { if $data diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 7a242a5..50c7701 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -42,6 +42,13 @@ fn check_supporter(value: &Value, _: &HashMap) -> tera::Result) -> tera::Result { + Ok(FinePermission::from_bits(value.as_u64().unwrap() as u32) + .unwrap() + .check(FinePermission::STAFF_BADGE) + .into()) +} + #[tokio::main(flavor = "multi_thread")] async fn main() { tracing_subscriber::fmt() @@ -70,6 +77,7 @@ async fn main() { tera.register_filter("markdown", render_markdown); tera.register_filter("color", color_escape); tera.register_filter("has_supporter", check_supporter); + tera.register_filter("has_staff_badge", check_staff_badge); let client = Client::new(); diff --git a/crates/app/src/public/html/mod/profile.html b/crates/app/src/public/html/mod/profile.html index d16612d..d201229 100644 --- a/crates/app/src/public/html/mod/profile.html +++ b/crates/app/src/public/html/mod/profile.html @@ -236,6 +236,8 @@ MANAGE_MESSAGES: 1 << 23, MANAGE_UPLOADS: 1 << 24, MANAGE_EMOJIS: 1 << 25, + MANAGE_STACKS: 1 << 26, + STAFF_BADGE: 1 << 27, }, ], ); diff --git a/crates/app/src/public/html/profile/banned.html b/crates/app/src/public/html/profile/banned.html new file mode 100644 index 0000000..aec1122 --- /dev/null +++ b/crates/app/src/public/html/profile/banned.html @@ -0,0 +1,27 @@ +{% extends "root.html" %} {% block head %} +{{ profile.username }} (banned) - {{ config.name }} +{% endblock %} {% block body %} {{ macros::nav() }} +
+
+
+
+ {{ components::avatar(username=profile.username, size="24px") }} + {{ profile.username }} +
+ + {{ text "auth:label.banned" }} +
+ +
+ {{ text "auth:label.banned_message" }} + + +
+
+
+{% endblock %} diff --git a/crates/app/src/public/html/profile/base.html b/crates/app/src/public/html/profile/base.html index 3dcf1de..2011245 100644 --- a/crates/app/src/public/html/profile/base.html +++ b/crates/app/src/public/html/profile/base.html @@ -47,7 +47,7 @@ }}
-

+

{{ components::username(user=profile) }} {% if profile.is_verified %} @@ -56,11 +56,17 @@ {% endif %} - {% if is_supporter %} + {% if profile.permissions|has_supporter %} {{ icon "star" }} {% endif %} + + {% if profile.permissions|has_staff_badge %} + + {{ icon "shield-user" }} + + {% endif %}

{{ profile.username }} diff --git a/crates/core/src/database/posts.rs b/crates/core/src/database/posts.rs index d46ee3e..dfa279b 100644 --- a/crates/core/src/database/posts.rs +++ b/crates/core/src/database/posts.rs @@ -102,20 +102,23 @@ impl DataManager { Err(_) => return None, }; - if let Some(ua) = user { - // TODO: maybe check community membership to see if we can MANAGE_POSTS in community - if owner.settings.private_profile - && owner.id != ua.id - && !ua.permissions.check(FinePermission::MANAGE_POSTS) - { - if self - .get_userfollow_by_initiator_receiver(owner.id, ua.id) - .await - .is_err() + // TODO: maybe check community membership to see if we can MANAGE_POSTS in community + if owner.settings.private_profile { + if let Some(ua) = user { + if owner.id != ua.id && !ua.permissions.check(FinePermission::MANAGE_POSTS) { - // owner isn't following us, we aren't the owner, AND we don't have MANAGE_POSTS permission - return None; + if self + .get_userfollow_by_initiator_receiver(owner.id, ua.id) + .await + .is_err() + { + // owner isn't following us, we aren't the owner, AND we don't have MANAGE_POSTS permission + return None; + } } + } else { + // private profile, but we're an unauthenticated user + return None; } } @@ -171,6 +174,8 @@ impl DataManager { let mut out: Vec<(Post, User, Option<(User, Post)>, Option<(Question, User)>)> = Vec::new(); let mut users: HashMap = HashMap::new(); + let mut seen_user_follow_statuses: HashMap<(usize, usize), bool> = HashMap::new(); + for post in posts { let owner = post.owner; @@ -187,6 +192,40 @@ impl DataManager { )); } else { let ua = self.get_user_by_id(owner).await?; + + // check relationship + if ua.settings.private_profile { + if let Some(ua1) = user { + if ua1.id == 0 { + continue; + } + + if let Some(is_following) = seen_user_follow_statuses.get(&(ua.id, ua1.id)) + { + if !is_following && (ua.id != ua1.id) { + // post owner is not following us + continue; + } + } else { + if self + .get_userfollow_by_initiator_receiver(ua.id, ua1.id) + .await + .is_err() + { + // post owner is not following us + seen_user_follow_statuses.insert((ua.id, ua1.id), false); + continue; + } + + seen_user_follow_statuses.insert((ua.id, ua1.id), true); + } + } else { + // private post, but not authenticated + continue; + } + } + + // ... users.insert(owner, ua.clone()); out.push(( post.clone(), diff --git a/crates/core/src/model/permissions.rs b/crates/core/src/model/permissions.rs index 207bd55..9be028c 100644 --- a/crates/core/src/model/permissions.rs +++ b/crates/core/src/model/permissions.rs @@ -35,6 +35,7 @@ bitflags! { const MANAGE_UPLOADS = 1 << 24; const MANAGE_EMOJIS = 1 << 25; const MANAGE_STACKS = 1 << 26; + const STAFF_BADGE = 1 << 27; const _ = !0; }