Abineshkumar commited on
Commit
51ac0e6
·
1 Parent(s): f9f6e70

Add application file

Browse files
Dockerfile ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Read the doc: https://huggingface.co/docs/hub/spaces-sdks-docker
2
+ # you will also find guides on how best to write your Dockerfile
3
+
4
+ FROM python:3.9
5
+
6
+ RUN useradd -m -u 1000 user
7
+ USER user
8
+ ENV PATH="/home/user/.local/bin:$PATH"
9
+
10
+ WORKDIR /app
11
+
12
+ COPY --chown=user ./requirements.txt requirements.txt
13
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
14
+
15
+ COPY --chown=user . /app
16
+ CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
README.md CHANGED
@@ -1,11 +1,10 @@
1
  ---
2
- title: Age Better
3
- emoji: 📈
4
- colorFrom: indigo
5
- colorTo: gray
6
  sdk: docker
7
  pinned: false
8
- license: apache-2.0
9
  ---
10
 
11
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: Age Better Endpoints
3
+ emoji: 👀
4
+ colorFrom: red
5
+ colorTo: blue
6
  sdk: docker
7
  pinned: false
 
8
  ---
9
 
10
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
__pycache__/config.cpython-310.pyc ADDED
Binary file (547 Bytes). View file
 
__pycache__/main.cpython-310.pyc ADDED
Binary file (443 Bytes). View file
 
auth/__init__.py ADDED
File without changes
auth/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (132 Bytes). View file
 
auth/__pycache__/auth_bearer.cpython-310.pyc ADDED
Binary file (1.27 kB). View file
 
auth/__pycache__/auth_handler.cpython-310.pyc ADDED
Binary file (1.22 kB). View file
 
auth/auth_bearer.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import Request, HTTPException
2
+ from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
3
+ from .auth_handler import decodeJWT
4
+
5
+ class JWTBearer(HTTPBearer):
6
+ """Class to validate JWT tokens on protected routes."""
7
+ async def __call__(self, request: Request):
8
+ credentials: HTTPAuthorizationCredentials = await super(JWTBearer, self).__call__(request)
9
+ if credentials:
10
+ if not credentials.scheme == "Bearer":
11
+ raise HTTPException(status_code=403, detail="Invalid authentication scheme.")
12
+ if not self.verify_jwt(credentials.credentials):
13
+ raise HTTPException(status_code=403, detail="Invalid token or expired token.")
14
+ return credentials.credentials
15
+ else:
16
+ raise HTTPException(status_code=403, detail="Invalid authorization code.")
17
+
18
+ def verify_jwt(self, jwtoken: str) -> bool:
19
+ is_token_valid: bool = False
20
+ try:
21
+ payload = decodeJWT(jwtoken)
22
+ except:
23
+ payload = None
24
+ if payload:
25
+ is_token_valid = True
26
+ return is_token_valid
auth/auth_handler.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import time
2
+ import jwt
3
+ from typing import Dict
4
+ from decouple import config
5
+
6
+ # Load secret and algorithm from environment variables
7
+ JWT_SECRET = config("SECRET_KEY") # Example: from .env file or environment variable
8
+ JWT_ALGORITHM = config("ALGORITHM", default="HS256") # Default to HS256 if not set
9
+
10
+ def token_response(token: str) -> Dict[str, str]:
11
+ return {
12
+ "access_token": token
13
+ }
14
+
15
+ def signJWT(user_id: str) -> Dict[str, str]:
16
+ """Sign a JWT for the user."""
17
+ payload = {
18
+ "user_id": user_id,
19
+ "expires": time.time() + 600 # 10-minute expiration
20
+ }
21
+ token = jwt.encode(payload, JWT_SECRET, algorithm=JWT_ALGORITHM)
22
+ return token_response(token)
23
+
24
+ def decodeJWT(token: str) -> dict:
25
+ """Decode a JWT token."""
26
+ try:
27
+ decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
28
+ return decoded_token if decoded_token["expires"] >= time.time() else None
29
+ except:
30
+ return {}
31
+
32
+ def decodeJWT(token: str) -> dict:
33
+ try:
34
+ # Decode JWT to get payload containing user_id
35
+ decoded_token = jwt.decode(token, JWT_SECRET, algorithms=[JWT_ALGORITHM])
36
+ # Ensure token has not expired
37
+ return decoded_token if decoded_token["expires"] >= time.time() else None
38
+ except:
39
+ return {}
config.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import firebase_admin
2
+ from firebase_admin import credentials, firestore, auth
3
+ import os
4
+ from decouple import config
5
+
6
+ FIREBASE_API_KEY = os.getenv("AIzaSyDCu6_7nNK63tkX1EONVz3ndIVd6frcy9Y") # Set this environment variable with your Firebase API key
7
+
8
+ if not firebase_admin._apps:
9
+ cred = credentials.Certificate("serviceAccountKey.json") # Path to Firebase Admin SDK JSON file
10
+ firebase_admin.initialize_app(cred)
11
+
12
+ db = firestore.client()
13
+
14
+ # JWT config
15
+ SECRET_KEY = config("SECRET_KEY")
16
+ ALGORITHM = config("ALGORITHM", default="HS256")
main.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from routes import users
3
+
4
+ app = FastAPI()
5
+
6
+ # Register the user routes
7
+ app.include_router(users.router)
8
+
9
+ @app.get("/")
10
+ def read_root():
11
+ return {"message": "User Management System with JWT and Firebase is running"}
models/__pycache__/user_model.cpython-310.pyc ADDED
Binary file (2.82 kB). View file
 
