Example #1
0
def operate(operation, type):
    user = check_permission()
    sudo = check_sudo(user)

    if not sudo:
        return flask.redirect("/dashboard/sudo")

    target_id = flask.request.args.get("target")
    if not target_id:
        flask.abort(400)

    hidden = True if operation == "delete" else False

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "UPDATE {0} SET hidden = %s WHERE {0}_id = %s ".format(type),
            (hidden, target_id))
        cnx.commit()
    finally:
        cnx.close()

    referrer = "/" if type == "thread" else flask.request.referrer
    write_log(operation, user, {"type": type, "id": target_id})
    return flask.redirect(referrer)
Example #2
0
def logout():
    referrer = flask.request.referrer

    try:
        referrer.index("/logout")
    except ValueError:
        pass
    else:
        referrer = "/"

    cookie = flask.request.cookies.get("session")
    if cookie == None:
        return flask.redirect(referrer)

    user_id = read_cookie(cookie)
    if user_id == None:
        return flask.redirect(referrer)

    cnx = get_pg_connection()

    response = flask.make_response(flask.redirect(referrer))
    response.set_cookie("session", "", expires=0)
    response.set_cookie("sudo_mode", "", expires=0)
    write_log("logout", user_id, {"success": True})
    return response
Example #3
0
def new_thread():
    now = datetime.datetime.now()

    try:
        userid = read_cookie(flask.request.cookies["session"])
    except KeyError:
        flask.abort(401)

    if userid == None:
        flask.abort(401)

    try:
        title = flask.request.form["title"]
        category = flask.request.form["category"]
        renderer = flask.request.form["renderer"]
        content = flask.request.form["content"]
        is_draft = bool(int(flask.request.form["draft"]))
    except KeyError:
        flask.abort(400)

    thread_id = str(uuid.uuid4()).replace('-', '')
    post_id = str(uuid.uuid4()).replace('-', '')
    post_content_id = str(uuid.uuid4()).replace('-', '')

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "INSERT INTO thread VALUES ("
            "%s, %s, %s, %s, %s, FALSE, %s )",
            (thread_id, userid, category, now, title, bool(is_draft)))

        cursor.execute(
            "INSERT INTO post VALUES ("
            "%s, %s, %s, %s, FALSE, %s, %s)",
            (post_id, userid, thread_id, now, now, post_content_id))

        cursor.execute(
            "INSERT INTO post_content VALUES ("
            "%s, %s, %s, %s, %s)",
            (post_content_id, post_id, renderer, content, now))
        cnx.commit()
        write_log("new_thread", userid, {
            "success": True,
            "id": thread_id,
            "title": title
        })
    finally:
        cnx.close()

    return flask.redirect("/thread/view/" + thread_id)
Example #4
0
def registration():
    if flask.request.method == "GET":
        referrer = flask.request.referrer
        return render_template("login.tmpl",
                               title="注册",
                               referrer=referrer,
                               type="registration")

    try:
        username = flask.request.form["username"]
        password = flask.request.form["password"]
        email = flask.request.form["email"]
        referrer = flask.request.form["referrer"]
    except KeyError:
        flask.abort(400)

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute("SELECT * FROM users WHERE name = %s", (username, ))
        if cursor.fetchone() != None:
            write_log(
                "registration", "", {
                    "success": False,
                    "username": username,
                    "reason": "user already exists"
                })
            return render_template("login.tmpl",
                                   title="注册",
                                   referrer=referrer,
                                   error="用户 {} 已经存在".format(username))

        user_id = str(uuid.uuid4()).replace('-', '').upper()
        salt = crypt.mksalt(crypt.METHOD_SHA256)
        hashed_password = hashlib.sha256(
            (password + salt).encode()).hexdigest().upper()
        cursor.execute(
            "INSERT INTO users VALUES ( "
            "%s, %s, %s, %s, %s, FALSE, FALSE, %s)",
            (user_id, username, email, hashed_password, username, salt))
        cnx.commit()
        write_log("registration", user_id, {"success": True})
    finally:
        cnx.close()

    cookie = create_cookie(user_id)
    response = flask.make_response(flask.redirect(referrer))
    response.set_cookie("session", cookie, expires=32503680000)
    return response
