Initial commit

This commit is contained in:
Jero
2024-12-18 20:29:52 +02:00
parent 843131d989
commit a8f4d1bc44
37157 changed files with 4756336 additions and 0 deletions
+17
View File
@@ -0,0 +1,17 @@
FROM python:3.13-alpine
WORKDIR /app
RUN adduser -D nonroot
USER nonroot
COPY ./src/ /app/
RUN pip install --upgrade pip &&\
pip install uv &&\
uv pip install --user --no-cache-dir --upgrade -r /code/requirements/requirements.txt
EXPOSE 8000
ENTRYPOINT ["python", "-m"]
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
View File
+6
View File
@@ -0,0 +1,6 @@
class Settings:
PROJECT_NAME:str = "Open Asset Manager"
PROJECT_VERSION: str = "0.0.1"
PROJECT_SUMMARY: str = "Product API for Open Asset Manager."
settings = Settings()
+32
View File
@@ -0,0 +1,32 @@
from typing_extensions import Any
from tortoise import Tortoise
import os
db_url = os.getenv('PSQL_CONNECT_STR')
modules: dict[str, Any] = {'models': [
'.models',
'.modules.auth.models',
'.modules.assets.models',
]}
TORTOISE_ORM = {
"connections": {"default": db_url},
"apps": {
"models": {
"models": modules.get("models", []) + ["aerich.models"],
"default_connection": "default",
},
},
}
async def init_db():
await Tortoise.init(
db_url=db_url,
modules=modules
)
async def migrate_db():
await init_db()
# Generate the schema
await Tortoise.generate_schemas(safe=True)
+30
View File
@@ -0,0 +1,30 @@
from fastapi import FastAPI
from starlette.responses import RedirectResponse
from .config import settings
from .modules.assets.router import router as asset_router
from dotenv import load_dotenv
from tortoise.contrib.fastapi import register_tortoise
from .database import db_url, modules
load_dotenv()
app = FastAPI(
title=settings.PROJECT_NAME,
version=settings.PROJECT_VERSION,
summary=settings.PROJECT_SUMMARY,
)
register_tortoise(
app,
db_url=db_url,
modules=modules,
generate_schemas=True,
add_exception_handlers=True,
)
app.include_router(asset_router)
@app.get("/")
async def main():
return RedirectResponse(url="/docs")
+74
View File
@@ -0,0 +1,74 @@
from enum import Enum
from typing import Type
from tortoise.exceptions import ConfigurationError
from tortoise.models import Model
from tortoise import fields
class EnumField(fields.CharField):
"""
An example extension to CharField that serializes Enums
to and from a str representation in the DB.
"""
def __init__(self, enum_type: Type[Enum], **kwargs):
super().__init__(128, **kwargs)
if not issubclass(enum_type, Enum):
raise ConfigurationError("{} is not a subclass of Enum!".format(enum_type))
self._enum_type = enum_type
def to_db_value(self, value: Enum, instance) -> str:
return value.value
def to_python_value(self, value: str) -> Enum:
try:
return self._enum_type(value)
except Exception:
raise ValueError(
"Database value {} does not exist on Enum {}.".format(value, self._enum_type)
)
class OrganizationType(Enum):
HOME = 1 # Home use (Any size)
SMALL_ORGANIZATION = 2 # 1-100
MEDIUM_ORGANIZATION = 3 # 100 - 500
LARGE_ORGANIZATION = 4 # 500 - 1000
EXTRA_LARGE_ORGANIZATION = 5 # 1000 - 5000+
class CreatedAndModifiedMixin():
created = fields.DatetimeField(null=True, auto_now_add=True)
modified = fields.DatetimeField(null=True, auto_now=True)
class Organization(Model, CreatedAndModifiedMixin):
id = fields.UUIDField(primary_key=True)
name = fields.CharField(max_length=128)
type = EnumField(OrganizationType)
users = fields.ManyToManyField('models.User',
related_name='members',
through="Membership",
forward_key='user_id',
backward_key='organization_id',
null=True
)
def __str__(self) -> str:
return f"{self.id} - {self.name}"
class User(Model, CreatedAndModifiedMixin):
id = fields.UUIDField(primary_key=True)
name = fields.TextField()
surname = fields.TextField()
password = fields.CharField(max_length=128, null=True)
organizations = fields.ManyToManyField('models.Organization',
related_name='members',
through='Membership',
forward_key='organization_id',
backward_key='user_id',
null=True
)
def __str__(self) -> str:
return f"{self.id} - {self.name} {self.surname}"
class Membership(Model, CreatedAndModifiedMixin):
organization = fields.ForeignKeyField('models.Organization')
user = fields.ForeignKeyField('models.User')
@@ -0,0 +1,6 @@
from tortoise.models import Model
from tortoise import fields
class Asset(Model):
id = fields.UUIDField(primary_key=True)
name = fields.CharField(max_length=128)
@@ -0,0 +1,26 @@
from uuid import UUID
from fastapi.routing import APIRouter
from .models import Asset
router = APIRouter(
prefix="/assets"
)
@router.get("/")
async def get_all_assets():
return await Asset.get_or_none()
@router.post("/")
async def create_asset(name: str):
asset = await Asset.create(name=name)
return asset
@router.delete("/", status_code=204)
async def delete_asset(remove_id: UUID):
await Asset.filter(id=remove_id).delete()
@router.get("/{asset_id}")
async def get_asset(asset_id: UUID):
return Asset.filter(id=asset_id).get_or_none()
@@ -0,0 +1 @@
@@ -0,0 +1 @@
+4
View File
@@ -0,0 +1,4 @@
[tool.aerich]
tortoise_orm = "database.TORTOISE_ORM"
location = "./migrations"
src_folder = "./."
@@ -0,0 +1,7 @@
aerich==0.8.0
fastapi[standard]==0.115.5
uvicorn==0.31.1
tortoise-orm[asyncpg]==0.22.1
black==24.10.0
python-dotenv==1.0.1
uvicorn[standard]==0.34.0