models/user_model.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, EmailStr
2
+
3
+ class User(BaseModel):
4
+ id: str
5
+ name: str
6
+ surname: str
7
+ phone: str
8
+ email: EmailStr
9
+ role: str
10
+ status: str
11
+
12
+ class CreateUser(BaseModel):
13
+ email: EmailStr
14
+ password: str
15
+
16
+ class UpdateUser(BaseModel):
17
+ name: str = None
18
+ surname: str = None
19
+ phone: str = None
20
+ email: EmailStr = None
21
+ role: str = None
22
+ status: str = None
23
+
24
+ class OTPVerification(BaseModel):
25
+ email: EmailStr
26
+ otp: str
27
+
28
+ class ResetPassword(BaseModel):
29
+ email: EmailStr
30
+ newPassword: str
31
+
32
+ class ChangePassword(BaseModel):
33
+ currentPassword: str
34
+ newPassword: str
35
+
36
+ class DeleteUserRequest(BaseModel):
37
+ password: str
38
+
39
+ class TokenRequest(BaseModel):
40
+ email: EmailStr
41
+
42
+ class UserProfileData(BaseModel):
43
+ id: str
44
+ name: str
45
+ surname: str
46
+ phone: str
47
+ email: str
48
+ role: str
49
+ status: str
50
+
51
+ class UserProfileResponse(BaseModel):
52
+ isSuccess: bool
53
+ data: UserProfileData
54
+
55
+ class CreateUser(BaseModel):
56
+ email: EmailStr
57
+ password: str
58
+
59
+ class TokenRequest(BaseModel):
60
+ email: EmailStr
61
+ password: str
62
+
63
+ class DeleteUserRequest(BaseModel):
64
+ password: str
65
+
66
+ class UpdateProfile(BaseModel):
67
+ name: str = None
68
+ surname: str = None
69
+
70
+ class Config:
71
+ schema_extra = {
72
+ "example": {
73
+ "name": "John",
74
+ "surname": "Doe"
75
+ }
76
+ }
requirements.txt ADDED
@@ -0,0 +1,14 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ firebase-admin
2
+ fastapi
3
+ uvicorn
4
+ sqlmodel
5
+ typer
6
+ dynaconf
7
+ jinja2
8
+ python-jose[cryptography]
9
+ passlib[bcrypt]
10
+ python-multipart
11
+ psycopg2-binary
12
+ uuid
13
+ pydantic
14
+ email-validator
routes/__init__.py ADDED
File without changes
routes/__pycache__/__init__.cpython-310.pyc ADDED
Binary file (142 Bytes). View file
 
routes/__pycache__/users.cpython-310.pyc ADDED
Binary file (2.42 kB). View file
 
