Exemple #1
0
def insert_user(user: dict):
    cur = get_db().cursor()

    # Check if user exists
    cur.execute("SELECT * FROM users WHERE id = ?", (user["id"], ))
    data = cur.fetchone()
    if data:
        if user["lastUpdate"] > data["last_update"]:
            # update our user
            current_app.logger.info(f"Updating user {user['name']}")
            cur.execute(
                "UPDATE users SET vip=?, name=?, transponder_code=? WHERE id=?",
                (
                    user["vip"],
                    user["name"],
                    user["transponder"],
                    user["id"],
                ),
            )
    else:
        current_app.logger.info(f"Inserting new user {user['name']}")
        cur.execute(
            "INSERT INTO users (vip, name, last_update, transponder_code) VALUES (?, ?,?,?)",
            (
                user["vip"],
                user["name"],
                user["lastUpdate"],
                user["transponder"],
            ),
        )

    get_db().commit()
Exemple #2
0
def delete_user(id: int):
    """Deletes a user

    Removes the user from the database, however debts are kept.
    """
    current_app.logger.warning(f"Deleting user with ID {id}")
    cur = get_db().cursor()
    cur.execute("DELETE FROM users WHERE id = ?", (id, ))
    get_db().commit()
Exemple #3
0
def sum_debt() -> int:
    """The sum of balances of users in debt"""
    cur = get_db().cursor()
    cur.execute(
        "SELECT SUM(balance) from balances WHERE id in (SELECT id FROM users WHERE system = FALSE) AND balance < 0;"
    )
    return cur.fetchone()[0] or 0
Exemple #4
0
def login():
    if request.method == "POST":
        username = request.form.get("username")
        password = request.form.get("password")
        next_url = request.form.get("next")
        db = get_db()
        error = None
        user = db.execute("SELECT * FROM admins WHERE username = ?",
                          (username, )).fetchone()

        if user is None:
            error = "Incorrect username."
        elif not check_password_hash(user["password"], password):
            error = "Incorrect password."

        if error is None:
            current_app.logger.info(f"{username} logged in")
            session.clear()
            session["user_id"] = user["username"]
            if next_url:
                return redirect(escape(next_url))
            return redirect(url_for(".admin"))

        current_app.logger.warn(f"{error} ({username}:{password})")
        flash(error)

    return render_template("admin/login.html")
Exemple #5
0
def total_intake() -> int:
    """The sum of money paid by non-system users"""
    cur = get_db().cursor()
    cur.execute(
        "SELECT SUM(amount) from transactions WHERE user in (SELECT id FROM users WHERE system = FALSE) AND amount > 0;"
    )
    return cur.fetchone()[0] or 0
Exemple #6
0
def vacuum_database():
    """Optimizes the Database file"""
    with scheduler.app.app_context():
        current_app.logger.info(f"Vacuuming database")
        with get_db() as con:
            con.execute("VACUUM")
        current_app.logger.info(f"Finished vacuuming")
Exemple #7
0
def load_logged_in_user():
    user_id = session.get("user_id")

    if user_id is None:
        g.user = None
    else:
        g.user = (get_db().execute("SELECT * FROM admins WHERE username = ?",
                                   (user_id, )).fetchone())
Exemple #8
0
def undo_transaction(id: int):
    """Deletes the last transaction of a user."""
    current_app.logger.warning(f"Deleting transaction with ID {id}")
    with get_db() as cur:
        cur.execute(
            "DELETE FROM transactions WHERE user = ? ORDER BY timestamp DESC LIMIT 1;",
            (id, ),
        )
Exemple #9
0
def get_transactions(limit=10) -> dict:
    """Return a list of transactions"""
    current_app.logger.debug(f"Retrieving last {limit} transactions")
    cur = get_db().cursor()
    cur.execute(
        "SELECT name, amount, description, timestamp FROM transactions LEFT JOIN users ON transactions.user = users.id ORDER BY timestamp DESC LIMIT ?;",
        (limit, ),
    )
    return cur.fetchall()
Exemple #10
0
def sum_transactions() -> int:
    """Sums all user transactions. Note that system users are excluded."""
    start_time = perf_counter()
    cur = get_db().cursor()
    cur.execute(
        "SELECT IFNULL(SUM(amount), 0) from transactions WHERE user in (SELECT id FROM users WHERE system = FALSE);"
    )
    current_app.logger.debug(
        f"Summing all transactions took {perf_counter() - start_time} milliseconds"
    )
    return cur.fetchone()[0]
