Example #1
0
def settings_post(v):

    updated = False

    if request.form.get("new_password"):
        if request.form.get("new_password") != request.form.get(
                "cnf_password"):
            return render_template("settings.html",
                                   v=v,
                                   error="Passwords do not match.")

        if not v.verifyPass(request.form.get("old_password")):
            return render_template("settings.html",
                                   v=v,
                                   error="Incorrect password")

        v.passhash = v.hash_password(request.form.get("new_password"))
        updated = True

    if request.form.get("over18") != v.over_18:
        updated = True
        v.over_18 = bool(request.form.get("over18", None))

    if updated:
        db.add(v)
        db.commit()

        return render_template("settings.html",
                               v=v,
                               msg="Your settings have been saved.")

    else:
        return render_template("settings.html",
                               v=v,
                               error="You didn't change anything.")
Example #2
0
def badge_grant_post(v):

    user = get_user(request.form.get("username"), graceful=True)
    if not user:
        return redirect("/badge_grant?error=no_user")

    badge_id = int(request.form.get("badge_id"))

    if user.has_badge(badge_id):
        return redirect("/badge_grant?error=already_owned")

    badge = db.query(BadgeDef).filter_by(id=badge_id).first()
    if badge.kind != 3:
        abort(403)

    new_badge = Badge(badge_id=badge_id,
                      user_id=user.id,
                      created_utc=int(time.time()))

    desc = request.form.get("description")
    if desc:
        new_badge.description = desc

    url = request.form.get("url")
    if url:
        new_badge.url = url

    db.add(new_badge)
    db.commit()

    badge_types = db.query(BadgeDef).filter_by(kind=3).order_by(
        BadgeDef.rank).all()

    return redirect(user.permalink)
Example #3
0
    def verify_username(self, username):
        
        #no reassignments allowed
        if self.username_verified:
            return render_template("settings.html", v=self, error="Your account has already validated its username.")
        
        #For use when verifying username with reddit
        #Set username. Randomize username of any other existing account with same
        try:
            existing = db.query(User).filter_by(username=username).all()[0]

            #No reassignments allowed
            if existing.username_verified:
                return render_template("settings.html", v=self, error="Another account has already validated that username.")
                
            # Rename new account to user_id
            # guaranteed to be unique
            existing.username=f"user_{existing.id}"
            
            db.add(existing)
            db.commit()
                                     
        except IndexError:
            pass
                                      
        self.username=username
        self.username_verified=True
        
        db.add(self)
        db.commit()

        return render_template("settings.html", v=self, msg="Your account name has been updated and validated.")
Example #4
0
def activate():

    token = request.args.get("token", "")
    email = request.args.get("email", "")
    id = request.args.get("id", "")
    time = request.args.get("time", "")

    user = db.query(User).filter(User.id == id).first()

    if not user:
        flash("User Does Not Exist")
        return redirect(url_for("index"))

    if user.is_activated == True:
        flash("Account is already activated")
        return redirect(url_for("login"))

    check_hash = validate_hash(f"{email}+{id}+{time}", token)

    if not check_hash:
        flash("Invalid Token")
        return redirect(url_for("index"))

    if user.is_activated == False:
        user.is_activated = True
        db.add(user)
        db.commit()
        flash("Account has been activated")
        return redirect(url_for("login"))
Example #5
0
def edit_post(pid, v):

    p = get_post(pid)

    if not p.author_id == v.id:
        abort(403)

    if p.is_banned:
        abort(403)

    if p.board.has_ban(v):
        abort(403)

    body = request.form.get("body", "")
    with CustomRenderer() as renderer:
        body_md = renderer.render(mistletoe.Document(body))
    body_html = sanitize(body_md, linkgen=True)

    p.body = body
    p.body_html = body_html
    p.edited_utc = int(time.time())

    db.add(p)
    db.commit()

    return redirect(p.permalink)
Example #6
0
    def del_profile(self):

        aws.delete_file(
            name=f"users/{self.username}/profile-{self.profile_nonce}.png")
        self.has_profile = False
        db.add(self)
        db.commit()
Example #7
0
def api_vote_post(post_id, x, v):

    if x not in ["-1", "0", "1"]:
        abort(400)

    x = int(x)

    post = get_post(post_id)

    if post.is_banned or post.is_deleted or post.is_archived:
        abort(403)

    #check for existing vote
    existing = db.query(Vote).filter_by(user_id=v.id,
                                        submission_id=post.id).first()
    if existing:
        existing.change_to(x)
        #print(f"Re-vote Event: @{v.username} vote {x} on post {post_id}")
        return "", 204

    vote = Vote(user_id=v.id, vote_type=x, submission_id=base36decode(post_id))

    db.add(vote)
    db.commit()

    #print(f"Vote Event: @{v.username} vote {x} on post {post_id}")

    return "", 204