Example #5
0
def userinfo_update():
    user = check_permission()
    sudo = check_sudo(user)
    if not sudo:
        return flask.redirect("/dashboard/sudo")

    try:
        userid = flask.request.form["id"]
        nick = flask.request.form["nick"]
        email = flask.request.form["email"]
        superuser = flask.request.form["superuser"]
    except KeyError:
        flask.abort(400)

    superuser = (superuser == "true")

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT nick, email, admin FROM users WHERE user_id = %s",
            (userid, ))
        oldnick, oldemail, oldadmin = cursor.fetchone()
        cursor.execute(
            "UPDATE users SET (nick, email, admin) = ( "
            "%s, %s, %s ) WHERE user_id = %s",
            (nick, email, superuser, userid))
        cnx.commit()
    finally:
        cnx.close()

    log_data = {
        "operator": user,
        "original": {
            "nick": oldnick,
            "email": oldemail,
            "superuser": oldadmin
        },
        "new": {
            "nick": nick,
            "email": email,
            "superuser": superuser
        }
    }

    write_log("update_profile", user, log_data)

    return flask.redirect("/dashboard/userinfo/{}".format(userid))
Example #6
0
def category_merge():
    user = check_permission()
    sudo = check_sudo(user)
    if not sudo:
        return flask.redirect("/dashboard/sudo")

    try:
        src_id = flask.request.form["src"]
        dst_id = flask.request.form["dst"]
    except KeyError:
        flask.abort(400)

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute('SELECT name FROM category WHERE category_id = %s',
                       (src_id, ))
        src_name, = cursor.fetchone()
        cursor.execute('SELECT name FROM category WHERE category_id = %s',
                       (dst_id, ))
        dst_name, = cursor.fetchone()

        cursor.execute('UPDATE thread SET category = %s WHERE category = %s',
                       (dst_id, src_id))
        cursor.execute('DELETE FROM category WHERE category_id = %s',
                       (src_id, ))
        cnx.commit()
    finally:
        cnx.close()

    log_data = {
        "src": {
            "id": src_id,
            "name": src_name
        },
        "dst": {
            "id": dst_id,
            "name": dst_name
        }
    }
    write_log("category_merge", user, log_data)

    return flask.redirect("/dashboard/category")
Example #7
0
def reply():
    now = datetime.datetime.now()

    try:
        userid = read_cookie(flask.request.cookies["session"])
    except KeyError:
        flask.abort(401)

    if userid == None:
        flask.abort(401)

    try:
        renderer = flask.request.form["renderer"]
        content = flask.request.form["content"]
        thread_id = flask.request.form["thread_id"]
    except KeyError:
        flask.abort(400)

    post_id = str(uuid.uuid4()).replace('-', '')
    post_content_id = str(uuid.uuid4()).replace('-', '')

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "INSERT INTO post VALUES ("
            "%s, %s, %s, %s, FALSE, %s, %s)",
            (post_id, userid, thread_id, now, now, post_content_id))
        cursor.execute(
            "INSERT INTO post_content VALUES ("
            "%s, %s, %s, %s, %s)",
            (post_content_id, post_id, renderer, content, now))
        cnx.commit()
        write_log("new_reply", userid, {
            "success": True,
            "post_id": post_id,
            "content_id": post_content_id
        })
    finally:
        cnx.close()

    return flask.redirect(flask.request.referrer)
Example #8
0
def sudo():
    user = check_permission()

    redis = get_redis_connection()
    failed_attempts = redis.get('sudo_fail_{}'.format(user))
    failed_attempts = int(failed_attempts) if failed_attempts != None else 0
    if failed_attempts >= 5:
        write_log("dashboard_access", user, {
            "success": False,
            "reason": "too many attemps"
        })
        return render_template("dashboard/sudo.tmpl", error=True, chances=0)

    if flask.request.method == "GET":
        return render_template("dashboard/sudo.tmpl")

    password = flask.request.form.get("password")
    if password == None:
        flask.abort(400)

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute("SELECT salt FROM users WHERE user_id = %s", (user, ))
        salt = cursor.fetchone()[0]

    finally:
        cnx.close()

    hashed_password = hashlib.sha256(
        (password + salt).encode()).hexdigest().upper()

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT * FROM users WHERE user_id = %s AND password = %s",
            (user, hashed_password))
        result = cursor.fetchone()
    finally:
        cnx.close()

    if result == None:
        write_log("dashboard_access", user, {"success": False})
        redis = get_redis_connection()
        failed_attemps = int(redis.incr('sudo_fail_{}'.format(user)))
        redis.expire('sudo_fail_{}'.format(user), 300)
        ret = render_template("dashboard/sudo.tmpl",
                              error=True,
                              chances=max(5 - failed_attemps, 0))
        return ret
    else:
        ret = flask.make_response(flask.redirect("/dashboard/"))
        ret.set_cookie("sudo_mode", create_cookie(user))
        redis = get_redis_connection()
        redis.delete('sudo_fail_{}'.format(user))
        write_log("dashboard_access", user, {"success": True})
        return ret
