Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/authentication/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ async def authenticate(
user = User(
token,
user_details,
await discord.get_member(request.state.db, user_details["id"]),
await discord.get_member(user_details["id"]),
)
if await user.fetch_admin_status(request.state.db):
scopes.append("admin")
Expand Down
4 changes: 2 additions & 2 deletions backend/authentication/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,9 +67,9 @@ async def fetch_admin_status(self, database: Database) -> bool:

return self.admin

async def refresh_data(self, database: Database) -> None:
async def refresh_data(self) -> None:
"""Fetches user data from discord, and updates the instance."""
self.member = await discord.get_member(database, self.payload["id"])
self.member = await discord.get_member(self.payload["id"])

if self.member:
self.payload = self.member.user.dict()
Expand Down
3 changes: 3 additions & 0 deletions backend/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from enum import Enum

from dotenv import load_dotenv
from redis.asyncio import Redis as _Redis

load_dotenv()

Expand All @@ -12,6 +13,8 @@
MONGO_DATABASE = os.getenv("MONGO_DATABASE", "pydis_forms")
SNEKBOX_URL = os.getenv("SNEKBOX_URL", "http://snekbox.default.svc.cluster.local/eval")

REDIS_CLIENT = _Redis.from_url(os.getenv("REDIS_URL"), encoding="utf-8")
Comment thread
ChrisLovering marked this conversation as resolved.

PRODUCTION = os.getenv("PRODUCTION", "True").lower() != "false"
PRODUCTION_URL = "https://forms.pythondiscord.com"

Expand Down
32 changes: 7 additions & 25 deletions backend/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ async def _fetch_member_api(member_id: str) -> models.DiscordMember | None:


async def get_member(
database: Database,
user_id: str,
*,
force_refresh: bool = False,
Expand All @@ -135,34 +134,17 @@ async def get_member(
If `force_refresh` is True, the cache is skipped and the entry is updated.
None may be returned if the member object does not exist.
"""
collection = database.get_collection("discord_members")
member_key = f"forms-backend:member_cache:{user_id}"

if force_refresh:
await collection.delete_one({"user": user_id})

# `create_index` creates the index if it does not exist, or passes
# This handles TTL on member objects
await collection.create_index(
"inserted_at",
expireAfterSeconds=60 * 60, # 1 hour
name="inserted_at",
)

result = await collection.find_one({"user": user_id})

if result is not None:
return models.DiscordMember(**json.loads(result["data"]))
if not force_refresh:
result = await constants.REDIS_CLIENT.get(member_key)
if result:
return models.DiscordMember(**json.loads(result))

member = await _fetch_member_api(user_id)
if member:
await constants.REDIS_CLIENT.set(member_key, member.json(), ex=60 * 60)

if not member:
return None

await collection.insert_one({
"user": user_id,
"data": member.json(),
"inserted_at": datetime.datetime.now(tz=datetime.UTC),
})
return member


Expand Down
2 changes: 1 addition & 1 deletion backend/routes/auth/authorize.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async def process_token(
return AUTH_FAILURE

user_id = user_details["id"]
member = await get_member(request.state.db, user_id, force_refresh=True)
member = await get_member(user_id, force_refresh=True)

max_age = datetime.timedelta(seconds=int(bearer_token["expires_in"]))
token_expiry = interaction_start + max_age
Expand Down
4 changes: 2 additions & 2 deletions backend/routes/discord.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class MemberRequest(pydantic.BaseModel):
async def delete(self, request: Request) -> JSONResponse:
"""Force a resync of the cache for the given user."""
body = await request.json()
member = await discord.get_member(request.state.db, body["user_id"], force_refresh=True)
member = await discord.get_member(body["user_id"], force_refresh=True)

if member:
return JSONResponse(member.dict())
Expand All @@ -75,7 +75,7 @@ async def delete(self, request: Request) -> JSONResponse:
async def get(self, request: Request) -> JSONResponse:
"""Get a user's roles on the configured server."""
body = await request.json()
member = await discord.get_member(request.state.db, body["user_id"])
member = await discord.get_member(body["user_id"])

if not member:
return NOT_FOUND_EXCEPTION
Expand Down
2 changes: 1 addition & 1 deletion backend/routes/forms/submit.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ async def post(self, request: Request) -> JSONResponse:
try:
if hasattr(request.user, User.refresh_data.__name__):
old = request.user.token
await request.user.refresh_data(request.state.db)
await request.user.refresh_data()

if old != request.user.token:
try:
Expand Down
13 changes: 9 additions & 4 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ services:
mongo:
image: mongo:latest
ports:
- 27017:27017
- "127.0.0.1:27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: forms-backend
MONGO_INITDB_ROOT_PASSWORD: forms-backend
Expand All @@ -15,16 +15,20 @@ services:
- "127.0.0.1:8060:8060"
privileged: true

redis:
image: redis:latest
ports:
- "127.0.0.1:6379:6379"

backend:
build:
context: .
dockerfile: Dockerfile
build: .
command: ["uvicorn", "--reload", "--host", "0.0.0.0", "backend:app"]
ports:
- "127.0.0.1:8000:8000"
depends_on:
- mongo
- snekbox
- redis
tty: true
env_file:
- .env
Expand All @@ -38,3 +42,4 @@ services:
- ALLOWED_URL
- DEBUG=true
- PRODUCTION=false
- REDIS_URL=redis://redis:6379
Loading