Example #8
0
def mod_toggle_post_pin(bid, pid, x, board, v):

    post = get_post(pid)

    if post.board_id != board.id:
        abort(422)

    try:
        x = bool(int(x))
    except:
        abort(422)

    if x and not board.can_pin_another:
        return jsonify({
            "error":
            f"+{board.name} already has the maximum number of pinned posts."
        }), 409

    post.is_pinned = x

    cache.delete_memoized(Board.idlist, post.board)

    db.add(post)
    db.commit()

    return "", 204
Example #9
0
def user_kick_pid(pid, v):

    #allows a user to yank their content back to +general if it was there previously

    post = get_post(pid)

    current_board = post.board

    if not post.author_id == v.id:
        abort(403)

    if post.board_id == post.original_board_id:
        abort(403)

    if post.board_id == 1:
        abort(400)

    #block further yanks to the same board
    new_rel = PostRelationship(post_id=post.id, board_id=post.board.id)
    db.add(new_rel)

    post.board_id = 1
    post.guild_name = "general"
    post.is_pinned = False

    db.add(post)
    db.commit()

    #clear board's listing caches
    cache.delete_memoized(Board.idlist, current_board)

    return "", 204
Example #10
0
def mod_approve_bid_user(bid, board, v):

    user=get_user(request.form.get("username"), graceful=True)

    if not user:
        return jsonify({"error":"That user doesn't exist."}), 404

    if board.has_ban(user):
        return jsonify({"error":f"@{user.username} is exiled from +{board.name} and can't currently be approved."}), 409
    if board.has_contributor(user):
        return jsonify({"error":f"@{user.username} is already an approved user."})        


    #check for an existing deactivated approval
    existing_contrib=db.query(ContributorRelationship).filter_by(user_id=user.id, board_id=board.id, is_active=False).first()
    if existing_contrib:
        existing_contrib.is_active=True
        existing_contrib.created_utc=int(time.time())
        existing_contrib.approving_mod_id=v.id
        db.add(existing_contrib)
    else:
        new_contrib=ContributorRelationship(user_id=user.id,
                                            board_id=board.id,
                                            is_active=True,
                                            approving_mod_id=v.id)
        db.add(new_contrib)

        if user.id != v.id:
            text=f"You have added as an approved contributor to +{board.name}."
            send_notification(user, text)
            
    db.commit()

    return "", 204
Example #11
0
    def ban(self, admin, include_alts=True, days=0):

        if days > 0:
            ban_time = int(time.time()) + (days * 86400)
            self.unban_utc = ban_time

        else:
            #Takes care of all functions needed for account termination
            self.unban_utc = 0
            self.del_banner()
            self.del_profile()

        self.is_banned = admin.id

        db.add(self)
        db.commit()

        if include_alts:
            for alt in self.alts:

                # suspend alts
                if days > 0:
                    alt.ban(admin=admin, include_alts=False, days=days)

                # ban alts
                alt.ban(admin=admin, include_alts=False)
Example #12
0
def edit_comment(v):

    comment_id = request.form.get("id")
    body = request.form.get("comment", "")
    with UserRenderer() as renderer:
        body_md=renderer.render(mistletoe.Document(body))
    body_html = sanitize(body_md, linkgen=True)

    c = db.query(Comment).filter_by(id=base36decode(comment_id)).first()

    if not c:
        abort(404)

    if not c.author_id == v.id:
        abort(403)

    if c.is_banned or c.is_deleted:
        abort(403)

    c.body=body
    c.body_html=body_html
    c.edited_timestamp = time.time()

    db.add(c)
    db.commit()
Example #13
0
def delete_post_pid(pid, v):

    post = get_post(pid)
    if not post.author_id == v.id:
        abort(403)

    post.is_deleted = True

    db.add(post)

    #clear cache
    cache.delete_memoized(User.userpagelisting, v, sort="new")
    cache.delete_memoized(Board.idlist, post.board)

    if post.age >= 3600 * 6:
        cache.delete_memoized(Board.idlist, post.board, sort="new")
        cache.delete_memoized(frontlist, sort="new")

    #delete i.ruqqus.com
    if post.domain == "i.ruqqus.com":

        segments = post.url.split("/")
        pid = segments[4]
        rand = segments[5]
        if pid == post.base36id:
            key = f"post/{pid}/{rand}"
            delete_file(key)
            post.is_image = False
            db.add(post)

    db.commit()

    return "", 204
