Ejemplo n.º 1
0
def admin(board_id):
    if get_slip() and get_slip().is_admin:
        board = db.session.query(Board).filter(Board.id == board_id).one()
        return render_template("board-admin.html", board=board)
    else:
        flash("Only admins can access board administration!")
        return redirect(url_for("boards.catalog", board_id=board_id))
Ejemplo n.º 2
0
def delete(thread_id):
    if not get_slip() or not (get_slip().is_admin or get_slip().is_mod):
        flash("Only moderators and admins can delete threads!")
        return redirect(url_for("threads.view", thread_id=thread_id))
    thread = db.session.query(Thread).filter(Thread.id == thread_id).one()
    board_id = thread.board
    ThreadPosts().delete(thread_id)
    flash("Thread deleted!")
    return redirect(url_for("boards.catalog", board_id=board_id))
Ejemplo n.º 3
0
def delete_post(post_id):
    if not get_slip() or not (get_slip().is_admin or get_slip().is_mod):
        flash("Only moderators and admins can delete posts!")
        return redirect(url_for_post(post_id))
    thread = db.session.query(Thread).filter(Thread.posts.any(Post.id == post_id)).one()
    thread_id = thread.id
    PostRemoval().delete(post_id)
    flash("Post deleted!")
    return redirect(url_for("threads.view", thread_id=thread_id))
Ejemplo n.º 4
0
def admin_update(board_id):
    if get_slip() is None or get_slip().is_admin is False:
        flash("Only admins can access board administration!")
        return redirect(url_for("boards.catalog", board_id=board_id))
    board = db.session.query(Board).filter(Board.id == board_id).one()
    parser = reqparse.RequestParser()
    parser.add_argument("name", type=str, required=True)
    parser.add_argument("rules", type=str, required=True)
    args = parser.parse_args()
    board.name = args["name"]
    board.rules = args["rules"]
    db.session.add(board)
    db.session.commit()
    return redirect(url_for("boards.catalog", board_id=board_id))
Ejemplo n.º 5
0
def move_submit(thread_id):
    if not get_slip() or not (get_slip().is_admin or get_slip().is_mod):
        flash("Only moderators and admins can move threads!")
        return redirect(url_for("threads.view", thread_id=thread_id))
    thread = Thread.query.get(thread_id)
    old_board = thread.board
    new_board = Board.query.filter(Board.name == request.form["board"]).one()
    thread.board = new_board.id
    db.session.add(thread)
    db.session.commit()
    invalidate_board_cache(old_board)
    invalidate_board_cache(new_board)
    flash("Thread moved!")
    return redirect(url_for("threads.view", thread_id=thread_id))
Ejemplo n.º 6
0
def update_poster_slip(poster: Poster, args: dict) -> None:
    "Updates the current poster with a slip if necessary."

    if args.get("useslip") is True:
        slip = get_slip()
        if slip and (slip.is_admin or slip.is_mod):
            poster.slip = slip.id
            db.session.add(poster)
