Generate and delete API tokens

This commit is contained in:
Simon 2018-06-09 12:41:28 -04:00
parent de717d3992
commit a25976d24a
5 changed files with 131 additions and 8 deletions

32
app.py
View File

@ -230,7 +230,37 @@ def admin_logout():
@app.route("/dashboard")
def admin_dashboard():
if "username" in session:
return render_template("dashboard.html")
tokens = db.get_tokens()
return render_template("dashboard.html", api_tokens=tokens)
else:
return abort(403)
@app.route("/generate_token", methods=["POST"])
def admin_generate_token():
if "username" in session:
description = request.form.get("description")
db.generate_api_token(description)
flash("Generated API token", "success")
return redirect("/dashboard")
else:
return abort(403)
@app.route("/del_token", methods=["POST"])
def admin_del_token():
if "username" in session:
token = request.form.get("token")
db.delete_token(token)
flash("Deleted API token", "success")
return redirect("/dashboard")
else:
return abort(403)

View File

@ -3,6 +3,7 @@ import datetime
import json
import os
import bcrypt
import uuid
class InvalidQueryException(Exception):
@ -29,6 +30,13 @@ class File:
self.website_id = website_id
class ApiToken:
def __init__(self, token, description):
self.token = token
self.description = description
class Database:
SORT_ORDERS = {
@ -391,6 +399,44 @@ class Database:
cursor.execute("INSERT INTO Admin (username, password) VALUES (?,?)", (username, hashed_pw))
conn.commit()
def check_api_token(self, token) -> bool:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("SELECT token FROM ApiToken WHERE token=?", (token, ))
return cursor.fetchone() is not None
def generate_api_token(self, description: str) -> str:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
token = str(uuid.uuid4())
cursor.execute("INSERT INTO ApiToken (token, description) VALUES (?, ?)", (token, description))
conn.commit()
return token
def get_tokens(self) -> list:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("SELECT * FROM ApiToken")
return [ApiToken(x[0], x[1]) for x in cursor.fetchall()]
def delete_token(self, token: str) -> None:
with sqlite3.connect(self.db_path) as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM ApiToken WHERE token=?", (token, ))
conn.commit()

View File

@ -45,7 +45,12 @@ CREATE TABLE Queue (
CREATE TABLE Admin (
username TEXT PRIMARY KEY NOT NULL,
password TEXT
)
);
CREATE TABLE ApiToken (
token TEXT PRIMARY KEY NOT NULL,
description TEXT
);
-- Full Text Index

View File

@ -75,7 +75,7 @@ function fillTable(rData) {
document.getElementById("baseUrl").innerHTML = rData["base_url"];
document.getElementById("fileCount").innerHTML = rData["total_count"];
document.getElementById("totalSize").innerHTML = humanFileSize(rData["total_size"]);
document.getElementById("reportTime").innerHTML = rData["report_time"];
document.getElementById("reportTime").innerHTML = rData["report_time"] + " UTC";
}

View File

@ -3,11 +3,53 @@
{% block body %}
<div class="container">
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
<a class="btn btn-info" href="/logout">Logout</a>
<div class="card">
<div class="card-header">Dashboard</div>
<div class="card-body">
<h3>API Keys</h3>
<table class="table table-striped">
<thead>
<tr>
<th>Description</th>
<th>Key</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{% for token in api_tokens %}
<tr>
<td>{{ token.description }}</td>
<td><code>{{ token.token }}</code></td>
<td>
<form action="/del_token" method="post">
<input type="hidden" value="{{ token.token }}" name="token">
<input type="submit" class="btn btn-danger" value="Delete">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<form action="/generate_token" method="post">
<div class="form-row">
<div class="col col-md-10">
<input class="form-control" name="description" placeholder="Description">
</div>
<div class="col col-md-2">
<input type="submit" class="form-control btn btn-primary" value="Generate API token">
</div>
</div>
</form>
<h3>Misc actions</h3>
<p>TODO: </p>
<hr>
<a class="btn btn-info" href="/logout">Logout</a>
</div>
</div>
</div>
</div>
{% endblock body %}