Untitled
Anonymous
plain_text
09/02/2026 11:12 AM
13.2 KB
1
Indexable
import os
import sqlite3
import secrets
import hashlib
import hmac
from datetime import datetime, timezone, timedelta
from flask import (
Flask, request, jsonify, session,
redirect, render_template_string
)
app = Flask(__name__)
app.secret_key = os.environ.get(
"APP_SECRET",
secrets.token_hex(32)
)
DB = "device_info.sqlite3"
def get_db():
conn = sqlite3.connect(DB)
conn.row_factory = sqlite3.Row
return conn
def init_db():
conn = get_db()
conn.execute("""
CREATE TABLE IF NOT EXISTS sessions (
token TEXT PRIMARY KEY,
created_at TEXT NOT NULL,
expires_at TEXT NOT NULL,
consented INTEGER DEFAULT 0
)
""")
conn.execute("""
CREATE TABLE IF NOT EXISTS devices (
id INTEGER PRIMARY KEY AUTOINCREMENT,
token TEXT NOT NULL,
received_at TEXT NOT NULL,
platform TEXT,
os_version TEXT,
model TEXT,
manufacturer TEXT,
screen TEXT,
browser TEXT
)
""")
conn.commit()
conn.close()
def hash_password(password, salt=None):
salt = salt or secrets.token_bytes(16)
digest = hashlib.pbkdf2_hmac(
"sha256",
password.encode(),
salt,
310000
)
return salt.hex() + "$" + digest.hex()
def verify_password(password, stored):
try:
salt_hex, digest_hex = stored.split("$", 1)
salt = bytes.fromhex(salt_hex)
digest = hashlib.pbkdf2_hmac(
"sha256",
password.encode(),
salt,
310000
)
return hmac.compare_digest(
digest.hex(),
digest_hex
)
except Exception:
return False
@app.post("/api/admin/login")
def admin_login():
data = request.get_json() or {}
password = data.get("password", "")
stored_hash = os.environ.get(
"ADMIN_PASSWORD_HASH",
""
)
if not stored_hash:
return jsonify({
"error": "Admin password is not configured"
}), 500
if not verify_password(password, stored_hash):
return jsonify({
"error": "Invalid password"
}), 401
session["admin"] = True
return jsonify({
"success": True
})
@app.post("/api/admin/logout")
def logout():
session.clear()
return jsonify({
"success": True
})
@app.post("/api/sessions")
def create_session():
if not session.get("admin"):
return jsonify({
"error": "Unauthorized"
}), 401
token = secrets.token_urlsafe(32)
now = datetime.now(timezone.utc)
expires = now + timedelta(minutes=30)
conn = get_db()
conn.execute(
"""
INSERT INTO sessions
(token, created_at, expires_at, consented)
VALUES (?, ?, ?, 0)
""",
(
token,
now.isoformat(),
expires.isoformat()
)
)
conn.commit()
conn.close()
return jsonify({
"token": token,
"consent_url": f"/consent/{token}"
})
@app.get("/consent/<token>")
def consent_page(token):
conn = get_db()
row = conn.execute(
"SELECT * FROM sessions WHERE token=?",
(token,)
).fetchone()
conn.close()
if not row:
return "Invalid link", 404
expires = datetime.fromisoformat(
row["expires_at"]
)
if expires < datetime.now(timezone.utc):
return "This link has expired", 404
return render_template_string("""
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>Device Information Consent</title>
</head>
<body>
<h2>Device Information Sharing</h2>
<p>
No information will be sent without your permission.
</p>
<p>
If you agree, only the following basic information
will be shared:
</p>
<ul>
<li>Platform</li>
<li>Operating System</li>
<li>Device Model</li>
<li>Manufacturer</li>
<li>Screen Size</li>
<li>Browser Information</li>
</ul>
<button onclick="shareInfo()">
I Agree & Share
</button>
<p id="status"></p>
<script>
async function shareInfo() {
const ua = navigator.userAgent;
const data = {
platform:
navigator.platform || "unknown",
os_version:
(ua.match(/Android\\s([\\d.]+)/i) || [])[1]
|| "unknown",
model:
(ua.match(/;\\s*([^;)]+)\\s+Build\\//i) || [])[1]
|| "unknown",
manufacturer:
"browser-reported",
screen:
screen.width + "x" + screen.height,
browser:
ua
};
const response = await fetch(
"/api/consent/{{ token }}",
{
method: "POST",
headers: {
"Content-Type":
"application/json"
},
body:
JSON.stringify(data)
}
);
if (response.ok) {
document.getElementById("status")
.textContent =
"Information shared successfully.";
} else {
document.getElementById("status")
.textContent =
"Unable to share information.";
}
}
</script>
</body>
</html>
""", token=token)
@app.post("/api/consent/<token>")
def receive_device_info(token):
data = request.get_json() or {}
allowed_fields = [
"platform",
"os_version",
"model",
"manufacturer",
"screen",
"browser"
]
if not all(field in data for field in allowed_fields):
return jsonify({
"error": "Incomplete information"
}), 400
conn = get_db()
session_row = conn.execute(
"SELECT * FROM sessions WHERE token=?",
(token,)
).fetchone()
if not session_row:
conn.close()
return jsonify({
"error": "Invalid session"
}), 404
expires = datetime.fromisoformat(
session_row["expires_at"]
)
if expires < datetime.now(timezone.utc):
conn.close()
return jsonify({
"error": "Session expired"
}), 404
now = datetime.now(timezone.utc).isoformat()
conn.execute(
"""
UPDATE sessions
SET consented=1
WHERE token=?
""",
(token,)
)
conn.execute(
"""
INSERT INTO devices
(
token,
received_at,
platform,
os_version,
model,
manufacturer,
screen,
browser
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
""",
(
token,
now,
str(data["platform"])[:200],
str(data["os_version"])[:200],
str(data["model"])[:200],
str(data["manufacturer"])[:200],
str(data["screen"])[:200],
str(data["browser"])[:500]
)
)
conn.commit()
conn.close()
return jsonify({
"success": True
})
@app.get("/admin")
def dashboard():
if not session.get("admin"):
return redirect("/admin/login")
conn = get_db()
devices = conn.execute(
"""
SELECT *
FROM devices
ORDER BY id DESC
"""
).fetchall()
conn.close()
return render_template_string("""
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>Admin Dashboard</title>
</head>
<body>
<h2>Admin Dashboard</h2>
<button onclick="createLink()">
Create Consent Link
</button>
<button onclick="logout()">
Logout
</button>
<p id="link"></p>
<table border="1" cellpadding="8">
<tr>
<th>Time</th>
<th>Platform</th>
<th>OS</th>
<th>Model</th>
<th>Manufacturer</th>
<th>Screen</th>
<th>Browser</th>
</tr>
{% for d in devices %}
<tr>
<td>{{ d.received_at }}</td>
<td>{{ d.platform }}</td>
<td>{{ d.os_version }}</td>
<td>{{ d.model }}</td>
<td>{{ d.manufacturer }}</td>
<td>{{ d.screen }}</td>
<td>{{ d.browser }}</td>
</tr>
{% endfor %}
</table>
<script>
async function createLink() {
const response =
await fetch(
"/api/sessions",
{
method: "POST"
}
);
const data =
await response.json();
const url =
location.origin +
data.consent_url;
document.getElementById("link")
.innerHTML =
"<a href='" + url + "'>" +
url + "</a>";
}
async function logout() {
await fetch(
"/api/admin/logout",
{
method: "POST"
}
);
location =
"/admin/login";
}
</script>
</body>
</html>
""", devices=devices)
@app.get("/admin/login")
def login_page():
return render_template_string("""
<!DOCTYPE html>
<html>
<head>
<meta name="viewport"
content="width=device-width, initial-scale=1">
<title>Admin Login</title>
</head>
<body>
<h2>Admin Login</h2>
<input
id="password"
type="password"
placeholder="Admin Password"
>
<button onclick="login()">
Login
</button>
<p id="message"></p>
<script>
async function login() {
const password =
document.getElementById(
"password"
).value;
const response =
await fetch(
"/api/admin/login",
{
method: "POST",
headers: {
"Content-Type":
"application/json"
},
body:
JSON.stringify({
password: password
})
}
);
if (response.ok) {
location =
"/admin";
} else {
document.getElementById(
"message"
).textContent =
"Invalid password";
}
}
</script>
</body>
</html>
""")
if __name__ == "__main__":
init_db()
app.run(
host="127.0.0.1",
port=5000,
debug=False
)Editor is loading...
Leave a Comment