add: show if user account is banned on profile

fix: check post owner privacy settings on community pages
This commit is contained in:
trisua 2025-05-16 00:25:44 -04:00
parent 03b252937b
commit 4c26879d00
9 changed files with 112 additions and 14 deletions

View file

@ -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);

View file

@ -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"

View file

@ -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

View file

@ -42,6 +42,13 @@ fn check_supporter(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Va
.into())
}
fn check_staff_badge(value: &Value, _: &HashMap<String, Value>) -> tera::Result<Value> {
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();

View file

@ -236,6 +236,8 @@
MANAGE_MESSAGES: 1 << 23,
MANAGE_UPLOADS: 1 << 24,
MANAGE_EMOJIS: 1 << 25,
MANAGE_STACKS: 1 << 26,
STAFF_BADGE: 1 << 27,
},
],
);

View file

@ -0,0 +1,27 @@
{% extends "root.html" %} {% block head %}
<title>{{ profile.username }} (banned) - {{ config.name }}</title>
{% endblock %} {% block body %} {{ macros::nav() }}
<main class="flex flex-col gap-2">
<div class="card-nest">
<div class="card small flex items-center justify-between gap-2">
<div class="flex items-center gap-2">
{{ components::avatar(username=profile.username, size="24px") }}
<span>{{ profile.username }}</span>
</div>
<b class="notification chip">{{ text "auth:label.banned" }}</b>
</div>
<div class="card flex flex-col gap-2">
<span>{{ text "auth:label.banned_message" }}</span>
<div class="card w-full secondary flex gap-2">
<a href="/" class="button red quaternary">
{{ icon "x" }}
<span>{{ text "general:action.back" }}</span>
</a>
</div>
</div>
</div>
</main>
{% endblock %}

View file

@ -47,7 +47,7 @@
}}
<div class="flex flex-col">
<!-- prettier-ignore -->
<h3 id="username" class="username flex items-center gap-2">
<h3 id="username" class="username flex items-center gap-2 flex-wrap w-full">
<span class="name shorter">{{ components::username(user=profile) }}</span>
{% if profile.is_verified %}
@ -56,11 +56,17 @@
</span>
{% endif %}
{% if is_supporter %}
{% if profile.permissions|has_supporter %}
<span title="Supporter" style="color: var(--color-primary);" class="flex items-center">
{{ icon "star" }}
</span>
{% endif %}
{% if profile.permissions|has_staff_badge %}
<span title="Staff" style="color: var(--color-primary);" class="flex items-center">
{{ icon "shield-user" }}
</span>
{% endif %}
</h3>
<span class="fade">{{ profile.username }}</span>

View file

@ -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<usize, User> = 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(),

View file

@ -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;
}