|
1 | | -from fastapi import APIRouter, Depends, HTTPException, Form |
2 | | -from passlib.hash import bcrypt |
| 1 | +# app/routers/users.py (or your existing users router) |
| 2 | +from fastapi import APIRouter, Depends, HTTPException |
3 | 3 | from sqlalchemy.orm import Session |
4 | 4 | from app.database import get_db |
5 | 5 | from app.models.user import User |
| 6 | +from app.utils.auth import hash_password, generate_otp, otp_expiry, send_otp_email |
| 7 | +from datetime import datetime |
6 | 8 |
|
7 | | -# ✅ Define router (this line is crucial) |
8 | 9 | router = APIRouter() |
9 | 10 |
|
10 | | -# ✅ Create a new user |
11 | 11 | @router.post("/") |
12 | 12 | def create_user( |
13 | | - name: str = Form(...), |
14 | | - email: str = Form(...), |
15 | | - password: str = Form(...), |
16 | | - department: str = Form(None), |
17 | | - role: str = Form("auditee"), |
18 | | - manager_email: str = Form(None), |
| 13 | + name: str, |
| 14 | + email: str, |
| 15 | + password: str, |
| 16 | + department: str = None, |
| 17 | + manager_email: str = None, |
| 18 | + role: str = "auditee", |
19 | 19 | db: Session = Depends(get_db), |
20 | 20 | ): |
| 21 | + # check exist |
| 22 | + if db.query(User).filter(User.email == email).first(): |
| 23 | + raise HTTPException(status_code=400, detail="Email already registered") |
| 24 | + |
| 25 | + hashed = hash_password(password) |
| 26 | + otp = generate_otp() |
| 27 | + expiry = otp_expiry(10) |
| 28 | + |
| 29 | + user = User( |
| 30 | + name=name, |
| 31 | + email=email, |
| 32 | + password=hashed, |
| 33 | + department=department, |
| 34 | + manager_email=manager_email, |
| 35 | + role=role, |
| 36 | + otp_code=otp, |
| 37 | + otp_expires_at=expiry, |
| 38 | + first_login=True, |
| 39 | + ) |
| 40 | + db.add(user) |
| 41 | + db.commit() |
| 42 | + db.refresh(user) |
| 43 | + |
| 44 | + # send mail (async if you prefer background task) |
21 | 45 | try: |
22 | | - if db.query(User).filter(User.email == email).first(): |
23 | | - raise HTTPException(status_code=400, detail="Email already exists") |
24 | | - user = User( |
25 | | - name=name, |
26 | | - email=email, |
27 | | - hashed_password=bcrypt.hash(password), |
28 | | - department=department, |
29 | | - role=role, |
30 | | - manager_email=manager_email, |
31 | | - ) |
32 | | - db.add(user) |
33 | | - db.commit() |
34 | | - return {"ok": True, "message": "User created successfully"} |
| 46 | + send_otp_email(email, otp) |
35 | 47 | except Exception as e: |
36 | | - return {"ok": False, "error": str(e)} |
| 48 | + # log error but user exists now — you can rollback if you prefer |
| 49 | + print("Warning: failed to send OTP", e) |
37 | 50 |
|
38 | | -# ✅ Login route |
39 | | -@router.post("/login") |
40 | | -def login_user( |
41 | | - email: str = Form(...), |
42 | | - password: str = Form(...), |
43 | | - db: Session = Depends(get_db) |
44 | | -): |
45 | | - try: |
46 | | - user = db.query(User).filter(User.email == email).first() |
47 | | - if not user or not bcrypt.verify(password, user.hashed_password): |
48 | | - raise HTTPException(status_code=401, detail="Invalid email or password") |
49 | | - return { |
50 | | - "ok": True, |
51 | | - "message": "Login successful", |
52 | | - "user": {"id": user.id, "name": user.name, "role": user.role}, |
53 | | - } |
54 | | - except Exception as e: |
55 | | - return {"ok": False, "error": str(e)} |
56 | | - |
57 | | -# ✅ Get all users |
58 | | -@router.get("/") |
59 | | -def list_users(db: Session = Depends(get_db)): |
60 | | - try: |
61 | | - return db.query(User).all() |
62 | | - except Exception as e: |
63 | | - return {"ok": False, "error": str(e)} |
64 | | - |
65 | | -# ✅ Delete user |
66 | | -@router.delete("/{user_id}") |
67 | | -def delete_user(user_id: int, db: Session = Depends(get_db)): |
68 | | - try: |
69 | | - user = db.get(User, user_id) |
70 | | - if not user: |
71 | | - raise HTTPException(status_code=404, detail="User not found") |
72 | | - db.delete(user) |
73 | | - db.commit() |
74 | | - return {"ok": True, "message": "User deleted"} |
75 | | - except Exception as e: |
76 | | - return {"ok": False, "error": str(e)} |
77 | | - |
78 | | -# ✅ Check Admin Users |
79 | | -@router.get("/check-admin") |
80 | | -def check_admin(db: Session = Depends(get_db)): |
81 | | - try: |
82 | | - users = db.query(User).all() |
83 | | - return {"count": len(users), "users": [u.email for u in users]} |
84 | | - except Exception as e: |
85 | | - return {"ok": False, "error": str(e)} |
86 | | - |
87 | | -# ✅ Seed Admin User (One-Time Setup) – FIXED bcrypt byte issue |
88 | | -@router.post("/seed-admin") |
89 | | -def seed_admin(db: Session = Depends(get_db)): |
90 | | - try: |
91 | | - |
92 | | - existing = db.query(User).filter(User.email == email).first() |
93 | | - if existing: |
94 | | - return {"ok": True, "note": "Admin already exists"} |
95 | | - |
96 | | - # --- Fix bcrypt 72-byte password limit --- |
97 | | - raw_password = "Edme@123" |
98 | | - encoded = raw_password.encode("utf-8") |
99 | | - if len(encoded) > 72: |
100 | | - encoded = encoded[:72] |
101 | | - safe_password = encoded.decode("utf-8", "ignore") |
102 | | - hashed_password = bcrypt.hash(safe_password) |
103 | | - # ------------------------------------------ |
104 | | - |
105 | | - admin = User( |
106 | | - name="Admin", |
107 | | - email=email, |
108 | | - hashed_password=hashed_password, |
109 | | - department="Finance", |
110 | | - role="admin", |
111 | | - manager_email=None, |
112 | | - ) |
113 | | - db.add(admin) |
114 | | - db.commit() |
115 | | - return {"ok": True, "note": "Admin created successfully"} |
116 | | - except Exception as e: |
117 | | - return {"ok": False, "error": str(e)} |
| 51 | + return {"ok": True, "message": "User created and OTP sent"} |
0 commit comments