Ejemplo n.º 7
0
 def post(self, thread_id):
     parser = reqparse.RequestParser()
     parser.add_argument("subject", type=str)
     parser.add_argument("body", type=str, required=True)
     parser.add_argument("useslip", type=inputs.boolean)
     parser.add_argument("spoiler", type=inputs.boolean)
     # check captcha cooldown
     on_cooldown = cooldown.on_captcha_cooldown()
     # only check of captcha if the client is not on cooldown
     if on_cooldown is False:
         if app.config.get("CAPTCHA_METHOD") == "RECAPTCHA":
             parser.add_argument("recaptcha-token", type=str, required=True)
         elif app.config.get("CAPTCHA_METHOD") == "CAPTCHOULI":
             parser.add_argument("captchouli-id", type=str, required=True)
             for img_num in range(0, 9):
                 # don't bother validating too closely since captchouli takes care of
                 # that for us
                 parser.add_argument("captchouli-%d" % img_num,
                                     type=str,
                                     default=False)
     args = parser.parse_args()
     ip = None
     # reverse proxy support
     if 'X-Forwarded-For' in request.headers:
         ip = request.headers.getlist("X-Forwarded-For")[0].rpartition(
             ' ')[-1]
     else:
         ip = request.environ["REMOTE_ADDR"]
     # check captcha if necessary
     board_id = db.session.query(Thread).filter_by(id=thread_id).one().board
     if on_cooldown is False:
         if app.config.get("CAPTCHA_METHOD") == "RECAPTCHA":
             google_response = requests.post(
                 "https://www.google.com/recaptcha/api/siteverify",
                 data={
                     "secret": app.config["RECAPTCHA_SECRET_KEY"],
                     "response": args["recaptcha-token"]
                 }).json()
             if google_response["success"] is False:
                 raise CaptchaError("Problem getting reCAPTCHA", board_id)
             if google_response["score"] < app.config["RECAPTCHA_THRESHOLD"]:
                 raise CaptchaError("reCAPTCHA threshold too low", board_id)
         elif app.config.get("CAPTCHA_METHOD") == "CAPTCHOULI":
             captchouli_form = {"captchouli-id": args["captchouli-id"]}
             for img_num in range(0, 9):
                 key = "captchouli-%d" % img_num
                 captchouli_form[key] = args[key]
             if not captchouli.valid_solution(captchouli_form):
                 raise CaptchaError("Incorrect CAPTCHA response", board_id)
     cooldown.refresh_captcha_cooldown()
     poster = db.session.query(Poster).filter_by(thread=thread_id,
                                                 ip_address=ip).first()
     body = args["body"]
     should_bump = False
     if poster is None:
         poster_hex = gen_poster_id()
         poster = Poster(hex_string=poster_hex,
                         ip_address=ip,
                         thread=thread_id)
         db.session.add(poster)
         db.session.flush()
         # bump thread if the poster hasn't posted in this thread before
         should_bump = True
     else:
         # bump thread if this poster isn't the same as the one who posted last in the thread
         last_post = db.session.query(Post).filter_by(
             thread=thread_id).order_by(Post.id.desc()).first()
         if last_post.poster != poster.id:
             should_bump = True
     if args.get("useslip") is True:
         slip = get_slip()
         if slip and (slip.is_admin or slip.is_mod):
             poster.slip = slip.id
             db.session.add(poster)
     media_id = None
     if "media" in request.files and request.files["media"].filename:
         uploaded_file = request.files["media"]
         mimetype = uploaded_file.content_type
         board = db.session.query(Board).filter_by(id=board_id).one()
         expected_mimetypes = board.mimetypes
         if re.match(expected_mimetypes, mimetype) is None:
             db.session.rollback()
             raise InvalidMimeError(mimetype, board_id)
         media = storage.save_attachment(uploaded_file)
         media_id = media.id
     post = Post(body=body,
                 subject=args["subject"],
                 thread=thread_id,
                 poster=poster.id,
                 media=media_id,
                 spoiler=args["spoiler"])
     db.session.add(post)
     db.session.flush()
     replying = re.finditer(REPLY_REGEXP, body)
     replies = set()
     if replying:
         for match in replying:
             raw_reply_id = match.group(2)
             reply_id = int(raw_reply_id)
             replies.add(reply_id)
         for reply_id in replies:
             reply = Reply(reply_from=post.id, reply_to=reply_id)
             db.session.add(reply)
     if should_bump:
         thread = db.session.query(Thread).filter_by(id=thread_id).one()
         thread.last_updated = post.datetime
         db.session.add(thread)
     db.session.flush()
     db.session.commit()
     pubsub_client = keystore.Pubsub()
     pubsub_client.publish(
         "new-post", json.dumps({
             "thread": thread_id,
             "post": post.id
         }))
     for reply_id in replies:
         pubsub_client.publish(
             "new-reply",
             json.dumps({
                 "post": post.id,
                 "thread": post.thread,
                 "reply_to": reply_id
             }))
Ejemplo n.º 8
0
 def post(self, thread_id):
     parser = reqparse.RequestParser()
     parser.add_argument("subject", type=str)
     parser.add_argument("body", type=str, required=True)
     parser.add_argument("useslip", type=inputs.boolean)
     parser.add_argument("spoiler", type=inputs.boolean)
     args = parser.parse_args()
     ip = ip_to_int(request.environ["REMOTE_ADDR"])
     poster = db.session.query(Poster).filter_by(thread=thread_id,
                                                 ip_address=ip).first()
     body = args["body"]
     should_bump = False
     if poster is None:
         poster_hex = gen_poster_id()
         poster = Poster(hex_string=poster_hex,
                         ip_address=ip,
                         thread=thread_id)
         db.session.add(poster)
         db.session.commit()
         # bump thread if the poster hasn't posted in this thread before
         should_bump = True
     if args.get("useslip") is True:
         slip = get_slip()
         if slip and (slip.is_admin or slip.is_mod):
             poster.slip = slip.id
             db.session.add(poster)
             db.session.commit()
     media_id = None
     if "media" in request.files and request.files["media"].filename:
         uploaded_file = request.files["media"]
         file_ext = uploaded_file.filename.rsplit('.', 1)[1].lower()
         media = Media(ext=file_ext)
         db.session.add(media)
         db.session.commit()
         media_id = media.id
         full_path = os.path.join(app.config["UPLOAD_FOLDER"],
                                  "%d.%s" % (media_id, file_ext))
         uploaded_file.save(full_path)
         if file_ext != "webm":
             # non-webm thumbnail generation
             thumb = Image.open(full_path)
             if thumb.mode in ("RGBA", "LA"):
                 background = Image.new(thumb.mode[:-1], thumb.size,
                                        (255, 255, 255))
                 background.paste(thumb, thumb.split()[-1])
                 thumb = background
             size = thumb.size
             scale_factor = 0
             # width > height
             if size[0] > size[1]:
                 scale_factor = 500 / size[0]
             else:
                 scale_factor = 500 / size[1]
             new_width = int(thumb.width * scale_factor)
             new_height = int(thumb.height * scale_factor)
             thumb = thumb.resize((new_width, new_height), Image.LANCZOS)
             thumb.convert("RGB").save(
                 os.path.join(app.config["THUMB_FOLDER"],
                              "%d.jpg" % media_id), "JPEG")
         else:
             # FIXME: webm thumbnail generation
             pass
     post = Post(body=body,
                 subject=args["subject"],
                 thread=thread_id,
                 poster=poster.id,
                 media=media_id,
                 spoiler=args["spoiler"])
     db.session.add(post)
     db.session.commit()
     replying = re.finditer(REPLY_REGEXP, body)
     if replying:
         for match in replying:
             for raw_reply_id in match.groups():
                 reply_id = int(raw_reply_id)
                 reply = Reply(reply_from=post.id, reply_to=reply_id)
                 db.session.add(reply)
                 db.session.commit()
     if should_bump:
         thread = db.session.query(Thread).filter_by(id=thread_id).one()
         thread.last_updated = post.datetime
         db.session.commit()
