Ali2206 commited on
Commit
b29925a
·
verified ·
1 Parent(s): 2a875aa

Upload 11 files

Browse files
__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This makes this directory a Python package
api/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This makes this directory a Python package
api/routes.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import APIRouter, HTTPException, Depends
2
+ from fastapi.security import OAuth2PasswordRequestForm
3
+ from app.models.schemas import SignupForm, TokenResponse
4
+ from app.db.mongo import users_collection
5
+ from app.core.security import hash_password, verify_password, create_access_token
6
+ from datetime import datetime
7
+
8
+ router = APIRouter()
9
+
10
+ @router.post("/signup")
11
+ async def signup(data: SignupForm):
12
+ email = data.email.lower().strip()
13
+ existing = await users_collection.find_one({"email": email})
14
+ if existing:
15
+ raise HTTPException(status_code=409, detail="Email already exists")
16
+
17
+ hashed_pw = hash_password(data.password)
18
+ user_doc = {
19
+ "email": email,
20
+ "password": hashed_pw,
21
+ "created_at": datetime.utcnow()
22
+ }
23
+ await users_collection.insert_one(user_doc)
24
+ return {"success": True, "message": "Account created"}
25
+
26
+ @router.post("/login", response_model=TokenResponse)
27
+ async def login(form_data: OAuth2PasswordRequestForm = Depends()):
28
+ email = form_data.username.lower().strip()
29
+ user = await users_collection.find_one({"email": email})
30
+ if not user or not verify_password(form_data.password, user["password"]):
31
+ raise HTTPException(status_code=401, detail="Invalid credentials")
32
+
33
+ access_token = create_access_token(data={"sub": user["email"]})
34
+ return {"access_token": access_token, "token_type": "bearer"}
app.py ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI
2
+ from fastapi.middleware.cors import CORSMiddleware
3
+ from app.api.routes import router as api_router
4
+
5
+ app = FastAPI()
6
+
7
+ app.add_middleware(
8
+ CORSMiddleware,
9
+ allow_origins=["*"],
10
+ allow_credentials=True,
11
+ allow_methods=["*"],
12
+ allow_headers=["*"],
13
+ )
14
+
15
+ app.include_router(api_router)
16
+
17
+ @app.get("/")
18
+ def root():
19
+ return {"message": "🚀 FastAPI MongoDB with JWT & bcrypt is running"}
core/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This makes this directory a Python package
core/config.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ SECRET_KEY = os.getenv("SECRET_KEY", "your-secret-key")
4
+ ALGORITHM = "HS256"
5
+ ACCESS_TOKEN_EXPIRE_MINUTES = 30
6
+ MONGO_URI = os.getenv("MONGO_URI")
7
+
8
+ if not MONGO_URI:
9
+ raise RuntimeError("MONGO_URI not set!")
core/security.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from datetime import datetime, timedelta
2
+ from passlib.context import CryptContext
3
+ from jose import jwt
4
+ from app.core.config import SECRET_KEY, ALGORITHM, ACCESS_TOKEN_EXPIRE_MINUTES
5
+
6
+ pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
7
+
8
+ def hash_password(password: str) -> str:
9
+ return pwd_context.hash(password)
10
+
11
+ def verify_password(plain: str, hashed: str) -> bool:
12
+ return pwd_context.verify(plain, hashed)
13
+
14
+ def create_access_token(data: dict, expires_delta: timedelta = None):
15
+ to_encode = data.copy()
16
+ expire = datetime.utcnow() + (expires_delta or timedelta(minutes=ACCESS_TOKEN_EXPIRE_MINUTES))
17
+ to_encode.update({"exp": expire})
18
+ return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
db/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This makes this directory a Python package
db/mongo.py ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import certifi
2
+ from motor.motor_asyncio import AsyncIOMotorClient
3
+ from app.core.config import MONGO_URI
4
+
5
+ client = AsyncIOMotorClient(MONGO_URI, tls=True, tlsCAFile=certifi.where())
6
+ db = client["cps_db"]
7
+ users_collection = db["users"]
models/__init__.py ADDED
@@ -0,0 +1 @@
 
 
1
+ # This makes this directory a Python package
models/schemas.py ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ from pydantic import BaseModel, EmailStr
2
+
3
+ class SignupForm(BaseModel):
4
+ email: EmailStr
5
+ password: str
6
+
7
+ class TokenResponse(BaseModel):
8
+ access_token: str
9
+ token_type: str