Skip to content
Draft
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 Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ deploy:
--workers $(DEPLOY_WORKERS) \
--log-syslog \
-p /tmp/BingoMaker.pid -n $(DEPLOY_NAME) \
"app:create_app()"
"app:aws_create_app()"

test:
@uv run pytest -m "not localstack"
Expand Down
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ dependencies = [
"boto3>=1.35.50",
"flask>=3.0.3",
"pillow>=11.0.0",
"flask-cognito-lib>=1.9.2",
]

[tool.uv]
Expand Down
2 changes: 1 addition & 1 deletion src/app/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .app import create_app
from .app import aws_create_app, create_app # noqa: F401

if __name__ == "__main__":
create_app().run(port=8080)
19 changes: 13 additions & 6 deletions src/app/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,32 @@
from data.persistence import TilePoolDB, tile_to_dict
from game.game import Board

from . import image_routes, tilepool_routes
from .config import Config, LocalDiskConfig
from . import auth_routes, image_routes, tilepool_routes
from .config import CloudAWSConfig, Config, LocalDiskConfig


def create_app(config: type[Config] = LocalDiskConfig) -> Flask:
def aws_create_app() -> Flask:
return create_app(CloudAWSConfig)


def create_app(config_class: type[Config] = LocalDiskConfig, TESTING: bool = False) -> Flask:
app = Flask(__name__)

app.config.from_object(config)
app.config.from_object(config_class())
app.config["TESTING"] = TESTING
auth_routes.cognito_app(app)

@app.route("/")
def index():
return render_template("index.html")

@app.route("/tilesets")
def tilesets():
return render_template("tilesets.html")

app.register_blueprint(tilepool_routes.bp)
app.register_blueprint(image_routes.bp)
app.register_blueprint(auth_routes.bp)

@app.route("/bingocard/<tilepoolId>")
def generate_card(tilepoolId: str):
Expand Down Expand Up @@ -51,4 +58,4 @@ def generate_card(tilepoolId: str):
"grid": [tile_to_dict(tile) for row in board.board for tile in row],
}

return app
return app
43 changes: 43 additions & 0 deletions src/app/auth_routes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from flask import Blueprint, Flask, redirect
from flask_cognito_lib import CognitoAuth
from flask_cognito_lib.decorators import (
cognito_login,
cognito_login_callback,
cognito_logout,
cognito_refresh_callback,
)

bp = Blueprint("auth", __name__)


def cognito_app(app: Flask):
return CognitoAuth(app)


@bp.get("/login")
@cognito_login
def login():
pass


@bp.get("/postlogin")
@cognito_login_callback
def post_login():
return redirect("/")


@bp.get("/logout")
@cognito_logout
def logout():
return "Logged out"


@bp.get("/postlogout")
def post_logout():
return "Logged out"


@bp.get("/refresh")
@cognito_refresh_callback
def refresh():
return "Refreshed"
63 changes: 60 additions & 3 deletions src/app/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import os
import boto3

from data import DynamoTilePoolDB, FileTilePoolDB, MemoryTilePoolDB
from images import (
Expand All @@ -12,6 +12,14 @@
class Config:
TESTING = False
DEBUG = False
SECRET_KEY = "07c56596b48f48b3a749a6969e64fadc"
AWS_REGION = "us-east-1"
AWS_COGNITO_DOMAIN = "https://bingomaker.auth.us-east-1.amazoncognito.com"
AWS_COGNITO_REDIRECT_URL = "https://bingo.drek.cloud/postlogin"
AWS_COGNITO_LOGOUT_URL = "https://bingo.drek.cloud/postlogout"
AWS_COGNITO_REFRESH_FLOW_ENABLED = True
AWS_COGNITO_REFRESH_COOKIE_ENCRYPTED = True
AWS_COGNITO_REFRESH_COOKIE_AGE_SECONDS = 86400

@property
def DB(self):
Expand Down Expand Up @@ -71,10 +79,59 @@ def IMAGES(self):


class CloudAWSConfig(Config):
def __init__(self):
self.client = boto3.client("secretsmanager", region_name=self.AWS_REGION)
self._DB = None
self._IMAGES = None
self._AWS_COGNITO_USER_POOL_CLIENT_SECRET = ""
self._AWS_COGNITO_USER_POOL_CLIENT_ID = ""
self._AWS_COGNITO_USER_POOL_ID = ""
self._S3_BUCKET_NAME = ""

@property
def DB(self):
return DynamoTilePoolDB()
if self._DB is None:
self._DB = DynamoTilePoolDB()
return self._DB

@property
def S3_BUCKET_NAME(self) -> str:
if not self._S3_BUCKET_NAME:
self._S3_BUCKET_NAME = self.client.get_secret_value(SecretId="S3BucketName")[
"SecretString"
]

return self._S3_BUCKET_NAME

@property
def IMAGES(self):
return S3ImageManager(os.environ["S3_BUCKET_NAME"], LocalReferenceCounts("counts"))
if self._IMAGES is None:
self._IMAGES = S3ImageManager(self.S3_BUCKET_NAME, LocalReferenceCounts("counts"))
return self._IMAGES

@property
def AWS_COGNITO_USER_POOL_CLIENT_SECRET(self):
if not self._AWS_COGNITO_USER_POOL_CLIENT_SECRET:
self._AWS_COGNITO_USER_POOL_CLIENT_SECRET = self.client.get_secret_value(
SecretId="CognitoUserPoolClientSecret"
)["SecretString"]

return self._AWS_COGNITO_USER_POOL_CLIENT_SECRET

@property
def AWS_COGNITO_USER_POOL_CLIENT_ID(self):
if not self._AWS_COGNITO_USER_POOL_CLIENT_ID:
self._AWS_COGNITO_USER_POOL_CLIENT_ID = self.client.get_secret_value(
SecretId="CognitoUserPoolClientId"
)["SecretString"]

return self._AWS_COGNITO_USER_POOL_CLIENT_ID

@property
def AWS_COGNITO_USER_POOL_ID(self):
if not self._AWS_COGNITO_USER_POOL_ID:
self._AWS_COGNITO_USER_POOL_ID = self.client.get_secret_value(
SecretId="CognitoUserPoolId"
)["SecretString"]

return self._AWS_COGNITO_USER_POOL_ID
2 changes: 1 addition & 1 deletion tests/test_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def db_data(db: MemoryTilePoolDB):

@pytest.fixture
def app(db_data: TilePoolDB, image_manager: ImageManager):
app = create_app()
app = create_app(TESTING=True)
app.config.update(TESTING=True, DB=db_data, IMAGES=image_manager)
return app

Expand Down
Loading