Add user login form
This commit is contained in:
+42
-3
@@ -1,11 +1,12 @@
|
|||||||
import sqlite3
|
import sqlite3
|
||||||
|
from hashlib import sha256
|
||||||
|
|
||||||
def init_db(path: str) -> None:
|
def init_db(path: str) -> None:
|
||||||
with sqlite3.connect(path) as connection:
|
with sqlite3.connect(path) as connection:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
CREATE TABLE IF NOT EXISTS Tokens (
|
CREATE TABLE IF NOT EXISTS Tokens (
|
||||||
TOKEN TEXT PRIMARY KEY NOT NULL,
|
TKHASH TEXT PRIMARY KEY NOT NULL,
|
||||||
USERID INTEGER NOT NULL,
|
USERID INTEGER NOT NULL,
|
||||||
NAME TEXT NOT NULL
|
NAME TEXT NOT NULL
|
||||||
)
|
)
|
||||||
@@ -18,17 +19,55 @@ def init_db(path: str) -> None:
|
|||||||
)
|
)
|
||||||
''')
|
''')
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
CREATE TABLE IF NOT EXISTS Users (
|
||||||
|
USERID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
|
||||||
|
USERNAME TEXT NOT NULL UNIQUE,
|
||||||
|
PWHASH TEXT NOT NULL,
|
||||||
|
PWSALT TEXT NOT NULL,
|
||||||
|
EMAIL TEXT
|
||||||
|
IS_ADMIN INTEGER NOT NULL DEFAULT 0
|
||||||
|
)
|
||||||
|
''')
|
||||||
|
|
||||||
connection.commit()
|
connection.commit()
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
def check_token_domain(db_path: str, token: str, domain: str) -> bool:
|
def check_token_domain(db_path: str, token: str, domain: str) -> bool:
|
||||||
with sqlite3.connect(db_path) as connection:
|
with sqlite3.connect(db_path) as connection:
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
token_hash = sha256(token.encode('utf-8')).hexdigest()
|
||||||
|
|
||||||
cursor.execute('''
|
cursor.execute('''
|
||||||
SELECT COUNT(*) FROM Tokens
|
SELECT COUNT(*) FROM Tokens
|
||||||
JOIN Domains ON Tokens.userid = Domains.userid
|
JOIN Domains ON Tokens.userid = Domains.userid
|
||||||
WHERE token = ?
|
WHERE tkhash = ?
|
||||||
AND domain = ?
|
AND domain = ?
|
||||||
''', (token,domain))
|
''', (token_hash, domain))
|
||||||
|
|
||||||
|
return cursor.fetchone()[0] == 1
|
||||||
|
|
||||||
|
def user_login(db_path: str, username: str, password: str) -> bool:
|
||||||
|
with sqlite3.connect(db_path) as connection:
|
||||||
|
cursor = connection.cursor()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT pwsalt FROM Users
|
||||||
|
WHERE username = ?
|
||||||
|
''', (username,))
|
||||||
|
|
||||||
|
password_salt = cursor.fetchone()
|
||||||
|
if password_salt is None:
|
||||||
|
return False
|
||||||
|
password_salt = password_salt[0]
|
||||||
|
|
||||||
|
password_hash = sha256( (password_salt + password).encode('utf-8') ).hexdigest()
|
||||||
|
|
||||||
|
cursor.execute('''
|
||||||
|
SELECT COUNT(*) FROM Users
|
||||||
|
WHERE username = ?
|
||||||
|
AND pwhash = ?
|
||||||
|
''', (username, password_hash))
|
||||||
|
|
||||||
return cursor.fetchone()[0] == 1
|
return cursor.fetchone()[0] == 1
|
||||||
|
|||||||
+23
-1
@@ -1,4 +1,4 @@
|
|||||||
from flask import Flask, jsonify, request
|
from flask import Flask, jsonify, request, render_template, redirect
|
||||||
import auth
|
import auth
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@@ -8,6 +8,7 @@ HOSTS_PATH = "/app/hosts.d/izbi"
|
|||||||
DB_PATH = "/app/sqlite.db"
|
DB_PATH = "/app/sqlite.db"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
hosts = {}
|
hosts = {}
|
||||||
@@ -36,6 +37,27 @@ def validate_ip(ip: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
@app.route('/', methods=["GET"])
|
@app.route('/', methods=["GET"])
|
||||||
|
def homepage():
|
||||||
|
return render_template("index.html")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/login', methods=["POST"])
|
||||||
|
def login():
|
||||||
|
if "user" not in request.form or "pass" not in request.form:
|
||||||
|
return redirect("/"), 400
|
||||||
|
|
||||||
|
if request.form["user"].strip() == "" or request.form["pass"].strip() == "":
|
||||||
|
return redirect("/"), 400
|
||||||
|
|
||||||
|
if not auth.user_login(DB_PATH, request.form["user"], request.form["pass"]):
|
||||||
|
return redirect("/")
|
||||||
|
|
||||||
|
return redirect("/dashboard", code=302)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/health', methods=["GET"])
|
||||||
def health():
|
def health():
|
||||||
return jsonify({"status": "healthy", "comment": ""})
|
return jsonify({"status": "healthy", "comment": ""})
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>IZBI DNS</title>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Dynamic DNS service for <span style="font-family: monospace">.izbi</span> domains <span style="font-family: monospace">:3</span></p>
|
||||||
|
|
||||||
|
<form method="POST" action="/login">
|
||||||
|
<input type="text" name="user" placeholder="username" required /><br />
|
||||||
|
<input type="password" name="pass" placeholder="password" required /><br />
|
||||||
|
<button type="submit">Log in</button>
|
||||||
|
</form>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user