From 83963470e8004b8291694872473710e97ba45fe1 Mon Sep 17 00:00:00 2001 From: justcool393 Date: Thu, 17 Nov 2022 13:02:08 -0800 Subject: [PATCH] user can_view functions (#460) * user: move can_see_to user class * stub out can_see in comments and posts * make can_see a classmethod so it's usable for loggedoutfriends * test * kill me now * threelargeclassesmating * dfdfdfdfdfdfd * sdsdsdsd * classmethod should be above i think * Revert "classmethod should be above i think" This reverts commit df1772eb9e7e71bf7b89123f6277b648de2b1af3. * Revert "Revert "classmethod should be above i think"" This reverts commit 32883406c2e2916fc6c436611376a1817c16cb84. * test rewritnig thing * go home python * what the fuck python * fix AttributeError * sdsdsdsdsdsd * lazy and user and stuff * test * Revert "test" This reverts commit 45af5bb3d45f3ec17126ab117d494ec978062a38. * merge * newline * test * test 2 * Revert "test" This reverts commit 196dae677e2ee8cd29261c93dcb747087cb399b6. * revert test * fix merge error * fix import error ciruclation i think * sdsd * add type annotations back * deleted_utc * isinstance * user_can_see in jinja and remove unnecessary things * a bunch of stuff remove can_see from comment and post expand can_see to messages * antiannoyingamountsofwhitespace * fix for chudrama * improve prev --- files/classes/comment.py | 11 ------ files/classes/submission.py | 13 +------ files/classes/user.py | 50 +++++++++++++++++++++++++ files/routes/comments.py | 11 ++---- files/routes/front.py | 6 +-- files/routes/jinja2.py | 5 ++- files/routes/posts.py | 5 +-- files/routes/votes.py | 5 +-- files/templates/comments.html | 2 +- files/templates/submission_listing.html | 2 +- 10 files changed, 64 insertions(+), 46 deletions(-) diff --git a/files/classes/comment.py b/files/classes/comment.py index 96204a190..5972622d3 100644 --- a/files/classes/comment.py +++ b/files/classes/comment.py @@ -82,17 +82,6 @@ class Comment(Base): def __repr__(self): return f"" - @lazy - def can_see(self, v): - if SITE != 'rdrama.net': return True - if not self.parent_submission: return True - if self.post.sub != 'chudrama': return True - if v: - if v.can_see_chudrama: return True - if v.id == self.author_id: return True - if v.id == self.post.author_id: return True - return False - @lazy def top_comment(self, db:scoped_session): return db.get(Comment, self.top_comment_id) diff --git a/files/classes/submission.py b/files/classes/submission.py index 2680b91e8..6f895f7d5 100644 --- a/files/classes/submission.py +++ b/files/classes/submission.py @@ -76,22 +76,12 @@ class Submission(Base): def __repr__(self): return f"" - @lazy - def can_see(self, v): - if SITE != 'rdrama.net': return True - if self.sub != 'chudrama': return True - if v: - if v.can_see_chudrama: return True - if v.id == self.author_id: return True - return False - @property @lazy def controversial(self): if self.downvotes > 5 and 0.25 < self.upvotes / self.downvotes < 4: return True return False - @property @lazy def created_datetime(self): @@ -115,8 +105,7 @@ class Submission(Base): @property @lazy def fullname(self): - return f"p_{self.id}" - + return f"p_{self.id}" @property @lazy diff --git a/files/classes/user.py b/files/classes/user.py index 433e368c1..aff17d264 100644 --- a/files/classes/user.py +++ b/files/classes/user.py @@ -1,5 +1,6 @@ import random from operator import * +from typing import Union import pyotp from sqlalchemy import Column, ForeignKey @@ -943,7 +944,56 @@ class User(Base): if self.patron == 6: return 'Contributed at least $200' return '' + + @classmethod + def can_see_content(cls, user:Optional["User"], other:Union["Submission", "Comment", Sub]) -> bool: + ''' + Whether a user can see this item (be it a submission or comment)'s content. + If False, they won't be able to view its content. + ''' + from files.classes.submission import Submission + from files.classes.comment import Comment + if not cls.can_see(user, other): return False + if user and user.admin_level >= PERMS["POST_COMMENT_MODERATION"]: return True + if isinstance(other, (Submission, Comment)): + if user and user.id == other.author_id: return True + if other.is_banned: return False + if other.deleted_utc: return False + if other.author.shadowbanned and not (user and user.can_see_shadowbanned): return False + if isinstance(other, Submission): + if other.club and not (user and user.paid_dues): return False + if other.sub == 'chudrama' and not (user and user.can_see_chudrama): return False + else: + if other.parent_submission and not cls.can_see_content(user, other.post): return False + return True + @classmethod + def can_see(cls, user:Optional["User"], other:Union["Submission", "Comment", "Sub", "User"]) -> bool: + ''' + Whether a user can strictly see this item. can_see_content is used where + content of a thing can be hidden from view + ''' + from files.classes.submission import Submission + from files.classes.comment import Comment + if isinstance(other, (Submission, Comment)): + if not cls.can_see(user, other.author): return False + if user and user.id == other.author_id: return True + if isinstance(other, Submission): + if other.sub and not cls.can_see(user, other.subr): return False + else: + if not other.parent_submission: + if not user: return False + if other.sentto == 2: return user.admin_level >= PERMS['VIEW_MODMAIL'] # type: ignore + if other.sentto != user.id: return user.admin_level >= PERMS['POST_COMMENT_MODERATION'] # type: ignore + if other.parent_submission and other.post.sub and not cls.can_see(user, other.post.subr): return False + # if other.parent_submission and not cls.can_see(user, other.post): return False + elif isinstance(other, Sub): + return other.name != 'chudrama' or (user and user.can_see_chudrama) + elif isinstance(other, User): + return (user and user.id == other.id) or (user and user.can_see_shadowbanned) or not other.shadowbanned + return True + + @property @lazy def can_see_chudrama(self): diff --git a/files/routes/comments.py b/files/routes/comments.py index 6d54822dc..16426e10a 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -32,19 +32,14 @@ WORDLE_COLOR_MAPPINGS = {-1: "🟥", 0: "🟨", 1: "🟩"} @auth_desired_with_logingate def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None): comment = get_comment(cid, v=v) - if not comment.can_see(v): abort(403) - - if comment.author.shadowbanned and not (v and v.can_see_shadowbanned): - abort(404) + if not User.can_see(v, comment): abort(404) + if comment.post and comment.post.club and not User.can_see_content(v, comment): abort(403) if v and request.values.get("read"): notif = g.db.query(Notification).filter_by(comment_id=cid, user_id=v.id, read=False).one_or_none() if notif: notif.read = True g.db.add(notif) - - if comment.post and comment.post.club and not (v and (v.paid_dues or v.id in [comment.author_id, comment.post.author_id])): abort(403) - if not comment.parent_submission and not (v and (comment.author.id == v.id or comment.sentto == v.id)) and not (v and v.admin_level >= PERMS['POST_COMMENT_MODERATION']) : abort(403) if not pid: if comment.parent_submission: pid = comment.parent_submission @@ -118,7 +113,7 @@ def comment(v): if parent_post.club and not (v and (v.paid_dues or v.id == parent_post.author_id)): abort(403) - if not parent.can_see(v): abort(404) + if not User.can_see(v, parent): abort(404) if parent.deleted_utc != 0: abort(404) if level > COMMENT_MAX_DEPTH: abort(400, f"Max comment level is {COMMENT_MAX_DEPTH}") diff --git a/files/routes/front.py b/files/routes/front.py index 14cac5359..2ed383775 100644 --- a/files/routes/front.py +++ b/files/routes/front.py @@ -42,9 +42,8 @@ def front_all(v, sub=None, subdomain=None): return redirect('/') #### WPD TEMP #### end special front logic if sub: - sub = sub.strip().lower() - if sub == 'chudrama' and not (v and v.can_see_chudrama): abort(403) sub = get_sub_by_name(sub, graceful=True) + if sub and not User.can_see(v, sub): abort(403) if (request.path.startswith('/h/') or request.path.startswith('/s/')) and not sub: abort(404) @@ -172,12 +171,9 @@ def frontlist(v=None, sort="hot", page=1, t="all", ids_only=True, filter_words=' if SITE_NAME == 'rDrama': pins = pins.order_by(Submission.author_id != LAWLZ_ID) pins = pins.order_by(Submission.created_utc.desc()).all() - posts = pins + posts if ids_only: posts = [x.id for x in posts] - - return posts, next_exists diff --git a/files/routes/jinja2.py b/files/routes/jinja2.py index f23d8f4dc..801bb7594 100644 --- a/files/routes/jinja2.py +++ b/files/routes/jinja2.py @@ -4,6 +4,7 @@ from os import environ, listdir, path from jinja2 import pass_context +from files.classes.user import User from files.helpers.assetcache import assetcache_path from files.helpers.const import * from files.helpers.settings import get_settings @@ -56,7 +57,7 @@ def inject_constants(): "KOFI_TOKEN":KOFI_TOKEN, "KOFI_LINK":KOFI_LINK, "approved_embed_hosts":approved_embed_hosts, "site_settings":get_settings(), "EMAIL":EMAIL, "calc_users":calc_users, - "max": max, "min": min, + "max": max, "min": min, "user_can_see":User.can_see, "TELEGRAM_LINK":TELEGRAM_LINK, "EMAIL_REGEX_PATTERN":EMAIL_REGEX_PATTERN, "CONTENT_SECURITY_POLICY_DEFAULT":CONTENT_SECURITY_POLICY_DEFAULT, "CONTENT_SECURITY_POLICY_HOME":CONTENT_SECURITY_POLICY_HOME, @@ -65,5 +66,5 @@ def inject_constants(): "HOUSE_JOIN_COST":HOUSE_JOIN_COST, "HOUSE_SWITCH_COST":HOUSE_SWITCH_COST, "IMAGE_FORMATS":IMAGE_FORMATS, "PAGE_SIZES":PAGE_SIZES, "THEMES":THEMES, "COMMENT_SORTS":COMMENT_SORTS, "SORTS":SORTS, "TIME_FILTERS":TIME_FILTERS, "HOUSES":HOUSES, "TIERS_ID_TO_NAME":TIERS_ID_TO_NAME, - "DEFAULT_CONFIG_VALUE":DEFAULT_CONFIG_VALUE + "DEFAULT_CONFIG_VALUE":DEFAULT_CONFIG_VALUE, } diff --git a/files/routes/posts.py b/files/routes/posts.py index 70befd2a2..e8e6c7581 100644 --- a/files/routes/posts.py +++ b/files/routes/posts.py @@ -137,7 +137,8 @@ def submit_get(v, sub=None): @auth_desired_with_logingate def post_id(pid, anything=None, v=None, sub=None): post = get_post(pid, v=v) - if not post.can_see(v): abort(403) + if not User.can_see(v, post): abort(403) + if not User.can_see_content(v, post) and post.club: abort(403) if post.over_18 and not (v and v.over_18) and session.get('over_18', 0) < int(time.time()): if g.is_api_or_xhr: return {"error":"Must be 18+ to view"}, 451 @@ -148,8 +149,6 @@ def post_id(pid, anything=None, v=None, sub=None): else: defaultsortingcomments = "hot" sort = request.values.get("sort", defaultsortingcomments) - if post.club and not (v and (v.paid_dues or v.id == post.author_id)): abort(403) - if v: execute_shadowban_viewers_and_voters(v, post) # shadowban check is done in sort_objects diff --git a/files/routes/votes.py b/files/routes/votes.py index 32c34630a..e67e15cfd 100644 --- a/files/routes/votes.py +++ b/files/routes/votes.py @@ -50,12 +50,11 @@ def vote_post_comment(target_id, new, v, cls, vote_cls): target = get_post(target_id) elif cls == Comment: target = get_comment(target_id) - if not target.post: abort(404) + if not target.parent_submission: abort(404) else: abort(404) - if target.author.shadowbanned and not v.can_see_shadowbanned: - abort(404) + if not User.can_see(v, target): abort(404) coin_delta = 1 if v.id == target.author.id: diff --git a/files/templates/comments.html b/files/templates/comments.html index 46f9d06c0..8958ac7e8 100644 --- a/files/templates/comments.html +++ b/files/templates/comments.html @@ -739,7 +739,7 @@ {% endif %} {% endmacro %} -{% for comment in comments if comment.can_see(v) %} +{% for comment in comments if user_can_see(v, comment) %} {{single_comment(comment)}} {% endfor %} diff --git a/files/templates/submission_listing.html b/files/templates/submission_listing.html index 46a097289..bffd74cc5 100644 --- a/files/templates/submission_listing.html +++ b/files/templates/submission_listing.html @@ -20,7 +20,7 @@ {% include "popover.html" %} -{% for p in listing if p.can_see(v) %} +{% for p in listing if user_can_see(v, p) %} {% set ups=p.upvotes %} {% set downs=p.downvotes %}