"""
Deliberately vulnerable Flask application -- Chapter 3 reference target.

INTENTIONALLY INSECURE: SQL injection, SSTI, weak hashing, leaky errors.
FOR EDUCATIONAL USE ONLY. Do not deploy outside a local lab network.
"""

import hashlib
import sqlite3
import os
from flask import Flask, request, render_template_string, g

app = Flask(__name__)
DATABASE = "/data/users.db"

SCHEMA = """
CREATE TABLE IF NOT EXISTS users (
    id   INTEGER PRIMARY KEY AUTOINCREMENT,
    name TEXT NOT NULL,
    pass TEXT NOT NULL,
    role TEXT NOT NULL DEFAULT 'user'
);
INSERT OR IGNORE INTO users (id, name, pass, role)
    VALUES (1, 'admin', '5f4dcc3b5aa765d61d8327deb882cf99', 'admin');
INSERT OR IGNORE INTO users (id, name, pass, role)
    VALUES (2, 'alice', 'ab4f63f9ac65152575886860dde480a1', 'user');
"""


def get_db():
    db = getattr(g, "_database", None)
    if db is None:
        os.makedirs(os.path.dirname(DATABASE), exist_ok=True)
        db = g._database = sqlite3.connect(DATABASE)
        db.row_factory = sqlite3.Row
        db.executescript(SCHEMA)
        db.commit()
    return db


@app.teardown_appcontext
def close_db(exc):
    db = getattr(g, "_database", None)
    if db is not None:
        db.close()


# --- Vuln 1: SQL injection via string concatenation ---
@app.route("/login", methods=["GET", "POST"])
def login():
    msg = ""
    if request.method == "POST":
        username = request.form.get("username", "")
        password = request.form.get("password", "")
        pw_hash = hashlib.md5(password.encode()).hexdigest()  # Vuln 2: bare MD5
        db = get_db()
        # INTENTIONAL SQL injection sink:
        query = f"SELECT * FROM users WHERE name='{username}' AND pass='{pw_hash}'"
        try:
            row = db.execute(query).fetchone()
        except Exception as e:
            # Vuln 3: leaky error page (exposes stack trace + query)
            return f"<pre>ERROR: {e}\nQuery: {query}</pre>", 500
        if row:
            msg = f"Welcome, {row['name']} (role={row['role']})"
        else:
            msg = "Invalid credentials."
    return render_template_string("""
    <h2>Login</h2>
    <form method=post>
      Username: <input name=username><br>
      Password: <input name=password type=password><br>
      <input type=submit value=Login>
    </form>
    <p>{{ msg }}</p>
    <p><a href='/greet'>Greet page (SSTI demo)</a></p>
    """, msg=msg)


# --- Vuln 4: Server-side template injection via render_template_string ---
@app.route("/greet")
def greet():
    name = request.args.get("name", "World")
    # INTENTIONAL SSTI: user input rendered as a Jinja2 template
    template = f"<h1>Hello, {name}!</h1><p><a href='/login'>Back</a></p>"
    return render_template_string(template)


@app.route("/")
def index():
    return """
    <h1>Chapter 7 Lab: Deliberately Vulnerable Flask App</h1>
    <p>This app is the Chapter 3 reference target used for STRIDE threat modelling.</p>
    <ul>
      <li><a href="/login">Login (SQL injection + weak hash)</a></li>
      <li><a href="/greet?name=World">Greet (SSTI)</a></li>
    </ul>
    <p><em>FOR EDUCATIONAL USE ONLY -- do not expose to the internet.</em></p>
    """


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)