Example #14
0
def edit_comment(cid, v):

    c = db.query(Comment).filter_by(id=base36decode(cid)).first()

    if not c:
        abort(404)

    if not c.author_id == v.id:
        abort(403)

    if c.is_banned or c.is_deleted:
        abort(403)

    body = request.form.get("body", "")
    with UserRenderer() as renderer:
        body_md = renderer.render(mistletoe.Document(body))
    body_html = sanitize(body_md, linkgen=True)

    c.body = body
    c.body_html = body_html
    c.edited_timestamp = int(time.time())

    db.add(c)
    db.commit()

    path = request.form.get("current_page", "/")

    return redirect(f"{path}#comment-{c.base36id}")
Example #15
0
def subscribe_board(boardname, v):

    board = get_guild(boardname)

    #check for existing subscription, canceled or otherwise
    sub = db.query(Subscription).filter_by(user_id=v.id,
                                           board_id=board.id).first()
    if sub:
        if sub.is_active:
            abort(409)
        else:
            #reactivate canceled sub
            sub.is_active = True
            db.add(sub)
            db.commit()
            return "", 204

    new_sub = Subscription(user_id=v.id, board_id=board.id)

    db.add(new_sub)
    db.commit()

    #clear your cached guild listings
    cache.delete_memoized(User.idlist, v, kind="board")

    return "", 204
Example #16
0
    def del_profile(self):

        aws.delete_file(
            name=f"board/{self.name.lower()}/profile-{self.profile_nonce}.png")
        self.has_profile = False
        db.add(self)
        db.commit()
Example #17
0
    def del_banner(self):

        aws.delete_file(
            name=f"board/{self.name.lower()}/banner-{self.banner_nonce}.png")
        self.has_banner = False
        db.add(self)
        db.commit()
Example #18
0
def ban_user(user_id, v):

    user=db.query(User).filter_by(id=user_id).first()

    # check for number of days for suspension
    days = int(request.form.get("days")) if request.form.get('days') else 0 
    reason = request.form.get("reason", "")

    if not user:
        abort(400)

    if days > 0:
        if reason:
            text = f"Your Ruqqus account has been suspended for {days} days. \n reason:\n\n{reason}"
        else:
            text = f"Your Ruqqus account has been suspended for {days} days due to a Terms of Service violation."
        user.ban(admin=v, days=days)

    else:
        if reason:
            text = f"Your Ruqqus account has been permanently suspended for the following reason:\n\n{reason}"
        else:
            text = "Your Ruqqus account has been permanently suspended due to a Terms of Service violation."

        user.ban(admin=v)

    send_notification(user, text)
    
    db.commit()
    
    return (redirect(user.url), user)
Example #19
0
    def notifications_page(self, page=1, include_read=False):

        page = int(page)

        notifications = self.notifications.filter_by(is_banned=False,
                                                     is_deleted=False)

        if not include_read:
            notifications = notifications.filter_by(read=False)

        notifications = notifications.order_by(
            text("notifications.created_utc desc")).offset(
                25 * (page - 1)).limit(25)

        comments = [n.comment for n in notifications]

        for n in notifications:
            if not n.read:
                n.read = True
                db.add(n)
                db.commit()

        return render_template("notifications.html",
                               v=self,
                               notifications=comments)
Example #20
0
def edit_post(pid, v):
    p = db.query(Submission).filter_by(id=base36decode(pid)).first()

    if not p:
        abort(404)

    if not p.author_id == v.id:
        abort(403)

    if p.is_banned:
        abort(403)

    body = request.form.get("body", "")
    with UserRenderer() as renderer:
        body_md = renderer.render(mistletoe.Document(body))
    body_html = sanitize(body_md, linkgen=True)

    p.body = body
    p.body_html = body_html
    p.edited_utc = int(time.time())

    db.add(p)
    db.commit()

    return redirect(p.permalink)
Example #21
0
def mod_invite_username(bid, board, v):

    username = request.form.get("username", '').lstrip('@')
    user = get_user(username)

    if not board.can_invite_mod(user):
        return jsonify({
            "error":
            f"@{user.username} is already a mod or has already been invited."
        }), 409

    if not user.can_join_gms:
        return jsonify(
            {"error": f"@{user.username} already leads enough guilds."}), 409

    if not board.has_rescinded_invite(user):

        #notification

        text = f"You have been invited to join +{board.name} as a guildmaster. You can [click here]({board.permalink}/mod/mods) and accept this invitation. Or, if you weren't expecting this, you can ignore it."
        send_notification(user, text)

    new_mod = ModRelationship(user_id=user.id,
                              board_id=board.id,
                              accepted=False)
    db.add(new_mod)
    db.commit()

    return "", 204
