From 7e3f43c9ab655b30eab3f301940054b661e68a9e Mon Sep 17 00:00:00 2001 From: justcool393 Date: Fri, 30 Sep 2022 14:00:58 -0700 Subject: [PATCH] unperson shadowbanned users (#373) * unperson shadowbanned users if a shadowbanned user copes, does anyone hear them seethe? * unperson shadowbanned users (by id) * don't import that * Add include_blocks. We don't always want to request blocks from the db when we have a user set * block shadowbanned users from hole mod tools * don't allow awarding shadowbanned things * fix conflict * gracefully use get_account when specified and also add include_blocks flag to get_account as well --- files/helpers/get.py | 36 ++++++++++---------- files/routes/asset_submissions.py | 4 +-- files/routes/awards.py | 1 + files/routes/login.py | 2 +- files/routes/search.py | 4 +-- files/routes/static.py | 2 +- files/routes/subs.py | 13 +++++++- files/routes/users.py | 55 +++++++++++++++---------------- 8 files changed, 63 insertions(+), 54 deletions(-) diff --git a/files/helpers/get.py b/files/helpers/get.py index 336c2c23e..6786f9965 100644 --- a/files/helpers/get.py +++ b/files/helpers/get.py @@ -1,7 +1,7 @@ from files.classes import * from flask import g -def get_id(username, v=None, graceful=False): +def get_id(username, v=None, graceful=False, include_shadowbanned=True): username = username.replace('\\', '').replace('_', '\_').replace('%', '').strip() @@ -14,17 +14,14 @@ def get_id(username, v=None, graceful=False): ) ).one_or_none() - if not user: - if not graceful: - abort(404) - else: - return None + if not user or (user.shadowbanned and not (include_shadowbanned or (v and (v.admin_level >= 2 or v.shadowbanned)))): + if not graceful: abort(404) + else: return None return user[0] -def get_user(username, v=None, graceful=False, rendered=False): - +def get_user(username, v=None, graceful=False, rendered=False, include_blocks=False, include_shadowbanned=True): if not username: if not graceful: abort(404) else: return None @@ -42,11 +39,11 @@ def get_user(username, v=None, graceful=False, rendered=False): user = user.one_or_none() - if not user: + if not user or (user.shadowbanned and not (include_shadowbanned or (v and (v.admin_level >= 2 or v.shadowbanned)))): if not graceful: abort(404) else: return None - if rendered and v: + if rendered and v and include_blocks: if v.id == user.id: user.is_blocked = False user.is_blocking = False @@ -88,18 +85,21 @@ def get_users(usernames, graceful=False): return users -def get_account(id, v=None, graceful=False): +def get_account(id, v=None, graceful=False, include_blocks=False, include_shadowbanned=True): - try: id = int(id) - except: abort(404) - - user = g.db.get(User, id) - - if not user: + try: + id = int(id) + except: if not graceful: abort(404) else: return None - if v: + user = g.db.get(User, id) + + if not user or (user.shadowbanned and not (include_shadowbanned or (v and (v.admin_level >= 2 or v.shadowbanned)))): + if not graceful: abort(404) + else: return None + + if v and include_blocks: block = g.db.query(UserBlock).filter( or_( and_( diff --git a/files/routes/asset_submissions.py b/files/routes/asset_submissions.py index 3008c1d05..b4aaf88f0 100644 --- a/files/routes/asset_submissions.py +++ b/files/routes/asset_submissions.py @@ -67,7 +67,7 @@ def submit_marsey(v): if not tags_regex.fullmatch(tags): return error("Invalid tags!") - author = get_user(username, graceful=True) + author = get_user(username, v=v, graceful=True, include_shadowbanned=False) if not author: return error(f"A user with the name '{username}' was not found!") @@ -221,7 +221,7 @@ def submit_hat(v): if not description_regex.fullmatch(description): return error("Invalid description!") - author = get_user(username, graceful=True) + author = get_user(username, v=v, graceful=True, include_shadowbanned=False) if not author: return error(f"A user with the name '{username}' was not found!") diff --git a/files/routes/awards.py b/files/routes/awards.py index 882ac2a1e..1d51b0ee9 100644 --- a/files/routes/awards.py +++ b/files/routes/awards.py @@ -165,6 +165,7 @@ def award_thing(v, thing_type, id): note = request.values.get("note", "").strip() author = thing.author + if author.shadowbanned: return {"error": f"This {thing_type} doesn't exist."}, 404 if SITE == 'rdrama.net' and author.id in (PIZZASHILL_ID, CARP_ID): return {"error": "This user is immune to awards."}, 403 diff --git a/files/routes/login.py b/files/routes/login.py index c015b004b..dfb7a4005 100644 --- a/files/routes/login.py +++ b/files/routes/login.py @@ -273,7 +273,7 @@ def sign_up_post(v): args = {"error": error} if request.values.get("referred_by"): - user = get_account(request.values.get("referred_by")) + user = get_account(request.values.get("referred_by"), include_shadowbanned=False) if user: args["ref"] = user.username return redirect(f"/signup?{urlencode(args)}") diff --git a/files/routes/search.py b/files/routes/search.py index 771b50d35..ae9ac3494 100644 --- a/files/routes/search.py +++ b/files/routes/search.py @@ -71,7 +71,7 @@ def searchposts(v): if 'author' in criteria: posts = posts.filter(Submission.ghost == False) - author = get_user(criteria['author']) + author = get_user(criteria['author'], v=v, include_shadowbanned=False) if not author: return {"error": "User not found"}, 400 if author.is_private and author.id != v.id and v.admin_level < 2 and not v.eye: if request.headers.get("Authorization"): @@ -208,7 +208,7 @@ def searchcomments(v): if 'author' in criteria: comments = comments.filter(Comment.ghost == False) - author = get_user(criteria['author']) + author = get_user(criteria['author'], v=v, include_shadowbanned=False) if not author: return {"error": "User not found"}, 400 if author.is_private and author.id != v.id and v.admin_level < 2 and not v.eye: if request.headers.get("Authorization"): diff --git a/files/routes/static.py b/files/routes/static.py index 65da9f713..7365ec153 100644 --- a/files/routes/static.py +++ b/files/routes/static.py @@ -131,7 +131,7 @@ def log(v): except: page = 1 admin = request.values.get("admin") - if admin: admin_id = get_id(admin) + if admin: admin_id = get_id(admin, v=v, include_shadowbanned=False) else: admin_id = 0 kind = request.values.get("kind") diff --git a/files/routes/subs.py b/files/routes/subs.py index 0f07e61d3..56fd7f7b2 100644 --- a/files/routes/subs.py +++ b/files/routes/subs.py @@ -11,6 +11,7 @@ import tldextract @app.post("/exile/post/") @is_not_permabanned def exile_post(v, pid): + if v.shadowbanned: return {"error": "Internal Server Error"}, 500 try: pid = int(pid) except: abort(400) @@ -46,6 +47,7 @@ def exile_post(v, pid): @app.post("/exile/comment/") @is_not_permabanned def exile_comment(v, cid): + if v.shadowbanned: return {"error": "Internal Server Error"}, 500 try: cid = int(cid) except: abort(400) @@ -83,6 +85,7 @@ def unexile(v, sub, uid): u = get_account(uid) if not v.mods(sub): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/exilees') if u.exiled_from(sub): exile = g.db.query(Exile).filter_by(user_id=u.id, sub=sub).one_or_none() @@ -263,12 +266,13 @@ def add_mod(v, sub): sub = sub.name if not v.mods(sub): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/mods') user = request.values.get('user') if not user: abort(400) - user = get_user(user) + user = get_user(user, v=v, include_shadowbanned=False) if sub in ('furry','vampire','racist','femboy') and not v.client and not user.house.lower().startswith(sub): return {"error": f"@{user.username} needs to be a member of House {sub.capitalize()} to be added as a mod there!"}, 400 @@ -301,6 +305,7 @@ def remove_mod(v, sub): sub = sub.name if not v.mods(sub): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/mods') uid = request.values.get('uid') @@ -385,6 +390,7 @@ def kick(v, pid): if not post.sub: abort(403) if not v.mods(post.sub): abort(403) + if v.shadowbanned: return {"error": "Internal Server Error"}, 500 old = post.sub post.sub = None @@ -439,6 +445,7 @@ def post_sub_sidebar(v, sub): if not sub: abort(404) if not v.mods(sub.name): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/settings') sub.sidebar = request.values.get('sidebar', '').strip()[:10000] sub.sidebar_html = sanitize(sub.sidebar) @@ -466,6 +473,7 @@ def post_sub_css(v, sub): if not sub: abort(404) if not v.mods(sub.name): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/settings') if len(css) > 6000: error = "CSS is too long (max 6000 characters)" @@ -508,6 +516,7 @@ def sub_banner(v, sub): if not sub: abort(404) if not v.mods(sub.name): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/settings') file = request.files["banner"] @@ -542,6 +551,7 @@ def sub_sidebar(v, sub): if not sub: abort(404) if not v.mods(sub.name): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/settings') file = request.files["sidebar"] name = f'/images/{time.time()}'.replace('.','') + '.webp' @@ -575,6 +585,7 @@ def sub_marsey(v, sub): if not sub: abort(404) if not v.mods(sub.name): abort(403) + if v.shadowbanned: return redirect(f'/h/{sub}/settings') file = request.files["marsey"] name = f'/images/{time.time()}'.replace('.','') + '.webp' diff --git a/files/routes/users.py b/files/routes/users.py index 7f57aa145..d7fe29e19 100644 --- a/files/routes/users.py +++ b/files/routes/users.py @@ -61,7 +61,7 @@ gevent.spawn(leaderboard_thread) @app.get("/@/upvoters//posts") @auth_required def upvoters_posts(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -83,7 +83,7 @@ def upvoters_posts(v, username, uid): @app.get("/@/upvoters//comments") @auth_required def upvoters_comments(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -105,7 +105,7 @@ def upvoters_comments(v, username, uid): @app.get("/@/downvoters//posts") @auth_required def downvoters_posts(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -127,7 +127,7 @@ def downvoters_posts(v, username, uid): @app.get("/@/downvoters//comments") @auth_required def downvoters_comments(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -152,7 +152,7 @@ def downvoters_comments(v, username, uid): @app.get("/@/upvoting//posts") @auth_required def upvoting_posts(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -174,7 +174,7 @@ def upvoting_posts(v, username, uid): @app.get("/@/upvoting//comments") @auth_required def upvoting_comments(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -196,7 +196,7 @@ def upvoting_comments(v, username, uid): @app.get("/@/downvoting//posts") @auth_required def downvoting_posts(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -218,7 +218,7 @@ def downvoting_posts(v, username, uid): @app.get("/@/downvoting//comments") @auth_required def downvoting_comments(v, username, uid): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) id = u.id @@ -240,7 +240,7 @@ def downvoting_comments(v, username, uid): @app.get("/@/upvoted/posts") @auth_required def user_upvoted_posts(v, username): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -266,7 +266,7 @@ def user_upvoted_posts(v, username): @app.get("/@/upvoted/comments") @auth_required def user_upvoted_comments(v, username): - u = get_user(username) + u = get_user(username, v=v, include_shadowbanned=False) if u.is_private and (not v or (v.id != u.id and v.admin_level < 2 and not v.eye)): abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -314,7 +314,7 @@ def agendaposters(v): @app.get("/@/upvoters") @auth_required def upvoters(v, username): - id = get_user(username).id + id = get_user(username, v=v, include_shadowbanned=False).id if not (v.id == id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -347,7 +347,7 @@ def upvoters(v, username): @app.get("/@/downvoters") @auth_required def downvoters(v, username): - id = get_user(username).id + id = get_user(username, v=v, include_shadowbanned=False).id if not (v.id == id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -378,7 +378,7 @@ def downvoters(v, username): @app.get("/@/upvoting") @auth_required def upvoting(v, username): - id = get_user(username).id + id = get_user(username, v=v, include_shadowbanned=False).id if not (v.id == id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -409,7 +409,7 @@ def upvoting(v, username): @app.get("/@/downvoting") @auth_required def downvoting(v, username): - id = get_user(username).id + id = get_user(username, v=v, include_shadowbanned=False).id if not (v.id == id or v.admin_level >= PERMS['USER_VOTERS_VISIBLE']): abort(403) @@ -457,7 +457,7 @@ def suicide(v, username): @app.get("/@/coins") @auth_required def get_coins(v, username): - user = get_user(username) + user = get_user(username, v=v, include_shadowbanned=False) if user != None: return {"coins": user.coins}, 200 else: return {"error": "invalid_user"}, 404 @@ -466,7 +466,7 @@ def get_coins(v, username): @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @is_not_permabanned def transfer_coins(v, username): - receiver = get_user(username) + receiver = get_user(username, v=v, include_shadowbanned=False) if receiver is None: return {"error": "This user doesn't exist."}, 404 @@ -511,7 +511,7 @@ def transfer_coins(v, username): @limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @is_not_permabanned def transfer_bux(v, username): - receiver = get_user(username) + receiver = get_user(username, v=v, include_shadowbanned=False) if not receiver: return {"error": "This user doesn't exist."}, 404 @@ -741,7 +741,7 @@ def unsubscribe(v, post_id): @limiter.limit("1/second;10/minute;20/hour;50/day", key_func=lambda:f'{SITE}-{session.get("lo_user")}') @is_not_permabanned def message2(v, username): - user = get_user(username, v=v) + user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False) if hasattr(user, 'is_blocking') and user.is_blocking: return {"error": "You're blocking this user."}, 403 @@ -955,7 +955,7 @@ def redditor_moment_redirect(username, v): @app.get("/@/followers") @auth_required def followers(username, v): - u = get_user(username, v=v) + u = get_user(username, v=v, include_shadowbanned=False) if u.id == CARP_ID and SITE == 'watchpeopledie.co': abort(403) if not (v.id == u.id or v.admin_level >= PERMS['USER_FOLLOWS_VISIBLE']): @@ -969,7 +969,7 @@ def followers(username, v): @app.get("/@/blockers") @auth_required def blockers(username, v): - u = get_user(username, v=v) + u = get_user(username, v=v, include_shadowbanned=False) users = g.db.query(UserBlock, User).join(UserBlock, UserBlock.target_id == u.id) \ .filter(UserBlock.user_id == User.id) \ @@ -979,7 +979,7 @@ def blockers(username, v): @app.get("/@/following") @auth_required def following(username, v): - u = get_user(username, v=v) + u = get_user(username, v=v, include_shadowbanned=False) if not (v.id == u.id or v.admin_level >= PERMS['USER_FOLLOWS_VISIBLE']): abort(403) @@ -1003,7 +1003,7 @@ def visitors(v): @auth_desired_with_logingate def u_username(username, v=None): - u = get_user(username, v=v, rendered=True) + u = get_user(username, v=v, include_blocks=True, include_shadowbanned=False, rendered=True) if v and username == v.username: is_following = False @@ -1020,9 +1020,6 @@ def u_username(username, v=None): return render_template("userpage_reserved.html", u=u, v=v) - if u.shadowbanned and not (v and (v.admin_level >= 2 or v.shadowbanned)): - abort(404) - if v and v.id not in (u.id, DAD_ID) and u.viewers_recorded: g.db.flush() view = g.db.query(ViewerRelationship).filter_by(viewer_id=v.id, user_id=u.id).one_or_none() @@ -1104,7 +1101,7 @@ def u_username(username, v=None): @auth_desired_with_logingate def u_username_comments(username, v=None): - user = get_user(username, v=v, rendered=True) + user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False, rendered=True) if v and username == v.username: is_following = False @@ -1179,7 +1176,7 @@ def u_username_comments(username, v=None): @auth_required def u_username_info(username, v=None): - user=get_user(username, v=v) + user=get_user(username, v=v, include_blocks=True, include_shadowbanned=False) if hasattr(user, 'is_blocking') and user.is_blocking: return {"error": "You're blocking this user."}, 401 @@ -1192,7 +1189,7 @@ def u_username_info(username, v=None): @auth_required def u_user_id_info(id, v=None): - user=get_account(id, v=v) + user=get_account(id, v=v, include_blocks=True, include_shadowbanned=False) if hasattr(user, 'is_blocking') and user.is_blocking: return {"error": "You're blocking this user."}, 401 @@ -1207,7 +1204,7 @@ def u_user_id_info(id, v=None): @auth_required def follow_user(username, v): - target = get_user(username) + target = get_user(username, v=v, include_shadowbanned=False) if target.id==v.id: return {"error": "You can't follow yourself!"}, 400