folder restructure

This commit is contained in:
johnpccd 2025-05-24 12:06:57 +02:00
parent d8a6cffcb4
commit e863a333bb
47 changed files with 159 additions and 159 deletions

View File

@ -9,8 +9,8 @@ from fastapi.openapi.utils import get_openapi
from src.api.v1 import teams, users, images, auth, search
# Import configuration and database
from src.core.config import settings
from src.core.logging import setup_logging
from src.config.config import settings
from src.utils.logging import setup_logging
from src.db import db
from src.db.providers.firestore_provider import firestore_db
from src.db.repositories import init_repositories

View File

@ -13,12 +13,12 @@ from src.db.repositories.user_repository import user_repository
from src.db.repositories.api_key_repository import api_key_repository
# Import models
from src.db.models.team import TeamModel
from src.db.models.user import UserModel
from src.db.models.api_key import ApiKeyModel
from src.models.team import TeamModel
from src.models.user import UserModel
from src.models.api_key import ApiKeyModel
# Import security functions
from src.core.security import generate_api_key, calculate_expiry_date
from src.auth.security import generate_api_key, calculate_expiry_date
async def create_admin():
# Create a new team

View File

@ -9,7 +9,7 @@ import string
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Get the API key secret from environment
from src.core.config import settings
from src.config.config import settings
def generate_api_key(team_id="dev-team", user_id="dev-admin"):
"""

View File

@ -22,16 +22,16 @@ load_dotenv()
# Add the parent directory to the path so we can import from src
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.db.models.team import TeamModel
from src.db.models.user import UserModel
from src.db.models.api_key import ApiKeyModel
from src.db.models.image import ImageModel
from src.models.team import TeamModel
from src.models.user import UserModel
from src.models.api_key import ApiKeyModel
from src.models.image import ImageModel
from src.db.providers.firestore_provider import firestore_db
from src.db.repositories.firestore_team_repository import firestore_team_repository
from src.db.repositories.firestore_user_repository import firestore_user_repository
from src.db.repositories.firestore_api_key_repository import firestore_api_key_repository
from src.db.repositories.firestore_image_repository import firestore_image_repository
from src.core.security import hash_api_key as app_hash_api_key
from src.auth.security import hash_api_key as app_hash_api_key
# Configure logging
logging.basicConfig(

View File

@ -21,7 +21,7 @@ sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
from src.db.providers.firestore_provider import firestore_db
from src.db.repositories.firestore_api_key_repository import firestore_api_key_repository
from src.db.repositories.firestore_user_repository import firestore_user_repository
from src.core.security import hash_api_key, verify_api_key
from src.auth.security import hash_api_key, verify_api_key
# Configure logging
logging.basicConfig(

View File

@ -8,9 +8,9 @@ from src.db.repositories.api_key_repository import api_key_repository
from src.db.repositories.user_repository import user_repository
from src.db.repositories.team_repository import team_repository
from src.schemas.api_key import ApiKeyCreate, ApiKeyResponse, ApiKeyWithValueResponse, ApiKeyListResponse
from src.core.security import generate_api_key, verify_api_key, calculate_expiry_date, is_expired, hash_api_key
from src.db.models.api_key import ApiKeyModel
from src.core.logging import log_request
from src.auth.security import generate_api_key, verify_api_key, calculate_expiry_date, is_expired, hash_api_key
from src.models.api_key import ApiKeyModel
from src.utils.logging import log_request
logger = logging.getLogger(__name__)

View File

@ -4,9 +4,9 @@ from bson import ObjectId
from src.db.repositories.team_repository import team_repository
from src.schemas.team import TeamCreate, TeamUpdate, TeamResponse, TeamListResponse
from src.db.models.team import TeamModel
from src.models.team import TeamModel
from src.api.v1.auth import get_current_user
from src.core.logging import log_request
from src.utils.logging import log_request
logger = logging.getLogger(__name__)

View File

@ -6,7 +6,7 @@ import hashlib
from datetime import datetime, timedelta
from typing import Optional, Tuple
from src.core.config import settings
from src.config.config import settings
def generate_api_key(team_id: str, user_id: str) -> Tuple[str, str]:
"""

0
src/config/__init__.py Normal file
View File

View File

