aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Chris Lovering <[email protected]>2024-07-08 21:35:32 +0100
committerGravatar Chris Lovering <[email protected]>2024-07-21 13:45:30 +0100
commit41169d155f025c78a68889d36b3cc4ebb07a99cf (patch)
treec06a45c930b3fcecc678256820962722c909b18a
parentUpdate middleware to use SQLA to create db sessions (diff)
Move existing models to schemas namespace
This is to make room for a new ORM namespace for SQLAlchemy models
-rw-r--r--backend/authentication/user.py5
-rw-r--r--backend/discord.py23
-rw-r--r--backend/models/__init__.py19
-rw-r--r--backend/models/dtos/__init__.py19
-rw-r--r--backend/models/dtos/antispam.py (renamed from backend/models/antispam.py)0
-rw-r--r--backend/models/dtos/discord_role.py (renamed from backend/models/discord_role.py)0
-rw-r--r--backend/models/dtos/discord_user.py (renamed from backend/models/discord_user.py)0
-rw-r--r--backend/models/dtos/form.py (renamed from backend/models/form.py)0
-rw-r--r--backend/models/dtos/form_response.py (renamed from backend/models/form_response.py)0
-rw-r--r--backend/models/dtos/question.py (renamed from backend/models/question.py)0
-rw-r--r--backend/models/orm/__init__.py0
-rw-r--r--backend/routes/discord.py9
-rw-r--r--backend/routes/forms/condorcet.py2
-rw-r--r--backend/routes/forms/discover.py2
-rw-r--r--backend/routes/forms/form.py2
-rw-r--r--backend/routes/forms/index.py4
-rw-r--r--backend/routes/forms/response.py2
-rw-r--r--backend/routes/forms/responses.py2
-rw-r--r--backend/routes/forms/submit.py2
-rw-r--r--backend/routes/forms/unittesting.py2
-rw-r--r--docker-compose.yml28
21 files changed, 72 insertions, 49 deletions
diff --git a/backend/authentication/user.py b/backend/authentication/user.py
index 5e99546..6ad4c63 100644
--- a/backend/authentication/user.py
+++ b/backend/authentication/user.py
@@ -4,8 +4,9 @@ import jwt
from pymongo.database import Database
from starlette.authentication import BaseUser
-from backend import discord, models
+from backend import discord
from backend.constants import SECRET_KEY
+from backend.models import dtos
class User(BaseUser):
@@ -15,7 +16,7 @@ class User(BaseUser):
self,
token: str,
payload: dict[str, t.Any],
- member: models.DiscordMember | None,
+ member: dtos.DiscordMember | None,
) -> None:
self.token = token
self.payload = payload
diff --git a/backend/discord.py b/backend/discord.py
index 4a1ecf5..22826e2 100644
--- a/backend/discord.py
+++ b/backend/discord.py
@@ -6,7 +6,8 @@ import httpx
import starlette.requests
from starlette import exceptions
-from backend import constants, models
+from backend import constants
+from backend.models import dtos
async def fetch_bearer_token(code: str, redirect: str, *, refresh: bool) -> dict:
@@ -51,7 +52,7 @@ async def fetch_user_details(bearer_token: str) -> dict:
return r.json()
-async def _get_role_info() -> list[models.DiscordRole]:
+async def _get_role_info() -> list[dtos.DiscordRole]:
"""Get information about the roles in the configured guild."""
async with httpx.AsyncClient() as client:
r = await client.get(
@@ -60,13 +61,13 @@ async def _get_role_info() -> list[models.DiscordRole]:
)
r.raise_for_status()
- return [models.DiscordRole(**role) for role in r.json()]
+ return [dtos.DiscordRole(**role) for role in r.json()]
async def get_roles(
*,
force_refresh: bool = False,
-) -> list[models.DiscordRole]:
+) -> list[dtos.DiscordRole]:
"""
Get a list of all roles from the cache, or discord API if not available.
@@ -77,7 +78,7 @@ async def get_roles(
roles = await constants.REDIS_CLIENT.hgetall(role_cache_key)
if roles:
return [
- models.DiscordRole(**json.loads(role_data)) for role_id, role_data in roles.items()
+ dtos.DiscordRole(**json.loads(role_data)) for role_id, role_data in roles.items()
]
roles = await _get_role_info()
@@ -86,7 +87,7 @@ async def get_roles(
return roles
-async def _fetch_member_api(member_id: str) -> models.DiscordMember | None:
+async def _fetch_member_api(member_id: str) -> dtos.DiscordMember | None:
"""Get a member by ID from the configured guild using the discord API."""
async with httpx.AsyncClient() as client:
r = await client.get(
@@ -99,14 +100,14 @@ async def _fetch_member_api(member_id: str) -> models.DiscordMember | None:
return None
r.raise_for_status()
- return models.DiscordMember(**r.json())
+ return dtos.DiscordMember(**r.json())
async def get_member(
user_id: str,
*,
force_refresh: bool = False,
-) -> models.DiscordMember | None:
+) -> dtos.DiscordMember | None:
"""
Get a member from the cache, or from the discord API.
@@ -118,7 +119,7 @@ async def get_member(
if not force_refresh:
result = await constants.REDIS_CLIENT.get(member_key)
if result:
- return models.DiscordMember(**json.loads(result))
+ return dtos.DiscordMember(**json.loads(result))
member = await _fetch_member_api(user_id)
if member:
@@ -150,14 +151,14 @@ async def _verify_access_helper(
if "admin" in request.auth.scopes:
return
- form = models.Form(**form)
+ form = dtos.Form(**form)
for role_id in getattr(form, attribute, None) or []:
role = await request.state.db.roles.find_one({"id": role_id})
if not role:
continue
- role = models.DiscordRole(**json.loads(role["data"]))
+ role = dtos.DiscordRole(**json.loads(role["data"]))
if role.name in request.auth.scopes:
return
diff --git a/backend/models/__init__.py b/backend/models/__init__.py
index 336e28b..e69de29 100644
--- a/backend/models/__init__.py
+++ b/backend/models/__init__.py
@@ -1,19 +0,0 @@
-from .antispam import AntiSpam
-from .discord_role import DiscordRole
-from .discord_user import DiscordMember, DiscordUser
-from .form import Form, FormList
-from .form_response import FormResponse, ResponseList
-from .question import CodeQuestion, Question
-
-__all__ = [
- "AntiSpam",
- "CodeQuestion",
- "DiscordMember",
- "DiscordRole",
- "DiscordUser",
- "Form",
- "FormList",
- "FormResponse",
- "Question",
- "ResponseList",
-]
diff --git a/backend/models/dtos/__init__.py b/backend/models/dtos/__init__.py
new file mode 100644
index 0000000..336e28b
--- /dev/null
+++ b/backend/models/dtos/__init__.py
@@ -0,0 +1,19 @@
+from .antispam import AntiSpam
+from .discord_role import DiscordRole
+from .discord_user import DiscordMember, DiscordUser
+from .form import Form, FormList
+from .form_response import FormResponse, ResponseList
+from .question import CodeQuestion, Question
+
+__all__ = [
+ "AntiSpam",
+ "CodeQuestion",
+ "DiscordMember",
+ "DiscordRole",
+ "DiscordUser",
+ "Form",
+ "FormList",
+ "FormResponse",
+ "Question",
+ "ResponseList",
+]
diff --git a/backend/models/antispam.py b/backend/models/dtos/antispam.py
index b596d4d..b596d4d 100644
--- a/backend/models/antispam.py
+++ b/backend/models/dtos/antispam.py
diff --git a/backend/models/discord_role.py b/backend/models/dtos/discord_role.py
index 195f557..195f557 100644
--- a/backend/models/discord_role.py
+++ b/backend/models/dtos/discord_role.py
diff --git a/backend/models/discord_user.py b/backend/models/dtos/discord_user.py
index be10672..be10672 100644
--- a/backend/models/discord_user.py
+++ b/backend/models/dtos/discord_user.py
diff --git a/backend/models/form.py b/backend/models/dtos/form.py
index 739464e..739464e 100644
--- a/backend/models/form.py
+++ b/backend/models/dtos/form.py
diff --git a/backend/models/form_response.py b/backend/models/dtos/form_response.py
index 3c8297b..3c8297b 100644
--- a/backend/models/form_response.py
+++ b/backend/models/dtos/form_response.py
diff --git a/backend/models/question.py b/backend/models/dtos/question.py
index a13ce93..a13ce93 100644
--- a/backend/models/question.py
+++ b/backend/models/dtos/question.py
diff --git a/backend/models/orm/__init__.py b/backend/models/orm/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/backend/models/orm/__init__.py
diff --git a/backend/routes/discord.py b/backend/routes/discord.py
index 5cd6b47..1a56aac 100644
--- a/backend/routes/discord.py
+++ b/backend/routes/discord.py
@@ -6,7 +6,8 @@ from starlette.authentication import requires
from starlette.responses import JSONResponse
from starlette.routing import Request
-from backend import discord, models, route
+from backend import discord, route
+from backend.models import dtos
from backend.validation import ErrorMessage, api
NOT_FOUND_EXCEPTION = JSONResponse(
@@ -24,7 +25,7 @@ class RolesRoute(route.Route):
class RolesResponse(pydantic.BaseModel):
"""A list of all roles on the configured server."""
- roles: list[models.DiscordRole]
+ roles: list[dtos.DiscordRole]
@requires(["authenticated", "admin"])
@api.validate(
@@ -53,7 +54,7 @@ class MemberRoute(route.Route):
@requires(["authenticated", "admin"])
@api.validate(
- resp=Response(HTTP_200=models.DiscordMember, HTTP_400=ErrorMessage),
+ resp=Response(HTTP_200=dtos.DiscordMember, HTTP_400=ErrorMessage),
json=MemberRequest,
tags=["auth"],
)
@@ -68,7 +69,7 @@ class MemberRoute(route.Route):
@requires(["authenticated", "admin"])
@api.validate(
- resp=Response(HTTP_200=models.DiscordMember, HTTP_400=ErrorMessage),
+ resp=Response(HTTP_200=dtos.DiscordMember, HTTP_400=ErrorMessage),
json=MemberRequest,
tags=["auth"],
)
diff --git a/backend/routes/forms/condorcet.py b/backend/routes/forms/condorcet.py
index 902770b..ac7e52e 100644
--- a/backend/routes/forms/condorcet.py
+++ b/backend/routes/forms/condorcet.py
@@ -9,7 +9,7 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend import discord
-from backend.models import Form, FormResponse, Question
+from backend.models.dtos import Form, FormResponse, Question
from backend.route import Route
from backend.validation import api
diff --git a/backend/routes/forms/discover.py b/backend/routes/forms/discover.py
index 0fe10b5..43e6cf3 100644
--- a/backend/routes/forms/discover.py
+++ b/backend/routes/forms/discover.py
@@ -5,7 +5,7 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend import constants
-from backend.models import Form, FormList, Question
+from backend.models.dtos import Form, FormList, Question
from backend.route import Route
from backend.validation import api
diff --git a/backend/routes/forms/form.py b/backend/routes/forms/form.py
index 86bbf49..c96d0d6 100644
--- a/backend/routes/forms/form.py
+++ b/backend/routes/forms/form.py
@@ -10,7 +10,7 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend import constants, discord
-from backend.models import Form
+from backend.models.dtos import Form
from backend.route import Route
from backend.routes.forms.discover import AUTH_FORM
from backend.validation import ErrorMessage, OkayResponse, api
diff --git a/backend/routes/forms/index.py b/backend/routes/forms/index.py
index 1fdfc48..4b55af2 100644
--- a/backend/routes/forms/index.py
+++ b/backend/routes/forms/index.py
@@ -6,8 +6,8 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend.constants import WebHook
-from backend.models import Form, FormList
-from backend.models.form import validate_hook_url
+from backend.models.dtos import Form, FormList
+from backend.models.dtos.form import validate_hook_url
from backend.route import Route
from backend.validation import ErrorMessage, OkayResponse, api
diff --git a/backend/routes/forms/response.py b/backend/routes/forms/response.py
index b4f7f04..ac80b74 100644
--- a/backend/routes/forms/response.py
+++ b/backend/routes/forms/response.py
@@ -6,7 +6,7 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend import discord
-from backend.models import FormResponse
+from backend.models.dtos import FormResponse
from backend.route import Route
from backend.validation import ErrorMessage, OkayResponse, api
diff --git a/backend/routes/forms/responses.py b/backend/routes/forms/responses.py
index 85e5af2..4228af8 100644
--- a/backend/routes/forms/responses.py
+++ b/backend/routes/forms/responses.py
@@ -7,7 +7,7 @@ from starlette.requests import Request
from starlette.responses import JSONResponse
from backend import discord
-from backend.models import FormResponse, ResponseList
+from backend.models.dtos import FormResponse, ResponseList
from backend.route import Route
from backend.validation import ErrorMessage, OkayResponse, api
diff --git a/backend/routes/forms/submit.py b/backend/routes/forms/submit.py
index 01c32cc..45636b7 100644
--- a/backend/routes/forms/submit.py
+++ b/backend/routes/forms/submit.py
@@ -19,7 +19,7 @@ from starlette.responses import JSONResponse
from backend import constants
from backend.authentication.user import User
-from backend.models import Form, FormResponse
+from backend.models.dtos import Form, FormResponse
from backend.route import Route
from backend.routes.auth.authorize import set_response_token
from backend.routes.forms.discover import AUTH_FORM
diff --git a/backend/routes/forms/unittesting.py b/backend/routes/forms/unittesting.py
index 57c3a86..469243c 100644
--- a/backend/routes/forms/unittesting.py
+++ b/backend/routes/forms/unittesting.py
@@ -8,7 +8,7 @@ import httpx
from httpx import HTTPStatusError
from backend.constants import SNEKBOX_URL
-from backend.models import Form, FormResponse
+from backend.models.dtos import Form, FormResponse
with Path("resources/unittest_template.py").open(encoding="utf8") as file:
TEST_TEMPLATE = file.read()
diff --git a/docker-compose.yml b/docker-compose.yml
index a9363f8..b8d58da 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -20,22 +20,42 @@ services:
ports:
- "127.0.0.1:6379:6379"
+ postgres:
+ image: postgres:16-alpine
+ environment:
+ POSTGRES_DB: backend
+ POSTGRES_PASSWORD: backend
+ POSTGRES_USER: backend
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U backend"]
+ interval: 2s
+ timeout: 1s
+ retries: 5
+ ports:
+ - 5000:5432
+
backend:
build: .
command: ["uvicorn", "--reload", "--host", "0.0.0.0", "backend:app"]
ports:
- "127.0.0.1:8000:8000"
depends_on:
- - mongo
- - snekbox
- - redis
+ mongo:
+ condition: service_started
+ snekbox:
+ condition: service_started
+ redis:
+ condition: service_started
+ postgres:
+ condition: service_healthy
tty: true
env_file:
- .env
volumes:
- .:/app:ro
environment:
- - DATABASE_URL=mongodb://forms-backend:forms-backend@mongo:27017
+ - MONGO_DATABASE_URL=mongodb://forms-backend:forms-backend@mongo:27017
+ - PSQL_DATABASE_URL=postgresql+psycopg_async://backend:backend@postgres:5432/backend
- SNEKBOX_URL=http://snekbox:8060/eval
- OAUTH2_CLIENT_ID
- OAUTH2_CLIENT_SECRET