AndreaNotes1 commited on
Commit
b0bc9fa
·
verified ·
1 Parent(s): 95fa610

Delete app.py

Browse files
Files changed (1) hide show
  1. app.py +0 -190
app.py DELETED
@@ -1,190 +0,0 @@
1
- """
2
- Flask REST API for Auth App
3
- Hosted on Hugging Face Spaces
4
- """
5
-
6
- from flask import Flask, request, jsonify
7
- from flask_cors import CORS
8
- from pymongo import MongoClient
9
- from pymongo.errors import DuplicateKeyError
10
- from werkzeug.security import generate_password_hash, check_password_hash
11
- import jwt
12
- import os
13
- import datetime
14
- from functools import wraps
15
- from dotenv import load_dotenv
16
- import logging
17
-
18
- load_dotenv()
19
-
20
- logging.basicConfig(level=logging.INFO)
21
- logger = logging.getLogger(__name__)
22
-
23
- app = Flask(__name__)
24
- CORS(app, origins="*", supports_credentials=True)
25
-
26
- # ── Config ────────────────────────────────────────────────────────────────────
27
- MONGO_URI = os.environ.get("MONGO_URI", "")
28
- JWT_SECRET = os.environ.get("JWT_SECRET", "change-me-in-production-please")
29
- JWT_EXPIRY = int(os.environ.get("JWT_EXPIRY_HOURS", 24))
30
- DB_NAME = os.environ.get("DB_NAME", "authapp")
31
-
32
- # ── DB connection (lazy) ──────────────────────────────────────────────────────
33
- _client = None
34
- _db = None
35
-
36
- def get_db():
37
- global _client, _db
38
- if _db is None:
39
- if not MONGO_URI:
40
- raise RuntimeError("MONGO_URI environment variable is not set.")
41
- _client = MongoClient(MONGO_URI, serverSelectionTimeoutMS=5000)
42
- _db = _client[DB_NAME]
43
- # Unique index on email
44
- _db.users.create_index("email", unique=True)
45
- logger.info("MongoDB connected.")
46
- return _db
47
-
48
-
49
- # ── JWT helpers ───────────────────────────────────────────────────────────────
50
- def create_token(user_id: str, email: str) -> str:
51
- payload = {
52
- "sub": str(user_id),
53
- "email": email,
54
- "iat": datetime.datetime.utcnow(),
55
- "exp": datetime.datetime.utcnow() + datetime.timedelta(hours=JWT_EXPIRY),
56
- }
57
- return jwt.encode(payload, JWT_SECRET, algorithm="HS256")
58
-
59
-
60
- def decode_token(token: str) -> dict:
61
- return jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
62
-
63
-
64
- def token_required(f):
65
- @wraps(f)
66
- def decorated(*args, **kwargs):
67
- auth_header = request.headers.get("Authorization", "")
68
- if not auth_header.startswith("Bearer "):
69
- return jsonify({"error": "Missing or invalid Authorization header"}), 401
70
- token = auth_header.split(" ", 1)[1]
71
- try:
72
- payload = decode_token(token)
73
- except jwt.ExpiredSignatureError:
74
- return jsonify({"error": "Token has expired"}), 401
75
- except jwt.InvalidTokenError as e:
76
- return jsonify({"error": f"Invalid token: {e}"}), 401
77
- request.user = payload
78
- return f(*args, **kwargs)
79
- return decorated
80
-
81
-
82
- # ── Health ────────────────────────────────────────────────────────────────────
83
- @app.route("/health", methods=["GET"])
84
- def health():
85
- try:
86
- db = get_db()
87
- db.command("ping")
88
- return jsonify({"status": "ok", "db": "connected"})
89
- except Exception as e:
90
- return jsonify({"status": "error", "detail": str(e)}), 503
91
-
92
-
93
- # ── Auth routes ───────────────────────────────────────────────────────────────
94
- @app.route("/api/signup", methods=["POST"])
95
- def signup():
96
- data = request.get_json(silent=True) or {}
97
- name = (data.get("name") or "").strip()
98
- email = (data.get("email") or "").strip().lower()
99
- password = (data.get("password") or "").strip()
100
-
101
- if not all([name, email, password]):
102
- return jsonify({"error": "name, email, and password are required"}), 400
103
- if len(password) < 8:
104
- return jsonify({"error": "Password must be at least 8 characters"}), 400
105
-
106
- db = get_db()
107
- user_doc = {
108
- "name": name,
109
- "email": email,
110
- "password_hash": generate_password_hash(password),
111
- "created_at": datetime.datetime.utcnow(),
112
- "last_login": None,
113
- }
114
- try:
115
- result = db.users.insert_one(user_doc)
116
- except DuplicateKeyError:
117
- return jsonify({"error": "An account with this email already exists"}), 409
118
-
119
- token = create_token(str(result.inserted_id), email)
120
- return jsonify({
121
- "message": "Account created successfully",
122
- "token": token,
123
- "user": {"id": str(result.inserted_id), "name": name, "email": email},
124
- }), 201
125
-
126
-
127
- @app.route("/api/login", methods=["POST"])
128
- def login():
129
- data = request.get_json(silent=True) or {}
130
- email = (data.get("email") or "").strip().lower()
131
- password = (data.get("password") or "").strip()
132
-
133
- if not all([email, password]):
134
- return jsonify({"error": "email and password are required"}), 400
135
-
136
- db = get_db()
137
- user = db.users.find_one({"email": email})
138
- if not user or not check_password_hash(user["password_hash"], password):
139
- return jsonify({"error": "Invalid email or password"}), 401
140
-
141
- db.users.update_one({"_id": user["_id"]}, {"$set": {"last_login": datetime.datetime.utcnow()}})
142
- token = create_token(str(user["_id"]), email)
143
- return jsonify({
144
- "message": "Login successful",
145
- "token": token,
146
- "user": {"id": str(user["_id"]), "name": user["name"], "email": email},
147
- })
148
-
149
-
150
- # ── Protected routes ──────────────────────────────────────────────────────────
151
- @app.route("/api/me", methods=["GET"])
152
- @token_required
153
- def me():
154
- from bson import ObjectId
155
- db = get_db()
156
- user = db.users.find_one({"_id": ObjectId(request.user["sub"])})
157
- if not user:
158
- return jsonify({"error": "User not found"}), 404
159
- return jsonify({
160
- "id": str(user["_id"]),
161
- "name": user["name"],
162
- "email": user["email"],
163
- "created_at": user["created_at"].isoformat(),
164
- "last_login": user["last_login"].isoformat() if user.get("last_login") else None,
165
- })
166
-
167
-
168
- @app.route("/api/dashboard/stats", methods=["GET"])
169
- @token_required
170
- def dashboard_stats():
171
- db = get_db()
172
- total = db.users.count_documents({})
173
- recent_cut = datetime.datetime.utcnow() - datetime.timedelta(days=7)
174
- recent = db.users.count_documents({"created_at": {"$gte": recent_cut}})
175
-
176
- from bson import ObjectId
177
- user = db.users.find_one({"_id": ObjectId(request.user["sub"])})
178
- member_days = (datetime.datetime.utcnow() - user["created_at"]).days if user else 0
179
-
180
- return jsonify({
181
- "total_users": total,
182
- "new_this_week": recent,
183
- "member_days": member_days,
184
- "active_sessions": 1, # placeholder – extend as needed
185
- })
186
-
187
-
188
- if __name__ == "__main__":
189
- port = int(os.environ.get("PORT", 7860)) # HF Spaces default
190
- app.run(host="0.0.0.0", port=port, debug=False)