Ejemplo n.º 9
0
def move(thread_id):
    if not get_slip() or not (get_slip().is_admin or get_slip().is_mod):
        flash("Only moderators and admins can move threads!")
        return redirect(url_for("threads.view", thread_id=thread_id))
    return render_template("thread-move.html", thread_id=thread_id)
Ejemplo n.º 10
0
def index():
    if get_slip() and get_slip().is_admin:
        boards = db.session.query(Board).all()
        slips = db.session.query(Slip).all()
        if (request.method == "POST"):
            for slip in slips:
                admin_status = request.form.getlist(slip.name + "_grant_admin")
                mod_status = request.form.getlist(slip.name + "_grant_mod")
                revoke_slip = request.form.getlist(slip.name + "_revoke_slip")
                new_board_name = request.form.getlist("board_name")

                # editing mod/admin status
                if (len(admin_status) > 0 and admin_status[0] == "on"):
                    slip.is_admin = True
                else:
                    slip.is_admin = False

                if (len(mod_status) > 0 and mod_status[0] == "on"):
                    slip.is_mod = True
                else:
                    slip.is_mod = False

                old_slip = db.session.query(Slip).filter(
                    Slip.name == slip.name).one()
                old_slip.is_admin = slip.is_admin
                old_slip.is_mod = slip.is_mod

                # revoking slip
                if (len(revoke_slip) > 0 and revoke_slip[0] == "on"):
                    db.session.query(Slip).filter(
                        Slip.name == slip.name).delete()

            # add board
            if (len(new_board_name) > 0 and len(new_board_name[0]) > 0):
                # check to see that board already exists
                existing_boards = db.session.query(Board).filter(
                    Board.name == new_board_name[0]).all()
                if (len(existing_boards) == 0):
                    new_board = Board(name=new_board_name[0],
                                      max_threads=50,
                                      mimetypes="",
                                      rules="",
                                      subreddits="")
                    db.session.add(new_board)

            # Delete board
            for board in boards:
                delete_board = request.form.getlist(board.name +
                                                    "_delete_board")
                if (len(delete_board) > 0 and delete_board[0] == "on"):
                    boards_to_delete = db.session.query(Board).filter(
                        Board.name == board.name).all()
                    for tmp_board in boards_to_delete:
                        threads_to_delete = db.session.query(Thread).filter(
                            Thread.board == tmp_board.id).all()
                        for thread in threads_to_delete:
                            posts_to_delete = db.session.query(Post).filter(
                                Post.thread == thread.id).all()
                            for post in posts_to_delete:
                                db.session.query(Post).filter(
                                    Post.id == post.id).delete()
                            db.session.query(Thread).filter(
                                Thread.id == thread.id).delete()
                        db.session.query(Board).filter(
                            Board.id == tmp_board.id).delete()
            db.session.commit()

            # edit FAQ
            faq = request.form.getlist("faq")
            if (len(faq) > 0):
                faq = faq[0]

            # edit rules
            rules = request.form.getlist("rules")
            if (len(rules) > 0):
                rules = rules[0]

        elif (request.method == "GET"):
            print("doing nothing")
        return render_template("site-admin.html",
                               boards=boards,
                               slips=slips,
                               faq=render_template("faq.html"),
                               rules=render_template("rules.html"))

    else:
        flash("Only admins can access board administration!")
        return redirect(url_for("main.faq"))