Additional check in - try-sign-in and upload-document works fine with the production creds. Need further tuning on remaining parts.
This commit is contained in:
parent
26eedb1b89
commit
193188dbb7
@ -6,8 +6,7 @@ from app.authentication.backend.models.user.constants import (
|
||||
UserLoginAction,
|
||||
NewUserMethod,
|
||||
)
|
||||
from infra.exception.exceptions import InvalidAuthCodeException
|
||||
from app.authentication.backend.models.constants import UserLoginAction
|
||||
from app.authentication.backend.models.user.constants import UserLoginAction
|
||||
from app.authentication.backend.services.user.user_management_service import (
|
||||
UserManagementService,
|
||||
)
|
||||
|
||||
@ -8,10 +8,10 @@ from app.authentication.backend.infra.code_management.depot_handler import (
|
||||
)
|
||||
|
||||
|
||||
from app.authentication.backend.models.constants import (
|
||||
from app.authentication.backend.models.user.constants import (
|
||||
AuthType,
|
||||
)
|
||||
from app.authentication.backend.models.models import (
|
||||
from app.authentication.backend.models.user.models import (
|
||||
AuthCodeDoc,
|
||||
UserEmailDoc,
|
||||
UserMobileDoc,
|
||||
|
||||
8
app/authentication/backend/models/__init__.py
Normal file
8
app/authentication/backend/models/__init__.py
Normal file
@ -0,0 +1,8 @@
|
||||
from .gitea import code_models
|
||||
from .user import user_models
|
||||
from .user_profile import profile_models
|
||||
|
||||
backend_models = []
|
||||
backend_models.extend(code_models)
|
||||
backend_models.extend(user_models)
|
||||
backend_models.extend(profile_models)
|
||||
@ -1,43 +0,0 @@
|
||||
from enum import IntEnum
|
||||
|
||||
|
||||
class NewUserMethod(IntEnum):
|
||||
EMAIL = 1
|
||||
MOBILE = 2
|
||||
|
||||
|
||||
class UserAccountProperty(IntEnum):
|
||||
EMAIL_VERIFIED = 1
|
||||
MOBILE_VERIFIED = 2
|
||||
PAYMENT_SETUP = 4
|
||||
ACCEPT_REQUEST = 8
|
||||
READY_PROVIDER = 16
|
||||
MANAGE_PROJECT = 32
|
||||
|
||||
|
||||
class UserLoginAction(IntEnum):
|
||||
VERIFY_EMAIL_WITH_AUTH_CODE = 0
|
||||
EXISTING_USER_PASSWORD_REQUIRED = 1
|
||||
NEW_USER_SET_PASSWORD = 2
|
||||
EMAIL_NOT_ASSOCIATED_WITH_USER = 3
|
||||
REVIEW_AND_REVISE_FLID = 4
|
||||
USER_SIGNED_IN = 100
|
||||
|
||||
|
||||
class AuthType(IntEnum):
|
||||
MOBILE = 0
|
||||
EMAIL = 1
|
||||
PASSWORD = 2
|
||||
|
||||
|
||||
class DepotStatus(IntEnum):
|
||||
TO_BE_CREATED = 0
|
||||
CREATED = 1
|
||||
DELETED = 2
|
||||
|
||||
|
||||
class UserAccountStatus(IntEnum):
|
||||
TO_BE_CREATED = 0
|
||||
CREATED = 1
|
||||
DELETED = 2
|
||||
DEACTIVATED = 3
|
||||
3
app/authentication/backend/models/gitea/__init__.py
Normal file
3
app/authentication/backend/models/gitea/__init__.py
Normal file
@ -0,0 +1,3 @@
|
||||
from .models import CodeDepotDoc
|
||||
|
||||
code_models = [CodeDepotDoc]
|
||||
@ -1,37 +0,0 @@
|
||||
from datetime import datetime
|
||||
from beanie import Document
|
||||
from .constants import AuthType
|
||||
|
||||
|
||||
class UserPasswordDoc(Document):
|
||||
user_id: str
|
||||
password: str
|
||||
|
||||
class Settings:
|
||||
name = "user_password"
|
||||
|
||||
|
||||
class UserEmailDoc(Document):
|
||||
user_id: str
|
||||
email: str
|
||||
|
||||
class Settings:
|
||||
name = "user_email"
|
||||
|
||||
|
||||
class UserMobileDoc(Document):
|
||||
user_id: str
|
||||
mobile: str
|
||||
|
||||
class Settings:
|
||||
name = "user_mobile"
|
||||
|
||||
|
||||
class AuthCodeDoc(Document):
|
||||
auth_code: str
|
||||
method: str
|
||||
method_type: AuthType
|
||||
expiry: datetime
|
||||
|
||||
class Settings:
|
||||
name = "user_auth_code"
|
||||
15
app/authentication/backend/models/user/__init__.py
Normal file
15
app/authentication/backend/models/user/__init__.py
Normal file
@ -0,0 +1,15 @@
|
||||
from .models import (
|
||||
UserAccountDoc,
|
||||
UserPasswordDoc,
|
||||
UserEmailDoc,
|
||||
UserMobileDoc,
|
||||
AuthCodeDoc,
|
||||
)
|
||||
|
||||
user_models = [
|
||||
UserAccountDoc,
|
||||
UserPasswordDoc,
|
||||
UserEmailDoc,
|
||||
UserMobileDoc,
|
||||
AuthCodeDoc,
|
||||
]
|
||||
@ -35,3 +35,45 @@ UserRegionToCurrency = {
|
||||
UserRegion.ZH_CN: Currency.CNY.name,
|
||||
UserRegion.OTHER: Currency.USD.name,
|
||||
}
|
||||
|
||||
|
||||
class NewUserMethod(IntEnum):
|
||||
EMAIL = 1
|
||||
MOBILE = 2
|
||||
|
||||
|
||||
class UserAccountProperty(IntEnum):
|
||||
EMAIL_VERIFIED = 1
|
||||
MOBILE_VERIFIED = 2
|
||||
PAYMENT_SETUP = 4
|
||||
ACCEPT_REQUEST = 8
|
||||
READY_PROVIDER = 16
|
||||
MANAGE_PROJECT = 32
|
||||
|
||||
|
||||
class UserLoginAction(IntEnum):
|
||||
VERIFY_EMAIL_WITH_AUTH_CODE = 0
|
||||
EXISTING_USER_PASSWORD_REQUIRED = 1
|
||||
NEW_USER_SET_PASSWORD = 2
|
||||
EMAIL_NOT_ASSOCIATED_WITH_USER = 3
|
||||
REVIEW_AND_REVISE_FLID = 4
|
||||
USER_SIGNED_IN = 100
|
||||
|
||||
|
||||
class AuthType(IntEnum):
|
||||
MOBILE = 0
|
||||
EMAIL = 1
|
||||
PASSWORD = 2
|
||||
|
||||
|
||||
class DepotStatus(IntEnum):
|
||||
TO_BE_CREATED = 0
|
||||
CREATED = 1
|
||||
DELETED = 2
|
||||
|
||||
|
||||
class UserAccountStatus(IntEnum):
|
||||
TO_BE_CREATED = 0
|
||||
CREATED = 1
|
||||
DELETED = 2
|
||||
DEACTIVATED = 3
|
||||
|
||||
@ -7,7 +7,9 @@ from app.authentication.backend.models.permission.constants import (
|
||||
AdministrativeRole,
|
||||
Capability,
|
||||
)
|
||||
from datetime import datetime
|
||||
from infra.models.constants import UserRegion
|
||||
from .constants import AuthType
|
||||
|
||||
|
||||
class UserAccountDoc(Document):
|
||||
@ -21,3 +23,37 @@ class UserAccountDoc(Document):
|
||||
|
||||
class Settings:
|
||||
name = "user_account"
|
||||
|
||||
|
||||
class UserPasswordDoc(Document):
|
||||
user_id: str
|
||||
password: str
|
||||
|
||||
class Settings:
|
||||
name = "user_password"
|
||||
|
||||
|
||||
class UserEmailDoc(Document):
|
||||
user_id: str
|
||||
email: str
|
||||
|
||||
class Settings:
|
||||
name = "user_email"
|
||||
|
||||
|
||||
class UserMobileDoc(Document):
|
||||
user_id: str
|
||||
mobile: str
|
||||
|
||||
class Settings:
|
||||
name = "user_mobile"
|
||||
|
||||
|
||||
class AuthCodeDoc(Document):
|
||||
auth_code: str
|
||||
method: str
|
||||
method_type: AuthType
|
||||
expiry: datetime
|
||||
|
||||
class Settings:
|
||||
name = "user_auth_code"
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
from .models import BasicProfileDoc, ProviderProfileDoc
|
||||
|
||||
profile_models = [BasicProfileDoc, ProviderProfileDoc]
|
||||
@ -1,7 +1,7 @@
|
||||
from infra.config.app_settings import app_settings
|
||||
from beanie import init_beanie
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from app.central_storage.backend.models.models import DocumentDoc
|
||||
from app.authentication.backend.models import backend_models
|
||||
|
||||
|
||||
def register(app):
|
||||
@ -21,5 +21,5 @@ async def initiate_database():
|
||||
maxPoolSize=20, # Maximum number of connections in the pool
|
||||
)
|
||||
await init_beanie(
|
||||
database=client[app_settings.MONGODB_NAME], document_models=[DocumentDoc]
|
||||
database=client[app_settings.MONGODB_NAME], document_models=backend_models
|
||||
)
|
||||
|
||||
@ -1,15 +0,0 @@
|
||||
from app.central_storage.backend.business.document_manager import (
|
||||
DocumentBusinessManager,
|
||||
)
|
||||
|
||||
|
||||
class DocumentHub:
|
||||
def __init__(self, user_id: str):
|
||||
self.user_id = user_id
|
||||
self.document_business_manager = DocumentBusinessManager(self.user_id)
|
||||
return
|
||||
|
||||
async def get_document_by_id(self, document_id: str):
|
||||
return await self.document_business_manager.get_document_details_by_id(
|
||||
document_id
|
||||
)
|
||||
25
app/central_storage/backend/application/document_hub.py
Normal file
25
app/central_storage/backend/application/document_hub.py
Normal file
@ -0,0 +1,25 @@
|
||||
from app.central_storage.backend.business.document_manager import (
|
||||
DocumentManager,
|
||||
)
|
||||
|
||||
|
||||
class DocumentHub:
|
||||
def __init__(self, user_id: str):
|
||||
self.user_id = user_id
|
||||
self.document_manager = DocumentManager(self.user_id)
|
||||
return
|
||||
|
||||
async def get_document_by_id(self, document_id: str):
|
||||
return await self.document_manager.get_document_details_by_id(document_id)
|
||||
|
||||
async def upload_document_for_object(
|
||||
self, object_id: str, file_name: str, file_data: bytes
|
||||
) -> bool:
|
||||
"""Upload a file
|
||||
Args:
|
||||
file_name: the name of the file
|
||||
file (bytes): the file to be uploaded
|
||||
"""
|
||||
return await self.document_manager.upload_file_for_object(
|
||||
object_id, file_name, file_data
|
||||
)
|
||||
@ -1,7 +1,8 @@
|
||||
from app.central_storage.backend.services.document_service import DocumentService
|
||||
from app.central_storage.backend.models.models import MediaType, DataFormat
|
||||
|
||||
|
||||
class DocumentBusinessManager:
|
||||
class DocumentManager:
|
||||
def __init__(self, user_id) -> None:
|
||||
self.user_id = user_id
|
||||
self.document_service = DocumentService()
|
||||
@ -17,3 +18,20 @@ class DocumentBusinessManager:
|
||||
"file_name": file_name,
|
||||
"file_download_url": download_link,
|
||||
}
|
||||
|
||||
async def upload_file_for_object(
|
||||
self, object_id: str, file_name: str, file_data: bytes
|
||||
) -> bool:
|
||||
await self.document_service.new_document(
|
||||
file_name=file_name,
|
||||
# This 'UNKNOWN' will make the document manager decide the media type from file name
|
||||
media_type=MediaType.UNKNOWN,
|
||||
data_format=DataFormat.RAW,
|
||||
created_by=object_id,
|
||||
)
|
||||
return await self.document_service.save_document_file(file_data) or None
|
||||
# TODO: This should go to Freeleaps App
|
||||
# add_doc = await self.attachment_service.add_document_to_request(
|
||||
# request_id, document_id
|
||||
# )
|
||||
# await self.proposal_store.update_latest_proposal_with_documents(request_id)
|
||||
|
||||
@ -16,7 +16,7 @@ from azure.storage.blob import (
|
||||
from azure.core.exceptions import ResourceExistsError
|
||||
|
||||
|
||||
class AzureBlobManager:
|
||||
class AzureBlobHandler:
|
||||
def __init__(self) -> None:
|
||||
pass
|
||||
|
||||
4
app/central_storage/backend/models/__init__.py
Normal file
4
app/central_storage/backend/models/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from .models import DocumentDoc
|
||||
|
||||
backend_models = []
|
||||
backend_models.extend([DocumentDoc])
|
||||
@ -3,8 +3,8 @@ from app.central_storage.backend.models.models import DocumentDoc
|
||||
from app.central_storage.backend.models.constants import MediaType, DataFormat
|
||||
|
||||
from infra.exception.exceptions import DoesNotExistError
|
||||
from app.central_storage.backend.infra.azure_storage.blob_manager import (
|
||||
AzureBlobManager,
|
||||
from app.central_storage.backend.infra.azure_storage.blob_handler import (
|
||||
AzureBlobHandler,
|
||||
)
|
||||
import base64
|
||||
import os
|
||||
@ -14,7 +14,7 @@ from re import match
|
||||
class DocumentService:
|
||||
def __init__(self) -> None:
|
||||
self.__document_doc = None
|
||||
self.blob_manager = AzureBlobManager()
|
||||
self.blob_manager = AzureBlobHandler()
|
||||
return
|
||||
|
||||
def __normalize_file_name__(file_name: str) -> str:
|
||||
@ -86,14 +86,14 @@ class DocumentService:
|
||||
document = DocumentDoc(
|
||||
document_id=None,
|
||||
location=None,
|
||||
file_name=DocumentManager.__normalize_file_name__(file_name),
|
||||
file_name=DocumentService.__normalize_file_name__(file_name),
|
||||
created_by=created_by,
|
||||
create_time=dt.now(tz.utc),
|
||||
updated_by=created_by,
|
||||
update_time=dt.now(tz.utc),
|
||||
version_number=1,
|
||||
media_type=(
|
||||
DocumentManager.__retrieve_media_type_from_file_name__(file_name)
|
||||
DocumentService.__retrieve_media_type_from_file_name__(file_name)
|
||||
if media_type == MediaType.UNKNOWN
|
||||
else media_type
|
||||
),
|
||||
|
||||
@ -5,8 +5,10 @@ pydantic==2.9.2
|
||||
loguru==0.7.2
|
||||
uvicorn==0.23.2
|
||||
beanie==1.21.0
|
||||
httpx
|
||||
aio-pika
|
||||
pydantic-settings
|
||||
python-multipart
|
||||
python-jose
|
||||
azure-storage-blob==12.22.0
|
||||
azure-identity
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
from infra.config.app_settings import app_settings
|
||||
from beanie import init_beanie
|
||||
from motor.motor_asyncio import AsyncIOMotorClient
|
||||
from app.central_storage.backend.models.models import DocumentDoc
|
||||
from app.central_storage.backend.models import backend_models
|
||||
|
||||
|
||||
def register(app):
|
||||
@ -21,5 +21,5 @@ async def initiate_database():
|
||||
maxPoolSize=20, # Maximum number of connections in the pool
|
||||
)
|
||||
await init_beanie(
|
||||
database=client[app_settings.MONGODB_NAME], document_models=[DocumentDoc]
|
||||
database=client[app_settings.MONGODB_NAME], document_models=backend_models
|
||||
)
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
from fastapi import APIRouter
|
||||
from .get_document_by_id import router as doc_router
|
||||
from .upload_document import router as ud_router
|
||||
|
||||
api_router = APIRouter()
|
||||
api_router.include_router(doc_router, tags=["attachment"])
|
||||
api_router.include_router(ud_router, tags=["attachment"])
|
||||
|
||||
websocket_router = APIRouter()
|
||||
|
||||
@ -1,8 +1,14 @@
|
||||
from fastapi import APIRouter, HTTPException, Request
|
||||
from fastapi import APIRouter
|
||||
from infra.token.token_manager import TokenManager
|
||||
from fastapi import APIRouter, Depends
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from fastapi import Depends, HTTPException
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from infra.token.token_manager import TokenManager
|
||||
from app.central_storage.backend.application.document_app import DocumentHub
|
||||
from app.central_storage.backend.application.document_hub import DocumentHub
|
||||
|
||||
router = APIRouter()
|
||||
token_manager = TokenManager()
|
||||
@ -19,32 +25,14 @@ token_manager = TokenManager()
|
||||
)
|
||||
async def get_document_by_id(
|
||||
document_id: str,
|
||||
request: Request,
|
||||
current_user: dict = Depends(token_manager.get_current_user),
|
||||
):
|
||||
# Extract the Authorization header
|
||||
auth_header = request.headers.get("Authorization")
|
||||
user_id = current_user.get("id")
|
||||
|
||||
if not auth_header:
|
||||
raise HTTPException(status_code=401, detail="Authorization header missing")
|
||||
|
||||
# Ensure the header starts with 'Bearer'
|
||||
if not auth_header.startswith("Bearer "):
|
||||
raise HTTPException(status_code=401, detail="Invalid authorization header")
|
||||
|
||||
token = auth_header.split(" ")[1]
|
||||
|
||||
try:
|
||||
# Decode the token using the TokenManager
|
||||
credentials = token_manager.decode_token(token)
|
||||
except Exception as e:
|
||||
raise HTTPException(
|
||||
status_code=401, detail=f"Invalid or expired token: {str(e)}"
|
||||
)
|
||||
|
||||
# Get the user_id from the decoded token
|
||||
user_id = credentials.get("id")
|
||||
if not user_id:
|
||||
raise HTTPException(status_code=401, detail="Invalid token payload")
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED, detail="Could not validate credentials"
|
||||
)
|
||||
|
||||
# Fetch the document using DocumentHub
|
||||
document = await DocumentHub(user_id).get_document_by_id(document_id)
|
||||
|
||||
50
app/central_storage/webapi/routes/upload_document.py
Normal file
50
app/central_storage/webapi/routes/upload_document.py
Normal file
@ -0,0 +1,50 @@
|
||||
from fastapi import APIRouter, UploadFile, File, Form, HTTPException
|
||||
from fastapi import APIRouter, Depends
|
||||
from infra.token.token_manager import TokenManager
|
||||
from starlette.status import HTTP_401_UNAUTHORIZED
|
||||
from fastapi.encoders import jsonable_encoder
|
||||
from fastapi.responses import JSONResponse
|
||||
from app.central_storage.backend.application.document_hub import DocumentHub
|
||||
|
||||
|
||||
router = APIRouter()
|
||||
token_manager = TokenManager()
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload-document",
|
||||
summary="upload a document for a given object.",
|
||||
description="upload a document. If success, returning the document id",
|
||||
)
|
||||
async def attach_document_for_request(
|
||||
object_id: str = Form(...),
|
||||
file: UploadFile = File(None),
|
||||
current_user: dict = Depends(token_manager.get_current_user),
|
||||
):
|
||||
print("current user", current_user)
|
||||
user_id = current_user.get("id")
|
||||
print("current user id", user_id)
|
||||
if not user_id:
|
||||
raise HTTPException(
|
||||
status_code=HTTP_401_UNAUTHORIZED, detail="Could not validate credentials"
|
||||
)
|
||||
|
||||
document_hub = DocumentHub(user_id)
|
||||
# File processing
|
||||
try:
|
||||
file_data = await file.read() # You can use async chunking for larger files
|
||||
document_id = await document_hub.upload_document_for_object(
|
||||
object_id, file.filename, file_data
|
||||
)
|
||||
|
||||
if document_id:
|
||||
result = {"document_id": str(document_id), "file_name": file.filename}
|
||||
return JSONResponse(content=jsonable_encoder(result))
|
||||
else:
|
||||
return JSONResponse(
|
||||
status_code=500, content={"error": "File upload failed"}
|
||||
)
|
||||
|
||||
except Exception as e:
|
||||
print("this is exception", e)
|
||||
return JSONResponse(status_code=500, content={"error": "Internal server error"})
|
||||
Loading…
Reference in New Issue
Block a user