Exemple #11
0
def get_user_from_name(name: str, sensitive=True) -> dict:
    """Like 'get_user()' but fetches by the name instead of ID"""
    with get_db() as cur:
        result = cur.execute(
            "SELECT users.id AS userid, * FROM users LEFT JOIN balances ON users.id = balances.id WHERE users.name LIKE ?",
            (name, ),
        ).fetchone()

    if result is None:
        raise ValueError(f"User with name '{name}' does not exist")
    else:
        return create_user(result, sensitive)
Exemple #12
0
def get_user(id: int, sensitive=True) -> dict:
    """Fetch a user by their ID"""
    with get_db() as cur:
        result = cur.execute(
            "SELECT users.id AS userid, * FROM users LEFT JOIN balances ON users.id = balances.id WHERE users.id = ?",
            (id, ),
        ).fetchone()

    if result is None:
        raise ValueError(f"User with ID '{id}' does not exist")
    else:
        return create_user(result, sensitive)
Exemple #13
0
def insert_transaction(transaction: dict):
    """Insert a transaction into the database"""

    user = transaction["user"]
    amount = transaction["amount"]
    description = transaction["description"]
    timestamp = transaction["timestamp"]

    current_app.logger.info(f"Booking {amount / 100} towards user ID {user}")

    cur = get_db().cursor()
    # Insert transaction
    cur.execute(
        "INSERT INTO transactions VALUES (?,?,?,?)",
        (
            user,
            amount,
            description,
            timestamp,
        ),
    )
    get_db().commit()
Exemple #14
0
def save_admin_password():
    """Change the admin password"""
    current_app.logger.warning("Changing administrator password")
    password = request.form.get("password")
    hashed = generate_password_hash(password)
    username = session.get("user_id")

    with get_db() as con:
        con.cursor().execute(
            "UPDATE admins SET password = ? WHERE username = ?",
            (hashed, username),
        )
        flash("Passwort geändert.")

    return redirect(url_for(".account"))
Exemple #15
0
def backup_database():
    """Saves an optimized copy of the database to instance folder"""

    backup_dir = current_app.config.get("BACKUP_DIR")

    # Ensure the backup folder exists
    os.makedirs(backup_dir, exist_ok=True)

    backup_file = os.path.join(backup_dir,
                               strftime("BACKUP-%Y-%m-%d-%H%M%S.sqlite"))

    current_app.logger.info(f"Backing up to {backup_file}")

    with get_db() as db:
        db.execute("VACUUM main INTO ?", (backup_file, ))

    current_app.logger.info(f"Finished backing up")

    prune_backups()
Exemple #16
0
def get_users(sensitive=True) -> dict:
    """Return a list of non-system users

    These can be directly converted to JSON for the client or used for further processing.
    """
    current_app.logger.debug(
        f"Retrieving users, include sensitive data: {sensitive}")
    cur = get_db().cursor()
    cur.execute(
        "SELECT users.id AS userid, * FROM users LEFT JOIN balances ON users.id = balances.id WHERE users.system = FALSE;"
    )

    # Probably inefficient, as this has serial overhead and then everything is fork()'ed
    results = [dict(row) for row in cur.fetchall()]

    with Pool() as pool:
        array = pool.starmap(create_user, product(results, [sensitive]))

    # Sort by VIP Status, then activity
    return sorted(array, key=lambda x: (-x["vip"], -x["lastUpdate"]))
Exemple #17
0
def save_table():
    user_id = request.form.get("id")
    vipstatus = request.form.get("vip") == "on"
    user_name = request.form.get("name")
    action = request.form.get("action")

    if action == "delete":
        delete_user(user_id)
        flash("Deleted user " + user_name)
        return redirect(url_for(".users"))

    if action == "undo":
        undo_transaction(user_id)
        flash(f"Letzte Transaktion von {user_name} gelöscht.")
        return redirect(url_for(".users"))

    # Assume we are getting one row
    user = [{
        "id": user_id,
        "vip": vipstatus,
        "name": user_name,
        "lastUpdate": time.time(),
        "transponder": request.form.get("transponder_code"),
    }]

    merge_users(user)

    # Check if a deposit was made
    if "payment" in request.form:
        # TODO: ensure there are no float innaccuracies
        payment = round(float(request.form.get("payment")) * 100)
        with get_db() as db:
            db.execute(
                "INSERT INTO transactions (user, amount, description) VALUES (?,?,?)",
                (user[0]["id"], payment, "Transaktion durch Adminbereich"),
            )

    flash("Updated user " + request.form.get("name"))

    return redirect(url_for(".users"))