img-processing / auth.py
harsh-dev's picture
Add application file
3ba5b62 unverified
Raw
History Blame Contribute Delete
2.25 kB
"""
Simple username + password authentication for DiffLens.
User credentials are stored in users.json next to this file:
{"users": {"alice": "$2b$12$..."}}
The hash is bcrypt. Sessions use Flask's signed cookie (SECRET_KEY must be
set in the environment for production).
"""
import json
import os
import secrets
from functools import wraps
import bcrypt
from flask import session, jsonify, request
USERS_FILE = os.path.join(os.path.dirname(__file__), "users.json")
def _load_users():
if not os.path.exists(USERS_FILE):
return {}
with open(USERS_FILE, "r") as f:
data = json.load(f) or {}
return data.get("users", {})
def _save_users(users):
with open(USERS_FILE, "w") as f:
json.dump({"users": users}, f, indent=2)
def hash_password(plain):
return bcrypt.hashpw(plain.encode("utf-8"), bcrypt.gensalt(12)).decode("ascii")
def verify_password(plain, hashed):
try:
return bcrypt.checkpw(plain.encode("utf-8"), hashed.encode("utf-8"))
except Exception:
return False
def create_user(username, password):
users = _load_users()
users[username] = hash_password(password)
_save_users(users)
def authenticate(username, password):
users = _load_users()
h = users.get(username)
if not h:
return False
return verify_password(password, h)
def get_secret_key():
"""Returns the Flask SECRET_KEY. Reads from env, falls back to a file
that's auto-generated on first run so the key persists across restarts."""
key = os.environ.get("DIFFLENS_SECRET_KEY")
if key:
return key
path = os.path.join(os.path.dirname(__file__), ".secret_key")
if os.path.exists(path):
with open(path, "r") as f:
return f.read().strip()
key = secrets.token_urlsafe(48)
with open(path, "w") as f:
f.write(key)
os.chmod(path, 0o600)
return key
def login_required(view):
"""Decorator that returns 401 for unauthenticated requests."""
@wraps(view)
def wrapper(*args, **kwargs):
if not session.get("user"):
return jsonify({"error": "unauthorized"}), 401
return view(*args, **kwargs)
return wrapper
def current_user():
return session.get("user")