routes/users.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Header, Query, Depends,Body
2
+ from services.users_service import create_user_in_firestore, get_user_from_firestore, update_user_in_firestore,login_for_access_token, delete_user_profile, get_user_profile_from_firestore,update_user_profile
3
+ from models.user_model import CreateUser, UpdateUser, TokenRequest,DeleteUserRequest,UpdateProfile
4
+ from datetime import timedelta
5
+ from firebase_admin import credentials, auth, firestore
6
+ from config import db
7
+ from auth.auth_bearer import JWTBearer
8
+ from auth.auth_handler import decodeJWT
9
+
10
+ router = APIRouter(
11
+ prefix="/api/v1/users",
12
+ tags=["Users"]
13
+ )
14
+
15
+ @router.post("")
16
+ def create_user(user_data: CreateUser):
17
+ """Route for creating a new user."""
18
+ return create_user_in_firestore(user_data.model_dump())
19
+
20
+ @router.get("/{id}")
21
+ def get_user(id: str):
22
+ return get_user_from_firestore(id)
23
+
24
+ @router.put("/{id}")
25
+ def edit_user(id: str, user_data: UpdateUser):
26
+ return update_user_in_firestore(id, user_data.model_dump())
27
+
28
+ @router.post("/login")
29
+ def login(user_data: TokenRequest):
30
+ """Login route for generating JWT token."""
31
+ return login_for_access_token(user_data.email, user_data.password)
32
+
33
+ @router.delete("/me", dependencies=[Depends(JWTBearer())])
34
+ def delete_user(user_request: DeleteUserRequest, token: str = Depends(JWTBearer())):
35
+ # Decode the token to get the user_id
36
+ user_id = decodeJWT(token)["user_id"]
37
+
38
+ # Call the delete function with the user_id
39
+ return delete_user_profile(user_id, user_request.model_dump())
40
+
41
+ @router.get("/me", dependencies=[Depends(JWTBearer())])
42
+ def get_my_profile(token: str = Depends(JWTBearer())):
43
+ # Decode the JWT token to get the user_id
44
+ user_id = decodeJWT(token)["user_id"]
45
+
46
+ # Fetch the user profile based on the user_id
47
+ return get_user_profile_from_firestore(user_id)
48
+
49
+ @router.put("/me", dependencies=[Depends(JWTBearer())])
50
+ def edit_my_profile(user_data: UpdateProfile = Body(...), token: str = Depends(JWTBearer())):
51
+ # Decode JWT to get the user_id
52
+ user_id = decodeJWT(token)["user_id"]
53
+
54
+ # Update the user profile in Firestore
55
+ updated_user = update_user_profile(user_id, user_data.model_dump())
56
+
57
+ return {
58
+ "isSuccess": True,
59
+ "data": updated_user
60
+ }
serviceAccountKey.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "news-b7cae",
4
+ "private_key_id": "3393fd91e87ef8353deb8d226159d46c0d314f6a",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDE7EL16g7NlpOK\n3Kcb+NixuMg/wwqJaKWZ1ts6iyt3l2Gn/I35it9bA+ocLsgE+JH+mHJdlt0e+/zv\nm40zQ8G432nZaTujq0BLMQH70qVFPxyeUZFCbw2OapNSPOcMBo1DgxG4JHMM74N8\nxUn5AOniP7yd+4ZlMkKk1q7vsO857okYqm4NajBsdV7EzV+XiS0J1ZbGvT2qRcYo\nXyUQwxX4NdxIzzT4wtajsMky8XewZzrOe5/IMRVEQE2ad13s/Lc9hoRKdD40XbuF\nw7uipgRO6UVLDb5+DGFXk9qP7oADjWDg5monZJ/4XLwDuFh/qdQZgn4XrI1abPAe\nRRlvva0XAgMBAAECggEARhbJZnmeNzJm5T/QAra5edgI/hjPgUTL3EuKz/WEzRYG\nXiIX7j+ta9mi09EaxBos7G8aFZGCtmp+BlJZGWv+YWyzYfyAi6qCQcD5scWxqUnj\nR75Ec17PdmccdGLU4YTbdrIJ9n6SrIH7TMdzorreg/anjZtepFoVOlJnBUz2eKl7\n3NyDykBtH++iFp2adwza0ZIpHIUCAp0VBNZjQbRH7WeKU8QS1Kfd1Mt1mzx9gsdR\nKXWgmZ5mD1xMjk0kwIEdyO4jVM+PCHTDeRGSRjtE8yVaIU1j0Rrhe+amEtu7aKHI\n0Tc0/ZDQBYKZMZhMdXniCZz3s8Fl8TPugaDko4ZBIQKBgQDveQ8aYpYft9jt7VXQ\nVG6b0X6/jVrF5zgGV84d20wyNSkrBRYL6UaTxGRccLEh+U1G5uIh27QA+xuliu7X\nVgIxdcwD31CvzHVusjpAXQwTg213dw2TVk1j7c1fBYT80kwlddQbnqq3yNjfg+8u\nA3tYWrBTlVUV0tk1jsTee+g2SQKBgQDSg3Dpqdw3KFJnbCh2eULj8awWCXHvw/EQ\nonTjNdIYUCYA4kiu7I5BMmLaY+NkMCrJ8z8JSoKocv9XwwqtHY3S/7kjTBeYajFD\nCd+IIvg5SlPzgjicbrlSBVqOUCjeFRSGyGExIofBnciqhHd354Ma4vuuOMEGz54X\nnEKi5uVIXwKBgEff186dhF1kurE+qKDsln4h9J7deD8p1MDinbSMW2Q+XGrTDfjp\nPQugyFaOZDvELZN4PKrY3D/nHjcjaegromDh8CfBYOBCx4Q/7gffZX591d8jVmnA\nX138w8UfTPjszXn40X6wsqCSobUETkdLODwejAmqKm1waU0P2rrECcAxAoGAMFlX\n+ZK1rUVph69jq7I2FrxO1dDdhj/uge+OARE/a64czF8samCSW48C/T2r4Drf2Pox\nJCUk1SN0WefF7/S1uhxZnS3AzZS2M7t0x4OglyfnGCp0bhlQHvJz1fO7LyaQTFSB\nXhOcMm/WwrMh7TwS9H3laCJI0xOkL7AH7fox9ukCgYBYGQkfPZUFo5grN+i9Z886\njSqODEhvnafLkiyr2nlSh/ZwL6nV0l9s77DBL9XVbGVCEPvCyn5XYJHwrn6B6JTZ\nOrPTmtJH+xQO4d3+MykoIjHNe4LUKKwGOESzSG0BzIFWrpkBe/2yEvIs/jlL6TLy\n6rQ3t9/+eYwMExTenGZGzQ==\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "firebase-adminsdk-cxdji@news-b7cae.iam.gserviceaccount.com",
7
+ "client_id": "103570192779780992565",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-cxdji%40news-b7cae.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
services/1.txt ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import HTTPException
2
+ from config import db, auth
3
+ from datetime import datetime, timedelta
4
+ from zoneinfo import ZoneInfo
5
+ import jwt
6
+
7
+ SECRET_KEY = "your_jwt_secret_key"
8
+
9
+ def create_user_in_firestore(user_data):
10
+ try:
11
+ user = auth.create_user(
12
+ email=user_data["email"],
13
+ password=user_data["password"]
14
+ )
15
+
16
+ user_ref = db.collection("users").document(user.uid)
17
+ user_ref.set({
18
+ "uid": user.uid,
19
+ "email": user_data["email"],
20
+ "status": "Active"
21
+ })
22
+
23
+ return {"isSuccess": True, "message": "User created successfully", "uid": user.uid}
24
+
25
+ except Exception as e:
26
+ raise HTTPException(status_code=400, detail=str(e))
27
+
28
+
29
+ def get_user_from_firestore(user_id: str):
30
+ try:
31
+ user_ref = db.collection("users").document(user_id)
32
+ user_snapshot = user_ref.get()
33
+
34
+ if user_snapshot.exists:
35
+ return {"isSuccess": True, "data": user_snapshot.to_dict()}
36
+ else:
37
+ raise HTTPException(status_code=404, detail="User not found")
38
+ except Exception as e:
39
+ raise HTTPException(status_code=500, detail=str(e))
40
+
41
+
42
+ def update_user_in_firestore(user_id: str, update_data):
43
+ try:
44
+ user_ref = db.collection("users").document(user_id)
45
+ user_ref.update(update_data)
46
+
47
+ if 'email' in update_data:
48
+ auth.update_user(user_id, email=update_data['email'])
49
+ if 'password' in update_data:
50
+ auth.update_user(user_id, password=update_data['password'])
51
+
52
+ return {"isSuccess": True, "message": "User updated successfully"}
53
+ except Exception as e:
54
+ raise HTTPException(status_code=400, detail=str(e))
55
+
56
+
57
+ def get_temporary_token_service(email: str):
58
+ try:
59
+ # Check if the user exists in Firestore
60
+ users_ref = db.collection("users")
61
+ query = users_ref.where("email", "==", email).stream()
62
+
63
+ user_doc = None
64
+ for doc in query:
65
+ user_doc = doc
66
+ break
67
+
68
+ if not user_doc:
69
+ raise HTTPException(status_code=404, detail="Use a registered email")
70
+
71
+ # Generate a temporary token valid for 300 seconds (5 minutes)
72
+ expiration = datetime.now(ZoneInfo("UTC")) + timedelta(seconds=300)
73
+ payload = {
74
+ "email": email,
75
+ "exp": expiration,
76
+ "uid": user_doc.id
77
+ }
78
+ token = jwt.encode(payload, SECRET_KEY, algorithm="HS256") # Ensure you use PyJWT's jwt
79
+
80
+ return {"isSuccess": True, "token": token}
81
+
82
+ except Exception as e:
83
+ raise HTTPException(status_code=500, detail=str(e))
84
+
85
+ # def get_user_profile_from_token(token: str):
86
+ # try:
87
+ # # Decode the token
88
+ # payload = jwt.decode(token, SECRET_KEY, algorithms=["HS256"])
89
+ # email = payload.get("email")
90
+
91
+ # if not email:
92
+ # raise HTTPException(status_code=401, detail="Invalid token")
93
+
94
+ # # Fetch user details from Firestore
95
+ # users_ref = db.collection("users")
96
+ # query = users_ref.where("email", "==", email).stream()
97
+
98
+ # user_doc = None
99
+ # for doc in query:
100
+ # user_doc = doc
101
+ # break
102
+
103
+ # if not user_doc:
104
+ # raise HTTPException(status_code=404, detail="User not found")
105
+
106
+ # return {"isSuccess": True, "data": user_doc.to_dict()}
107
+
108
+ # except jwt.ExpiredSignatureError:
109
+ # raise HTTPException(status_code=401, detail="Token has expired")
110
+ # except jwt.InvalidTokenError:
111
+ # raise HTTPException(status_code=401, detail="Invalid token")
112
+ # except Exception as e:
113
+ # raise HTTPException(status_code=500, detail=str(e))
114
+
115
+ from fastapi import APIRouter, HTTPException, Header, Query
116
+ from pydantic import EmailStr
117
+ from services.users_service import create_user_in_firestore, get_user_from_firestore, update_user_in_firestore, get_temporary_token_service
118
+ from models.user_model import CreateUser, UpdateUser, TokenRequest
119
+
120
+ router = APIRouter(
121
+ prefix="/api/v1/users",
122
+ tags=["Users"]
123
+ )
124
+
125
+ @router.post("/")
126
+ def create_user(user_data: CreateUser):
127
+ return create_user_in_firestore(user_data.model_dump())
128
+
129
+ @router.get("/{id}")
130
+ def get_user(id: str):
131
+ return get_user_from_firestore(id)
132
+
133
+ @router.put("/{id}")
134
+ def edit_user(id: str, user_data: UpdateUser):
135
+ return update_user_in_firestore(id, user_data.model_dump())
136
+
137
+ @router.post("/token")
138
+ def get_temporary_token(token_request: TokenRequest):
139
+ return get_temporary_token_service(token_request.email)
140
+
141
+ # @router.post("/me")
142
+ # def get_my_profile(token_request: TokenRequest1):
143
+ # token = token_request.token
144
+ # return get_user_profile_from_token(token)
services/__pycache__/users_service.cpython-310.pyc ADDED
Binary file (3.88 kB). View file
 