Example #22
0
def api_vote_comment(comment_id, x, v):

    if x not in ["-1", "0", "1"]:
        abort(400)

    x = int(x)

    comment = get_comment(comment_id)

    if comment.is_banned or comment.is_deleted or comment.post.is_archived:
        abort(403)

    #check for existing vote
    existing = db.query(CommentVote).filter_by(user_id=v.id,
                                               comment_id=comment.id).first()
    if existing:
        existing.change_to(x)
        #print(f"Re-vote Event: @{v.username} vote {x} on comment {comment_id}")
        return "", 204

    vote = CommentVote(user_id=v.id,
                       vote_type=x,
                       comment_id=base36decode(comment_id))

    db.add(vote)
    db.commit()

    #print(f"Vote Event: @{v.username} vote {x} on comment {comment_id}")

    return "", 204
Example #23
0
def mod_edit_rule(bid, board, v):
    r = base36decode(request.form.get("rid"))
    r = db.query(Rules).filter_by(id=r)

    if not r:
        abort(500)

    if board.is_banned:
        abort(403)

    if board.has_ban(v):
        abort(403)

    body = request.form.get("body", "")
    with CustomRenderer() as renderer:
        body_md = renderer.render(mistletoe.Document(body))
    body_html = sanitize(body_md, linkgen=True)

    r.rule_body = body
    r.rule_html = body_html
    r.edited_utc = int(time.time())

    db.add(r)
    db.commit()
    return "", 204
Example #24
0
def api_vote_comment(post_id, x, v):

    if x not in ["-1", "0", "1"]:
        abort(400)

    x = int(x)
    comment_id = base36decode(comment_id)

    comment = db.query(Comment).filter_by(id=comment_id).first()
    if not comment_id:
        abort(404)

    if comment_id.is_banned:
        abort(403)

    #check for existing vote
    existing = db.query(CommentVote).filter_by(user_id=v.id,
                                               comment_id=comment_id).first()
    if existing:
        existing.change_to(x)
        return "", 204

    vote = Vote(user_id=v.id, vote_type=x, submission_id=post_id)

    db.add(vote)
    db.commit()

    return "", 204
Example #25
0
def mod_board_color(bid, board, v):

    color = str(request.form.get("color", ""))

    if len(color) != 6:
        color = "603abb"

    r = color[0:1]
    g = color[2:3]
    b = color[4:5]

    try:
        if any([int(x, 16) > 255 for x in [r, g, b]]):
            color = "603abb"
    except ValueError:
        color = "603abb"

    board.color = color
    board.color_nonce += 1

    db.add(board)
    db.commit()

    try:
        cache.delete_memoized(board_css, board.name)
        cache.delete_memoized(board_dark_css, board.name)
    except:
        pass

    return redirect(f"/+{board.name}/mod/appearance?msg=Success")
Example #26
0
def mod_take_pid(pid, v):

    bid = request.form.get("board_id",None)
    if not bid:
        abort(400)

    board=get_board(bid)

    if board.is_banned:
        abort(403)

    if not board.has_mod(v):
        abort(403)

    post = get_post(pid)

    if not post.board_id==1:
        abort(422)

    if board.has_ban(post.author):
        abort(403)

    if not board.can_take(post):
        abort(403)

    post.board_id=board.id
    post.guild_name=board.name
    db.add(post)
    db.commit()

    #clear board's listing caches
    cache.delete_memoized(Board.idlist, board)
    
    return redirect(post.permalink)
Example #27
0
def settings_new_feedkey(v):

    v.feed_nonce+=1
    db.add(v)
    db.commit()

    return render_template("settings_profile.html", v=v, msg="Your new custom RSS Feed Token has been generated.")
Example #28
0
    def del_banner(self):

        aws.delete_file(
            name=f"users/{self.username}/banner-{self.banner_nonce}.png")
        self.has_banner = False
        db.add(self)
        db.commit()
Example #29
0
def api_agree_tos(v):

    v.tos_agreed_utc=int(time.time())

    db.add(v)
    db.commit()

    return redirect("/help/terms")
Example #30
0
def mod_settings_toggle_banner(bid, board, v):
    #toggle show/hide banner
    board.hide_banner_data = bool(request.form.get("hidebanner", False) == 'true')

    db.add(board)
    db.commit()

    return "", 204