alts: propagate shadowbans by walking the entire graph #68

Closed
justcool393 wants to merge 9 commits from <deleted>:fix-shadowbans-and-stuff into master
4 changed files with 39 additions and 32 deletions

View File

@ -1,11 +1,11 @@
import random
from operator import *
from typing import Any, Union
from typing import Callable, Union
import pyotp
from sqlalchemy import Column, ForeignKey
from sqlalchemy.orm import aliased, deferred
from sqlalchemy.sql import func
from sqlalchemy.orm import aliased, deferred, Query
from sqlalchemy.sql import case, func, literal
from sqlalchemy.sql.expression import not_, and_, or_
from sqlalchemy.sql.sqltypes import *
@ -478,9 +478,41 @@ class User(Base):
@lazy
def alts_patron(self):
for u in self.alts_unique:
if u.patron: return True
if not u._deleted and u.patron: return True
return False
@lazy
def get_alt_graph(self, db:scoped_session, alt_filter:Optional[Callable[[Query], Query]]=None, **kwargs) -> Query:
'''
Gets the full graph of alts (optionally filtering `Alt` objects by criteria using a callable,
such as by a date to only get alts from a certain date) as a query of users that can be filtered
further. This function filters alts marked as deleted by default, pass `include_deleted=True` to
disable this behavior and include delinked alts.
'''
if not alt_filter:
alt_filter = lambda q:q
if not kwargs.get('include_deleted', False):
deleted_filter = lambda q:q.filter(Alt.deleted == False)
else:
deleted_filter = lambda q:q
combined_filter = lambda q:deleted_filter(alt_filter(q))
alt_graph_cte = db.query(literal(self.id).label('user_id')).select_from(Alt).cte('alt_graph', recursive=True)
alt_graph_cte_inner = combined_filter(db.query(
case(
(Alt.user1 == alt_graph_cte.c.user_id, Alt.user2),
(Alt.user2 == alt_graph_cte.c.user_id, Alt.user1),
)
).select_from(Alt, alt_graph_cte).filter(
or_(alt_graph_cte.c.user_id == Alt.user1, alt_graph_cte.c.user_id == Alt.user2)
))
alt_graph_cte = alt_graph_cte.union(alt_graph_cte_inner)
return db.query(User).filter(User.id == alt_graph_cte.c.user_id)
@property
@lazy
def follow_count(self):

View File

@ -465,7 +465,7 @@ def execute_antispam_comment_check(body:str, v:User):
g.db.commit()
abort(403, "Too much spam!")
def execute_under_siege(v:User, target:Optional[Union[Submission, Comment]], body, type:str):
def execute_under_siege(v:User, target:Optional[Union[Submission, Comment]], body, type:str) -> bool:
if not get_setting("under_siege"): return True
if v.age < UNDER_SIEGE_AGE_THRESHOLD and not v.admin_level >= PERMS['SITE_BYPASS_UNDER_SIEGE_MODE']:
v.shadowbanned = AUTOJANNY_ID

View File

@ -159,13 +159,11 @@ def merge_all(v:User, id):
@app.get('/admin/edit_rules')
@admin_level_required(PERMS['EDIT_RULES'])
def edit_rules_get(v):
try:
with open(f'files/templates/rules_{SITE_NAME}.html', 'r', encoding="utf-8") as f:
rules = f.read()
except:
rules = None
return render_template('admin/edit_rules.html', v=v, rules=rules)
@ -184,11 +182,8 @@ def edit_rules_post(v):
user_id=v.id,
)
g.db.add(ma)
return render_template('admin/edit_rules.html', v=v, rules=rules, msg='Rules edited successfully!')
@app.post("/@<username>/make_admin")
@admin_level_required(PERMS['ADMIN_ADD'])
def make_admin(v:User, username):
@ -214,7 +209,7 @@ def make_admin(v:User, username):
def remove_admin(v:User, username):
user = get_user(username)
if user.id == v.id:
abort(403, "You can't remove yourself JC")
abort(403, "You can't remove yourself JC -- jc was here in this error msg <3")
user.admin_level = 0
g.db.add(user)
@ -896,22 +891,6 @@ def shadowban(user_id, v):
g.db.add(user)
check_for_alts(user, False)
for u in user.alts_unique:
u.shadowbanned = v.id
g.db.add(u)
for u in u.alts_unique:
u.shadowbanned = v.id
g.db.add(u)
for u in u.alts_unique:
u.shadowbanned = v.id
g.db.add(u)
for u in u.alts_unique:
u.shadowbanned = v.id
g.db.add(u)
for u in u.alts_unique:
u.shadowbanned = v.id
g.db.add(u)
ma = ModAction(
kind="shadowban",
user_id=v.id,

View File

@ -27,9 +27,6 @@ def validate_formkey(u:User, formkey:Optional[str]) -> bool:
def check_for_alts(current:User, include_current_session=True):
current_id = current.id
if current_id in (1691,6790,7069,36152) and include_current_session:
session["history"] = []
return
ids = [x[0] for x in g.db.query(User.id).all()]
past_accs = set(session.get("history", [])) if include_current_session else set()
@ -68,8 +65,7 @@ def check_for_alts(current:User, include_current_session=True):
if include_current_session:
session["history"] = list(past_accs)
g.db.flush()
for u in current.alts_unique:
if u._alt_deleted: continue
for u in current.get_alt_graph(g.db).all():
if u.shadowbanned:
current.shadowbanned = u.shadowbanned
if not current.is_banned: current.ban_reason = u.ban_reason