services/users_service.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import HTTPException
2
+ from config import db, auth
3
+ from datetime import datetime, timedelta
4
+ from zoneinfo import ZoneInfo
5
+ from jose import JWTError, jwt
6
+ from firebase_admin import auth, firestore
7
+ from auth.auth_handler import signJWT
8
+
9
+ SECRET_KEY = "your-secret-key"
10
+ ALGORITHM = "HS256"
11
+ ACCESS_TOKEN_EXPIRE_MINUTES = 30
12
+
13
+ def get_user_from_firestore(user_id: str):
14
+ try:
15
+ user_ref = db.collection("users").document(user_id)
16
+ user_snapshot = user_ref.get()
17
+
18
+ if user_snapshot.exists:
19
+ return {"isSuccess": True, "data": user_snapshot.to_dict()}
20
+ else:
21
+ raise HTTPException(status_code=404, detail="User not found")
22
+ except Exception as e:
23
+ raise HTTPException(status_code=500, detail=str(e))
24
+
25
+ def update_user_in_firestore(user_id: str, update_data):
26
+ try:
27
+ user_ref = db.collection("users").document(user_id)
28
+ user_ref.update(update_data)
29
+
30
+ if 'email' in update_data:
31
+ auth.update_user(user_id, email=update_data['email'])
32
+ if 'password' in update_data:
33
+ auth.update_user(user_id, password=update_data['password'])
34
+
35
+ return {"isSuccess": True, "message": "User updated successfully"}
36
+ except Exception as e:
37
+ raise HTTPException(status_code=400, detail=str(e))
38
+
39
+ def create_user_in_firestore(user_data):
40
+ """Create user in Firebase Auth and Firestore."""
41
+ try:
42
+ user = auth.create_user(
43
+ email=user_data["email"],
44
+ password=user_data["password"]
45
+ )
46
+
47
+ user_ref = db.collection("users").document(user.uid)
48
+ user_ref.set({
49
+ "uid": user.uid,
50
+ "email": user_data["email"],
51
+ "status": "Active"
52
+ })
53
+
54
+ return {"isSuccess": True, "message": "User created successfully", "uid": user.uid}
55
+
56
+ except Exception as e:
57
+ raise HTTPException(status_code=400, detail=str(e))
58
+
59
+ def authenticate_user(email: str, password: str):
60
+ """Authenticate Firebase user."""
61
+ try:
62
+ # In Firebase, password verification is handled on the client side.
63
+ user = auth.get_user_by_email(email)
64
+ return user
65
+ except Exception as e:
66
+ raise HTTPException(status_code=400, detail="Invalid credentials")
67
+
68
+ def login_for_access_token(email: str, password: str):
69
+ """Verify user and return JWT token."""
70
+ user = authenticate_user(email, password)
71
+ if not user:
72
+ raise HTTPException(status_code=400, detail="Incorrect email or password")
73
+
74
+ # Generate JWT token for the user
75
+ return signJWT(user.uid)
76
+
77
+ def delete_user_profile(user_id: str, user_request: dict):
78
+ try:
79
+ # Retrieve the user's Firebase Auth record
80
+ user_record = auth.get_user(user_id)
81
+ if not user_record:
82
+ raise HTTPException(status_code=404, detail="User not found")
83
+
84
+ # Deleting the user from Firebase Auth
85
+ auth.delete_user(user_id)
86
+
87
+ # Deleting the user from Firestore
88
+ user_ref = db.collection("users").document(user_id)
89
+ user_snapshot = user_ref.get()
90
+
91
+ if user_snapshot.exists:
92
+ user_ref.delete()
93
+ return {"isSuccess": True, "message": "User deleted successfully"}
94
+ else:
95
+ raise HTTPException(status_code=404, detail="User not found in Firestore")
96
+
97
+ except Exception as e:
98
+ raise HTTPException(status_code=400, detail=str(e))
99
+
100
+ def get_user_profile_from_firestore(user_id: str):
101
+ try:
102
+ # Get the user's profile from Firestore
103
+ user_ref = db.collection("users").document(user_id)
104
+ user_snapshot = user_ref.get()
105
+
106
+ if user_snapshot.exists:
107
+ user_data = user_snapshot.to_dict()
108
+ return {
109
+ "isSuccess": True,
110
+ "data": {
111
+ "id": user_data.get("uid"),
112
+ "name": user_data.get("name"),
113
+ "surname": user_data.get("surname"),
114
+ "phone": user_data.get("phone"),
115
+ "email": user_data.get("email"),
116
+ "role": user_data.get("role"),
117
+ "status": user_data.get("status")
118
+ }
119
+ }
120
+ else:
121
+ raise HTTPException(status_code=404, detail="User profile not found in Firestore")
122
+
123
+ except Exception as e:
124
+ raise HTTPException(status_code=500, detail=str(e))
125
+
126
+ def update_user_profile(user_id: str, update_data: dict):
127
+ try:
128
+ # Access Firestore document for the user
129
+ user_ref = db.collection("users").document(user_id)
130
+ user_snapshot = user_ref.get()
131
+
132
+ # Check if user exists
133
+ if not user_snapshot.exists:
134
+ raise HTTPException(status_code=404, detail="User not found")
135
+
136
+ # Update the user profile with provided data
137
+ user_ref.update(update_data)
138
+
139
+ # Fetch updated user data from Firestore
140
+ updated_user = user_ref.get().to_dict()
141
+
142
+ return updated_user
143
+ except Exception as e:
144
+ raise HTTPException(status_code=500, detail=str(e))