Example #9
0
def check_permission():
    session = flask.request.cookies.get("session")
    if session == None or read_cookie(session) == None:
        write_log("dashboard_access", "", {"success": False})
        flask.abort(401)

    user = read_cookie(session)

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT * FROM users WHERE user_id = %s AND admin = TRUE",
            (user, ))
        result = (cursor.fetchone() != None)
    finally:
        cnx.close()

    if not result:
        write_log("dashboard_access", user, {"success": False})
        flask.abort(401)

    return user
Example #10
0
def categories_new():
    user = check_permission()
    sudo = check_sudo(user)

    if not sudo:
        return flask.redirect("/dashboard/sudo")

    name = flask.request.form.get("name")
    if not name:
        flask.abort(400)

    category_id = str(uuid.uuid4()).replace('-', '').upper()

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute("INSERT INTO category VALUES (%s, %s)",
                       (category_id, name))
        cnx.commit()
    finally:
        cnx.close()

    write_log("category_new", user, {"success": True, "category": name})
    return flask.redirect('/dashboard/category')
Example #11
0
def userinfo():
    try:
        user = read_cookie(flask.request.cookies["session"])
    except KeyError:
        return flask.redirect("/")

    if not user:
        flask.redirect("/")

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            'SELECT name, email, nick, salt FROM users WHERE user_id = %s',
            (user, ))
        name, email, nick, salt = cursor.fetchone()
    finally:
        cnx.close()

    if flask.request.method == "GET":
        return render_template("userinfo.tmpl",
                               error=False,
                               name=name,
                               email=email,
                               nick=nick,
                               title="User Info")
    else:
        try:
            new_email = flask.request.form["email"]
            new_nick = flask.request.form["nick"]
            old_password = flask.request.form["old_password"]
            new_password = flask.request.form["new_password"]
        except:
            return flask.abort(400)

        if new_password != "":
            cnx = get_pg_connection()
            cursor = cnx.cursor()
            try:
                hashed_old_password = hashlib.sha256(
                    (old_password + salt).encode()).hexdigest().upper()
                cursor.execute(
                    "SELECT user_id FROM users WHERE user_id = %s AND password = %s",
                    (user, hashed_old_password))
                if not cursor.fetchone():
                    cnx.close()
                    write_log("update_userinfo", user, {
                        "success": False,
                        "reason": "wrong password"
                    })
                    return render_template("userinfo.tmpl",
                                           error=True,
                                           name=name,
                                           email=email,
                                           nick=nick,
                                           title="User Info")
            except:
                cnx.close()
                raise

            salt = crypt.mksalt(crypt.METHOD_SHA256)
            hashed_password = hashlib.sha256(
                (new_password + salt).encode()).hexdigest().upper()
        else:
            hashed_password = None

        cnx = get_pg_connection()
        try:
            cursor = cnx.cursor()
            if hashed_password:
                cursor.execute(
                    "UPDATE users SET email = %s, nick = %s, password = %s, salt = %s WHERE user_id = %s",
                    (new_email, new_nick, hashed_password, salt, user))
            else:
                cursor.execute(
                    "UPDATE users SET email = %s, nick = %s WHERE user_id = %s",
                    (new_email, new_nick, user))
            cnx.commit()
        finally:
            cnx.close()

        log_data = {
            "success": True,
            "nick": [nick, new_nick],
            "email": [email, new_email],
            "password_changed": new_password != ""
        }
        write_log("update_userinfo", user, log_data)
        return flask.redirect("/userinfo")
