implement client users
This commit is contained in:
73
app.py
73
app.py
@@ -7,6 +7,7 @@ from urllib.parse import urlparse
|
||||
from flask import (
|
||||
Flask, render_template, request, redirect, url_for, flash, session, jsonify, abort
|
||||
)
|
||||
from werkzeug.security import generate_password_hash, check_password_hash
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Config
|
||||
@@ -121,6 +122,39 @@ def create_app():
|
||||
rows = conn.execute(query).fetchall()
|
||||
return render_template("apps_list.html", apps=rows)
|
||||
|
||||
@app.route("/admin/users/new", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def user_create():
|
||||
"""Admin page to create application users (username + password)."""
|
||||
if request.method == "POST":
|
||||
username = (request.form.get("username", "").strip()).lower()
|
||||
password = request.form.get("password", "")
|
||||
|
||||
# Basic validations
|
||||
if not username:
|
||||
flash("Username is required", "danger")
|
||||
return render_template("create_user.html")
|
||||
if not password or len(password) < 6:
|
||||
flash("Password must be at least 6 characters", "danger")
|
||||
return render_template("create_user.html")
|
||||
|
||||
pwd_hash = generate_password_hash(password)
|
||||
try:
|
||||
with get_db() as conn:
|
||||
conn.execute(
|
||||
"INSERT INTO users (username, password_hash, created_at) VALUES (?,?,?)",
|
||||
(username, pwd_hash, datetime.utcnow().isoformat(timespec='seconds')),
|
||||
)
|
||||
conn.commit()
|
||||
flash("User created", "success")
|
||||
return redirect(url_for("apps_list"))
|
||||
except sqlite3.IntegrityError:
|
||||
flash("Username already exists", "danger")
|
||||
return render_template("create_user.html")
|
||||
|
||||
# GET
|
||||
return render_template("create_user.html")
|
||||
|
||||
@app.route("/apps/new", methods=["GET", "POST"])
|
||||
@login_required
|
||||
def app_create():
|
||||
@@ -221,6 +255,36 @@ def create_app():
|
||||
# ---------------------------
|
||||
# API Endpoint (public or protected — here public for simplicity)
|
||||
# ---------------------------
|
||||
@app.route("/api/login", methods=["POST"])
|
||||
def api_login():
|
||||
"""Simple login endpoint for the Android app.
|
||||
Expects JSON: {"username": "...", "password": "..."}
|
||||
Returns 200 on success with optional token field, 401 on failure.
|
||||
"""
|
||||
try:
|
||||
payload = request.get_json(silent=True) or {}
|
||||
username = (payload.get("username") or "").strip().lower()
|
||||
password = payload.get("password") or ""
|
||||
except Exception:
|
||||
return jsonify({"error": "Invalid JSON"}), 400
|
||||
|
||||
if not username or not password:
|
||||
return jsonify({"error": "username and password are required"}), 400
|
||||
|
||||
with sqlite3.connect(DB_PATH) as conn:
|
||||
conn.row_factory = sqlite3.Row
|
||||
row = conn.execute(
|
||||
"SELECT id, username, password_hash FROM users WHERE username=?",
|
||||
(username,),
|
||||
).fetchone()
|
||||
|
||||
if not row or not check_password_hash(row["password_hash"], password):
|
||||
return jsonify({"error": "Invalid credentials"}), 401
|
||||
|
||||
# For now we do not issue a JWT; Android accepts null/absent token.
|
||||
# If you later add JWT, return it here as {"token": "..."}
|
||||
return jsonify({"token": None}), 200
|
||||
|
||||
@app.route("/api/apps", methods=["GET"])
|
||||
def api_apps():
|
||||
with get_db() as conn:
|
||||
@@ -256,6 +320,13 @@ CREATE TABLE IF NOT EXISTS apps (
|
||||
priority INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS users (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT NOT NULL UNIQUE,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at TEXT NOT NULL
|
||||
);
|
||||
"""
|
||||
|
||||
|
||||
@@ -263,7 +334,7 @@ def init_db():
|
||||
DB_PATH.parent.mkdir(parents=True, exist_ok=True)
|
||||
with sqlite3.connect(DB_PATH) as conn:
|
||||
conn.execute("PRAGMA journal_mode=WAL;")
|
||||
conn.execute(SCHEMA_SQL)
|
||||
conn.executescript(SCHEMA_SQL)
|
||||
conn.commit()
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user