@ -1,100 +1,100 @@
import logging
import os
import json
from google.cloud import firestore
from google.oauth2 import service_account
from src.core.config import settings
logger = logging.getLogger(__name__)
class Database:
client = None
database_name = None
def connect_to_database(self):
"""Create database connection."""
try:
# Store database name
self.database_name = settings.FIRESTORE_DATABASE_NAME
# Print project ID and database name for debugging
logger.info(f"Attempting to connect to Firestore with project ID: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
# First try using Application Default Credentials (for Cloud environments)
try:
logger.info("Attempting to connect using Application Default Credentials")
self.client = firestore.Client(
project=settings.FIRESTORE_PROJECT_ID,
database=self.database_name
)
# Test connection by trying to access a collection
self.client.collection('test').limit(1).get()
logger.info(f"Connected to Firestore project using Application Default Credentials: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
return
except Exception as adc_error:
logger.error(f"Application Default Credentials failed: {adc_error}", exc_info=True)
# Fall back to service account file
credentials_path = settings.FIRESTORE_CREDENTIALS_FILE
if not os.path.exists(credentials_path):
logger.error(f"Firestore credentials file not found: {credentials_path}")
raise FileNotFoundError(f"Credentials file not found: {credentials_path}")
# Print key file contents (without sensitive parts) for debugging
try:
with open(credentials_path, 'r') as f:
key_data = json.load(f)
# Log non-sensitive parts of the key
logger.info(f"Using credentials file with project_id: {key_data.get('project_id')}")
logger.info(f"Client email: {key_data.get('client_email')}")
logger.info(f"Key file type: {key_data.get('type')}")
except Exception as e:
logger.error(f"Error reading key file: {e}")
# Load credentials
credentials = service_account.Credentials.from_service_account_file(credentials_path)
# Initialize Firestore client
self.client = firestore.Client(
project=settings.FIRESTORE_PROJECT_ID,
database=self.database_name,
credentials=credentials
)
# Test connection by trying to access a collection
self.client.collection('test').limit(1).get()
logger.info(f"Connected to Firestore project using credentials file: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
except Exception as e:
logger.error(f"Failed to connect to Firestore: {e}", exc_info=True)
raise
def close_database_connection(self):
"""Close database connection."""
try:
# No explicit close method needed for Firestore client
self.client = None
logger.info("Closed Firestore connection")
except Exception as e:
logger.error(f"Failed to close Firestore connection: {e}")
def get_database(self):
"""Get the database instance."""
if self.client is None:
logger.warning("Database client is None. Attempting to reconnect...")
try:
self.connect_to_database()
except Exception as e:
logger.error(f"Failed to reconnect to database: {e}")
# Return None to avoid further errors but log this issue
return None
# Verify that client is properly initialized
if self.client is None:
logger.error("Database client is still None after reconnect attempt")
return None
return self.client
# Create a singleton database instance
db = Database()
import logging
import os
import json
from google.cloud import firestore
from google.oauth2 import service_account
from src.config.config import settings
logger = logging.getLogger(__name__)
class Database:
client = None
database_name = None
def connect_to_database(self):
"""Create database connection."""
try:
# Store database name
self.database_name = settings.FIRESTORE_DATABASE_NAME
# Print project ID and database name for debugging
logger.info(f"Attempting to connect to Firestore with project ID: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
# First try using Application Default Credentials (for Cloud environments)
try:
logger.info("Attempting to connect using Application Default Credentials")
self.client = firestore.Client(
project=settings.FIRESTORE_PROJECT_ID,
database=self.database_name
)
# Test connection by trying to access a collection
self.client.collection('test').limit(1).get()
logger.info(f"Connected to Firestore project using Application Default Credentials: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
return
except Exception as adc_error:
logger.error(f"Application Default Credentials failed: {adc_error}", exc_info=True)
# Fall back to service account file
credentials_path = settings.FIRESTORE_CREDENTIALS_FILE
if not os.path.exists(credentials_path):
logger.error(f"Firestore credentials file not found: {credentials_path}")
raise FileNotFoundError(f"Credentials file not found: {credentials_path}")
# Print key file contents (without sensitive parts) for debugging
try:
with open(credentials_path, 'r') as f:
key_data = json.load(f)
# Log non-sensitive parts of the key
logger.info(f"Using credentials file with project_id: {key_data.get('project_id')}")
logger.info(f"Client email: {key_data.get('client_email')}")
logger.info(f"Key file type: {key_data.get('type')}")
except Exception as e:
logger.error(f"Error reading key file: {e}")
# Load credentials
credentials = service_account.Credentials.from_service_account_file(credentials_path)
# Initialize Firestore client
self.client = firestore.Client(
project=settings.FIRESTORE_PROJECT_ID,
database=self.database_name,
credentials=credentials
)
# Test connection by trying to access a collection
self.client.collection('test').limit(1).get()
logger.info(f"Connected to Firestore project using credentials file: {settings.FIRESTORE_PROJECT_ID}, database: {self.database_name}")
except Exception as e:
logger.error(f"Failed to connect to Firestore: {e}", exc_info=True)
raise
def close_database_connection(self):
"""Close database connection."""
try:
# No explicit close method needed for Firestore client
self.client = None
logger.info("Closed Firestore connection")
except Exception as e:
logger.error(f"Failed to close Firestore connection: {e}")
def get_database(self):
"""Get the database instance."""
if self.client is None:
logger.warning("Database client is None. Attempting to reconnect...")
try:
self.connect_to_database()
except Exception as e:
logger.error(f"Failed to reconnect to database: {e}")
# Return None to avoid further errors but log this issue
return None
# Verify that client is properly initialized
if self.client is None:
logger.error("Database client is still None after reconnect attempt")
return None
return self.client
# Create a singleton database instance
db = Database()

View File

@ -4,11 +4,11 @@ import os
from google.cloud import firestore
from pydantic import BaseModel
from src.core.config import settings
from src.db.models.team import TeamModel
from src.db.models.user import UserModel
from src.db.models.api_key import ApiKeyModel
from src.db.models.image import ImageModel
from src.config.config import settings
from src.models.team import TeamModel
from src.models.user import UserModel
from src.models.api_key import ApiKeyModel
from src.models.image import ImageModel
logger = logging.getLogger(__name__)

View File

@ -1,5 +1,5 @@
import logging
from src.core.config import settings
from src.config.config import settings
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@ from typing import List, Optional
from bson import ObjectId
from src.db import db
from src.db.models.api_key import ApiKeyModel
from src.models.api_key import ApiKeyModel
logger = logging.getLogger(__name__)

View File

@ -1,6 +1,6 @@
import logging
from src.db.repositories.firestore_repository import FirestoreRepository
from src.db.models.api_key import ApiKeyModel
from src.models.api_key import ApiKeyModel
logger = logging.getLogger(__name__)

View File

@ -1,6 +1,6 @@
import logging
from src.db.repositories.firestore_repository import FirestoreRepository
from src.db.models.image import ImageModel
from src.models.image import ImageModel
logger = logging.getLogger(__name__)

View File

@ -3,7 +3,7 @@ from typing import List, Optional
from bson import ObjectId
from src.db.repositories.firestore_repository import FirestoreRepository
from src.db.models.team import TeamModel
from src.models.team import TeamModel
logger = logging.getLogger(__name__)

View File

@ -1,6 +1,6 @@
import logging
from src.db.repositories.firestore_repository import FirestoreRepository
from src.db.models.user import UserModel
from src.models.user import UserModel
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@ from typing import List, Optional, Dict, Any
from bson import ObjectId
from src.db import db
from src.db.models.image import ImageModel
from src.models.image import ImageModel
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@ from typing import List, Optional
from bson import ObjectId
from src.db import db
from src.db.models.team import TeamModel
from src.models.team import TeamModel
logger = logging.getLogger(__name__)

View File

@ -4,7 +4,7 @@ from typing import List, Optional
from bson import ObjectId
from src.db import db
from src.db.models.user import UserModel
from src.models.user import UserModel
logger = logging.getLogger(__name__)

0
src/models/__init__.py Normal file
View File

View File

@ -3,7 +3,7 @@ from typing import Optional, ClassVar
from pydantic import BaseModel, Field
from bson import ObjectId
from src.db.models.team import PyObjectId
from src.models.team import PyObjectId
class ApiKeyModel(BaseModel):
"""Database model for an API key"""

View File

@ -3,7 +3,7 @@ from typing import Optional, List, Dict, Any, ClassVar
from pydantic import BaseModel, Field, HttpUrl
from bson import ObjectId
from src.db.models.team import PyObjectId
from src.models.team import PyObjectId
class ImageModel(BaseModel):
"""Database model for an image"""

View File

@ -3,7 +3,7 @@ from typing import Optional, List, ClassVar
from pydantic import BaseModel, Field, EmailStr
from bson import ObjectId
from src.db.models.team import PyObjectId
from src.models.team import PyObjectId
class UserModel(BaseModel):
"""Database model for a user"""

View File

@ -5,7 +5,7 @@ from typing import List, Dict, Any, Union, Optional
import numpy as np
from PIL import Image
from src.core.config import settings
from src.config.config import settings
logger = logging.getLogger(__name__)

View File

@ -10,7 +10,7 @@ from google.cloud import storage
from google.oauth2 import service_account
from PIL import Image
from src.core.config import settings
from src.config.config import settings
logger = logging.getLogger(__name__)

View File

@ -3,7 +3,7 @@ from typing import List, Dict, Any, Optional, Tuple
import pinecone
from bson import ObjectId
from src.core.config import settings
from src.config.config import settings
logger = logging.getLogger(__name__)

0
src/utils/__init__.py Normal file
View File

View File

@ -2,7 +2,7 @@ import logging
import sys
from typing import Dict, Any
from src.core.config import settings
from src.config.config import settings
def setup_logging():
"""Configure logging settings for the application"""

View File

@ -6,11 +6,11 @@ from bson import ObjectId
from fastapi import FastAPI
from fastapi.testclient import TestClient
from src.db.models.team import TeamModel
from src.db.models.user import UserModel
from src.db.models.api_key import ApiKeyModel
from src.db.models.image import ImageModel
from src.core.security import generate_api_key
from src.models.team import TeamModel
from src.models.user import UserModel
from src.models.api_key import ApiKeyModel
from src.models.image import ImageModel
from src.auth.security import generate_api_key
from src.db.repositories.team_repository import team_repository
from src.db.repositories.user_repository import user_repository
from src.db.repositories.api_key_repository import api_key_repository

View File

@ -3,9 +3,9 @@ from fastapi.testclient import TestClient
from datetime import datetime, timedelta
from bson import ObjectId
from src.db.models.api_key import ApiKeyModel
from src.models.api_key import ApiKeyModel
from src.db.repositories.api_key_repository import api_key_repository
from src.core.security import generate_api_key
from src.auth.security import generate_api_key
@pytest.mark.asyncio

View File

@ -5,7 +5,7 @@ from fastapi.testclient import TestClient
from unittest.mock import patch, MagicMock
from src.db.repositories.image_repository import ImageRepository, image_repository
from src.db.models.image import ImageModel
from src.models.image import ImageModel
from main import app
# Hardcoded API key as requested

View File

@ -3,7 +3,7 @@ from fastapi.testclient import TestClient
from datetime import datetime
from bson import ObjectId
from src.db.models.image import ImageModel
from src.models.image import ImageModel
from src.db.repositories.image_repository import image_repository # Assuming this exists

View File

@ -3,7 +3,7 @@ from fastapi.testclient import TestClient
from datetime import datetime
from bson import ObjectId
from src.db.models.image import ImageModel
from src.models.image import ImageModel
from src.db.repositories.image_repository import image_repository # Assuming this exists

View File

@ -1,7 +1,7 @@
import pytest
from fastapi.testclient import TestClient
from datetime import datetime, timedelta
from src.core.security import generate_api_key, hash_api_key, verify_api_key, calculate_expiry_date, is_expired
from src.auth.security import generate_api_key, hash_api_key, verify_api_key, calculate_expiry_date, is_expired
def test_api_key_generation():

View File

@ -2,7 +2,7 @@ import pytest
from fastapi.testclient import TestClient
from bson import ObjectId
from src.db.models.team import TeamModel
from src.models.team import TeamModel
from src.db.repositories.team_repository import team_repository

0
tests/auth/__init__.py Normal file
View File

View File

@ -2,7 +2,7 @@ import pytest
from datetime import datetime, timedelta
from bson import ObjectId
from pydantic import ValidationError
from src.db.models.api_key import ApiKeyModel
from src.models.api_key import ApiKeyModel
class TestApiKeyModel:
def test_create_api_key(self):

View File

@ -2,7 +2,7 @@ import pytest
from datetime import datetime
from bson import ObjectId
from pydantic import ValidationError, HttpUrl
from src.db.models.image import ImageModel
from src.models.image import ImageModel
class TestImageModel:
def test_create_image(self):

View File

@ -1,7 +1,7 @@
import pytest
from bson import ObjectId
from pydantic import ValidationError, BaseModel, Field
from src.db.models.team import PyObjectId
from src.models.team import PyObjectId
class TestPyObjectId:
def test_valid_object_id(self):

View File

@ -1,7 +1,7 @@
import pytest
from datetime import datetime
from bson import ObjectId
from src.db.models.team import TeamModel, PyObjectId
from src.models.team import TeamModel, PyObjectId
class TestTeamModel:
def test_create_team(self):

View File

@ -2,8 +2,8 @@ import pytest
from datetime import datetime
from bson import ObjectId
from pydantic import ValidationError
from src.db.models.user import UserModel
from src.db.models.team import PyObjectId
from src.models.user import UserModel
from src.models.team import PyObjectId
class TestUserModel:
def test_create_user(self):

0
tests/models/__init__.py Normal file
View File

View File

@ -7,7 +7,7 @@ from io import BytesIO
from src.services.storage import StorageService
from src.db.repositories.image_repository import ImageRepository, image_repository
from src.db.models.image import ImageModel
from src.models.image import ImageModel
# Hardcoded API key as requested
API_KEY = "Wwg4eJjJ.d03970d43cf3a454ad4168b3226b423f"