Spaces:
Running
Running
Ved Gupta commited on
Commit ·
2f43b92
1
Parent(s): f4c6a6b
Schema added
Browse files- app/api/endpoints/users.py +14 -12
- app/api/models/transcribe.py +11 -0
- app/api/models/user.py +5 -15
- app/core/config.py +3 -3
- app/core/models/AuthToken.py +38 -0
- app/core/models/Transcribe.py +21 -0
- app/core/models/User.py +26 -0
- app/core/models/__init__.py +8 -0
- app/core/security.py +3 -1
- requirements.txt +2 -1
app/api/endpoints/users.py
CHANGED
|
@@ -1,8 +1,10 @@
|
|
| 1 |
-
from fastapi import APIRouter
|
|
|
|
| 2 |
|
| 3 |
-
from app.api.models.user import
|
| 4 |
from app.core.database import SessionLocal
|
| 5 |
from app.core.security import get_password_hash, verify_password
|
|
|
|
| 6 |
|
| 7 |
database = SessionLocal()
|
| 8 |
|
|
@@ -22,17 +24,17 @@ async def create_user(user: User):
|
|
| 22 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
| 23 |
|
| 24 |
|
| 25 |
-
@router.get("/{
|
| 26 |
-
async def read_user(
|
| 27 |
-
db_user = database.query(UserInDB).filter(UserInDB.id ==
|
| 28 |
if not db_user:
|
| 29 |
raise HTTPException(status_code=404, detail="User not found")
|
| 30 |
return UserResponse.from_orm(db_user)
|
| 31 |
|
| 32 |
|
| 33 |
-
@router.put("/{
|
| 34 |
-
async def update_user(
|
| 35 |
-
db_user =
|
| 36 |
if not db_user:
|
| 37 |
raise HTTPException(status_code=404, detail="User not found")
|
| 38 |
if not verify_password(user.current_password, db_user.hashed_password):
|
|
@@ -49,9 +51,9 @@ async def update_user(id: int, user: UpdateUser):
|
|
| 49 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
| 50 |
|
| 51 |
|
| 52 |
-
@router.delete("/{
|
| 53 |
-
async def delete_user(
|
| 54 |
-
db_user = database.query(UserInDB).filter(UserInDB.id ==
|
| 55 |
database.delete(db_user)
|
| 56 |
database.commit()
|
| 57 |
-
return
|
|
|
|
| 1 |
+
from fastapi import APIRouter, HTTPException
|
| 2 |
+
from uuid import UUID
|
| 3 |
|
| 4 |
+
from app.api.models.user import User, UpdateUser, UserResponse
|
| 5 |
from app.core.database import SessionLocal
|
| 6 |
from app.core.security import get_password_hash, verify_password
|
| 7 |
+
from app.core.models import UserInDB
|
| 8 |
|
| 9 |
database = SessionLocal()
|
| 10 |
|
|
|
|
| 24 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
| 25 |
|
| 26 |
|
| 27 |
+
@router.get("/{user_id}/", response_model=UserResponse)
|
| 28 |
+
async def read_user(user_id: UUID):
|
| 29 |
+
db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
|
| 30 |
if not db_user:
|
| 31 |
raise HTTPException(status_code=404, detail="User not found")
|
| 32 |
return UserResponse.from_orm(db_user)
|
| 33 |
|
| 34 |
|
| 35 |
+
@router.put("/{user_id}/", response_model=User)
|
| 36 |
+
async def update_user(user_id: UUID, user: UpdateUser):
|
| 37 |
+
db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
|
| 38 |
if not db_user:
|
| 39 |
raise HTTPException(status_code=404, detail="User not found")
|
| 40 |
if not verify_password(user.current_password, db_user.hashed_password):
|
|
|
|
| 51 |
return {**user.dict(), "id": db_user.id, "hashed_password": None}
|
| 52 |
|
| 53 |
|
| 54 |
+
@router.delete("/{user_id}/", response_model=int)
|
| 55 |
+
async def delete_user(user_id: UUID):
|
| 56 |
+
db_user = database.query(UserInDB).filter(UserInDB.id == user_id).first()
|
| 57 |
database.delete(db_user)
|
| 58 |
database.commit()
|
| 59 |
+
return user_id
|
app/api/models/transcribe.py
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import uuid
|
| 2 |
+
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from typing import Optional
|
| 5 |
+
|
| 6 |
+
from sqlalchemy.dialects.postgresql import UUID
|
| 7 |
+
|
| 8 |
+
from sqlalchemy import Column, Integer, String, Boolean, ForeignKey
|
| 9 |
+
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
| 10 |
+
|
| 11 |
+
from app.core.database import Base
|
app/api/models/user.py
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
|
|
|
|
|
| 1 |
from pydantic import BaseModel
|
| 2 |
from typing import Optional
|
| 3 |
|
|
|
|
| 4 |
from sqlalchemy import Column, Integer, String, Boolean
|
|
|
|
| 5 |
from app.core.database import Base
|
|
|
|
| 6 |
|
| 7 |
|
| 8 |
class UserBase(BaseModel):
|
|
@@ -27,18 +32,3 @@ class User(UserBase):
|
|
| 27 |
|
| 28 |
class UpdateUser(UserBase):
|
| 29 |
current_password: str
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
class UserInDB(Base):
|
| 33 |
-
__tablename__ = "users"
|
| 34 |
-
|
| 35 |
-
id = Column(Integer, primary_key=True, index=True, autoincrement=True)
|
| 36 |
-
username = Column(String, unique=True, index=True)
|
| 37 |
-
email = Column(String, unique=True, index=True)
|
| 38 |
-
hashed_password = Column(String)
|
| 39 |
-
is_active = Column(Boolean, default=True)
|
| 40 |
-
|
| 41 |
-
def __init__(self, username: str, email: str, hashed_password: str):
|
| 42 |
-
self.username = username
|
| 43 |
-
self.email = email
|
| 44 |
-
self.hashed_password = hashed_password
|
|
|
|
| 1 |
+
import uuid
|
| 2 |
+
|
| 3 |
from pydantic import BaseModel
|
| 4 |
from typing import Optional
|
| 5 |
|
| 6 |
+
from sqlalchemy.dialects.postgresql import UUID
|
| 7 |
from sqlalchemy import Column, Integer, String, Boolean
|
| 8 |
+
|
| 9 |
from app.core.database import Base
|
| 10 |
+
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
| 11 |
|
| 12 |
|
| 13 |
class UserBase(BaseModel):
|
|
|
|
| 32 |
|
| 33 |
class UpdateUser(UserBase):
|
| 34 |
current_password: str
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app/core/config.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
|
|
|
|
|
| 1 |
from typing import Any, Dict, List, Optional, Union
|
| 2 |
from pydantic import AnyHttpUrl, validator
|
| 3 |
|
| 4 |
-
from pydantic_settings import BaseSettings
|
| 5 |
-
|
| 6 |
-
from os import environ as env
|
| 7 |
|
| 8 |
|
| 9 |
class Settings(BaseSettings):
|
|
|
|
| 1 |
+
from os import environ as env
|
| 2 |
+
|
| 3 |
from typing import Any, Dict, List, Optional, Union
|
| 4 |
from pydantic import AnyHttpUrl, validator
|
| 5 |
|
| 6 |
+
from pydantic_settings import BaseSettings
|
|
|
|
|
|
|
| 7 |
|
| 8 |
|
| 9 |
class Settings(BaseSettings):
|
app/core/models/AuthToken.py
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timedelta
|
| 2 |
+
import uuid
|
| 3 |
+
import random
|
| 4 |
+
import string
|
| 5 |
+
|
| 6 |
+
from app.core.config import settings
|
| 7 |
+
|
| 8 |
+
from sqlalchemy.dialects.postgresql import UUID
|
| 9 |
+
from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
|
| 10 |
+
from sqlalchemy.sql import func
|
| 11 |
+
|
| 12 |
+
from app.core.database import Base, engine
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class AuthToken(Base):
|
| 16 |
+
__tablename__ = "auth_tokens"
|
| 17 |
+
|
| 18 |
+
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
| 19 |
+
token = Column(String, unique=True, index=True)
|
| 20 |
+
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
|
| 21 |
+
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
| 22 |
+
|
| 23 |
+
def __init__(self, user_id: UUID):
|
| 24 |
+
self.user_id = user_id
|
| 25 |
+
self.token = self.create_token()
|
| 26 |
+
|
| 27 |
+
def create_token(self):
|
| 28 |
+
token = self.generate_bearer_token()
|
| 29 |
+
return token
|
| 30 |
+
|
| 31 |
+
def generate_bearer_token(self):
|
| 32 |
+
token_prefix = str(self.id).replace("-", "") # Remove hyphens from UUID
|
| 33 |
+
token_suffix = str(uuid.uuid4().hex) # Generate a random UUID string
|
| 34 |
+
return f"{token_prefix}{token_suffix}"
|
| 35 |
+
|
| 36 |
+
@staticmethod
|
| 37 |
+
def validate_bearer_token(request_token):
|
| 38 |
+
...
|
app/core/models/Transcribe.py
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from datetime import datetime, timedelta
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
import uuid
|
| 5 |
+
from app.core.config import settings
|
| 6 |
+
|
| 7 |
+
from sqlalchemy.dialects.postgresql import UUID
|
| 8 |
+
from sqlalchemy import Column, String, Boolean, ForeignKey, DateTime
|
| 9 |
+
from sqlalchemy.orm import Mapped, mapped_column, relationship
|
| 10 |
+
from sqlalchemy.sql import func
|
| 11 |
+
|
| 12 |
+
from app.core.database import Base, engine
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
class TranscibeInDB(Base):
|
| 16 |
+
__tablename__ = "transcribe_data"
|
| 17 |
+
|
| 18 |
+
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
| 19 |
+
text = Column(String)
|
| 20 |
+
user_id = Column(UUID(as_uuid=True), ForeignKey("users.id"))
|
| 21 |
+
user = relationship("UserInDB", back_populates="transcribes")
|
app/core/models/User.py
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import uuid
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
from app.core.config import settings
|
| 5 |
+
|
| 6 |
+
from sqlalchemy.dialects.postgresql import UUID
|
| 7 |
+
from sqlalchemy import Column, String, Boolean
|
| 8 |
+
from sqlalchemy.orm import relationship
|
| 9 |
+
|
| 10 |
+
from app.core.database import Base, engine
|
| 11 |
+
|
| 12 |
+
|
| 13 |
+
class UserInDB(Base):
|
| 14 |
+
__tablename__ = "users"
|
| 15 |
+
|
| 16 |
+
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
| 17 |
+
username = Column(String, unique=True, index=True)
|
| 18 |
+
email = Column(String, unique=True, index=True)
|
| 19 |
+
hashed_password = Column(String)
|
| 20 |
+
is_active = Column(Boolean, default=True)
|
| 21 |
+
transcribes = relationship("TranscibeInDB", back_populates="user")
|
| 22 |
+
|
| 23 |
+
def __init__(self, username: str, email: str, hashed_password: str):
|
| 24 |
+
self.username = username
|
| 25 |
+
self.email = email
|
| 26 |
+
self.hashed_password = hashed_password
|
app/core/models/__init__.py
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .AuthToken import AuthToken
|
| 2 |
+
from .User import UserInDB
|
| 3 |
+
from .Transcribe import TranscibeInDB
|
| 4 |
+
|
| 5 |
+
from app.core.database import Base, engine
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
Base.metadata.create_all(engine)
|
app/core/security.py
CHANGED
|
@@ -1,10 +1,12 @@
|
|
| 1 |
from passlib.context import CryptContext
|
| 2 |
|
|
|
|
|
|
|
| 3 |
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
| 4 |
|
| 5 |
ALGORITHM = "HS256"
|
| 6 |
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
| 7 |
-
SECRET_KEY =
|
| 8 |
|
| 9 |
|
| 10 |
def get_password_hash(password: str) -> str:
|
|
|
|
| 1 |
from passlib.context import CryptContext
|
| 2 |
|
| 3 |
+
from app.core.config import settings
|
| 4 |
+
|
| 5 |
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
|
| 6 |
|
| 7 |
ALGORITHM = "HS256"
|
| 8 |
ACCESS_TOKEN_EXPIRE_MINUTES = 30
|
| 9 |
+
SECRET_KEY = settings.SECRET_KEY
|
| 10 |
|
| 11 |
|
| 12 |
def get_password_hash(password: str) -> str:
|
requirements.txt
CHANGED
|
@@ -8,4 +8,5 @@ pytest-cov
|
|
| 8 |
faker
|
| 9 |
requests-mock
|
| 10 |
passlib
|
| 11 |
-
httpx
|
|
|
|
|
|
| 8 |
faker
|
| 9 |
requests-mock
|
| 10 |
passlib
|
| 11 |
+
httpx
|
| 12 |
+
PyJWT
|