Example #12
0
def edit(edit_type):
    try:
        renderer = flask.request.form["renderer"]
        content = flask.request.form["content"]
        referrer = flask.request.form["referrer"]
        post_id = flask.request.form["post_id"]
    except KeyError:
        flask.abort(400)

    user = read_cookie(flask.request.cookies["session"])

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "SELECT post.author, users.admin, post.content FROM post, users "
            "WHERE post.post_id = %s AND users.user_id = %s "
            "AND (post.author = users.user_id OR users.admin = TRUE)",
            (post_id, user))
        post_ret = cursor.fetchone()

        if not post_ret:
            cnx.close()
            flask.abort(401)

        _, _, old_content_id = post_ret
    except:
        cnx.close()
        raise

    if edit_type == "thread":
        try:
            thread_id = flask.request.form["thread_id"]
            title = flask.request.form["title"]
            category = flask.request.form["category"]
            is_draft = bool(int(flask.request.form["draft"]))
        except KeyError:
            flask.abort(400)

        cnx = get_pg_connection()
        try:
            cursor = cnx.cursor()
            cursor.execute(
                "SELECT title, category, draft FROM thread "
                "WHERE thread_id = %s", (thread_id, ))
            old_title, old_category, old_draft = cursor.fetchone()
        except TypeError:
            flask.abort(400)

    new_content_id = str(uuid.uuid4()).replace('-', '')

    cnx = get_pg_connection()
    try:
        cursor = cnx.cursor()
        cursor.execute(
            "INSERT INTO post_content VALUES ("
            "%s, %s, %s, %s, NOW())",
            (new_content_id, post_id, renderer, content))

        cursor.execute(
            "UPDATE post SET content = %s, last_modified = NOW() WHERE post_id = %s",
            (new_content_id, post_id))

        if edit_type == "thread":
            cursor.execute(
                "UPDATE thread SET title = %s, category = %s, draft = %s "
                "WHERE thread_id = %s", (title, category, is_draft, thread_id))
        cnx.commit()
    except:
        traceback.print_exc()

    finally:
        cnx.close()

    log_data = {
        "success": True,
        "post_id": post_id,
        "type": edit_type,
        "rev": [old_content_id, new_content_id]
    }

    if edit_type == "thread":
        log_data["thread"] = {
            "title": [old_title, title],
            "category": [old_category, category],
            "draft": [old_draft, is_draft]
        }

    write_log("edit", user, log_data)
    return flask.redirect(referrer)
Example #13
0
def login():
    if flask.request.method == "GET":
        referrer = flask.request.referrer
    else:
        referrer = flask.request.form["referrer"]

    try:
        referrer.index("/login")
    except ValueError:
        pass
    else:
        referrer = "/"

    if flask.request.method == "GET":
        return render_template("login.tmpl",
                               title="登录",
                               referrer=flask.request.referrer,
                               error=None,
                               type="login")
    else:
        username = flask.request.form["username"]
        password = flask.request.form["password"]

        cnx = get_pg_connection()
        try:
            cursor = cnx.cursor()
            cursor.execute("SELECT salt FROM users WHERE name = %s",
                           (username, ))
            salt = cursor.fetchone()
            if salt:
                salt = salt[0]
            else:
                error = "用户名或密码错误"
                write_log(
                    "login", "", {
                        "success": False,
                        "username": username,
                        "reason": "user does not exist"
                    })
                return render_template("login.tmpl",
                                       referrer=referrer,
                                       error=error,
                                       title="Login",
                                       type="login")
            hashed_password = hashlib.sha256(
                (password + salt).encode()).hexdigest().upper()
            cursor.execute(
                "SELECT user_id AS uid FROM users WHERE name = %s AND password = %s",
                (username, hashed_password))

            ret = cursor.fetchone()
            if not ret:
                cnx.close()
                error = "用户名或密码错误"
                write_log(
                    "login", "", {
                        "success": False,
                        "username": username,
                        "reason": "wrong password"
                    })
                return render_template("login.tmpl",
                                       referrer=referrer,
                                       error=error,
                                       title="Login",
                                       type="login")
        finally:
            cnx.close()

        userid = ret[0]
        cookie = create_cookie(userid)
        response = flask.make_response(flask.redirect(referrer))
        response.set_cookie("session", cookie, expires=32503680000)
        write_log("login", userid, {"success": True, "username": username})
        return response