Skip to content

Commit

Permalink
Let flask_admin peek defaults without crashing
Browse files Browse the repository at this point in the history
The flask_admin database frontend attempts to peek column default values
to fill form fields, but calls the functions generating dynamic defaults
with a context of None. Paper over this.

Fixes: #89

Signed-off-by: Nils Philippsen <[email protected]>
  • Loading branch information
nphilipp authored and abompard committed Dec 6, 2024
1 parent 4620ac2 commit d51c5f9
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 3 deletions.
15 changes: 12 additions & 3 deletions tahrir_api/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ def as_dict(self):


def generate_default_id(context):
# Allow flask_admin to peek without crashing.
if not context:
return None
return context.current_parameters["name"].lower().replace(" ", "-")


Expand Down Expand Up @@ -182,8 +185,8 @@ def as_dict(self):
)


def invitation_id_default(context):
return hashlib.md5(salt_default(context).encode("utf-8")).hexdigest()
def invitation_id_default():
return hashlib.md5(salt_default().encode("utf-8")).hexdigest()


class Invitation(DeclarativeBase):
Expand Down Expand Up @@ -236,6 +239,9 @@ class CurrentValue(DeclarativeBase):


def recipient_default(context):
# Allow flask_admin to peek without crashing.
if not context:
return None
person_id = context.current_parameters["person_id"]
salt = context.current_parameters["salt"]
person_email = context.connection.scalar(select(Person.email).where(Person.id == person_id))
Expand All @@ -246,11 +252,14 @@ def get_assertion_recipient(email, salt):
return hashlib.sha256((email + salt).encode("utf-8")).hexdigest()


def salt_default(context):
def salt_default():
return str(uuid.uuid4())


def assertion_id_default(context):
# Allow flask_admin to peek without crashing.
if not context:
return None
person_id = context.current_parameters["person_id"]
badge_id = context.current_parameters["badge_id"]
return f"{badge_id} -> {person_id}"
Expand Down
34 changes: 34 additions & 0 deletions tests/test_model.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import pytest
from sqlalchemy import inspect
from sqlalchemy.exc import NoInspectionAvailable
from sqlalchemy.orm import Mapper

from tahrir_api import model


def get_models_columns_with_defaults():
models_columns_as_params = []

for name, thing in model.__dict__.items():
if isinstance(thing, type):
try:
inspected = inspect(thing)
except NoInspectionAvailable:
continue

if isinstance(inspected, Mapper):
for colname, column in inspected.c.items():
default = getattr(column, "default", None)
if default is None:
continue
if hasattr(default, "arg"):
models_columns_as_params.append(
pytest.param(column, id=f"{name}.{colname}"))

return models_columns_as_params


@pytest.mark.parametrize("column", get_models_columns_with_defaults())
def test_safe_column_default(column):
if getattr(column.default, "is_callable", False):
column.default.arg(None)

0 comments on commit d51c5f9

Please sign in to comment.