diff --git a/CHANGELOG.md b/CHANGELOG.md index 543a1d8..4011856 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## 0.3.4 -- Bug fixes in `.flask_sqlalchemy` +- Bug fixes in `.flask_sqlalchemy` and `.sqlalchemy` — `require_auth()` is unusable before this point! ## 0.3.3 diff --git a/src/suou/__init__.py b/src/suou/__init__.py index 39a7b30..51253f2 100644 --- a/src/suou/__init__.py +++ b/src/suou/__init__.py @@ -27,7 +27,7 @@ from .itertools import makelist, kwargs_prefix, ltuple, rtuple, additem from .i18n import I18n, JsonI18n, TomlI18n from .snowflake import Snowflake, SnowflakeGen -__version__ = "0.3.4-dev24" +__version__ = "0.3.4.rc1" __all__ = ( 'Siq', 'SiqCache', 'SiqType', 'SiqGen', 'StringCase', diff --git a/src/suou/flask_restx.py b/src/suou/flask_restx.py index 9d4955a..ecdf3da 100644 --- a/src/suou/flask_restx.py +++ b/src/suou/flask_restx.py @@ -54,7 +54,10 @@ class Api(_Api): Notably, all JSON is whitespace-free and .message is remapped to .error """ def handle_error(self, e): + ### XXX apparently this handle_error does not get called AT ALL. + print(e) res = super().handle_error(e) + print(res) if isinstance(res, Mapping) and 'message' in res: res['error'] = res['message'] del res['message'] diff --git a/src/suou/flask_sqlalchemy.py b/src/suou/flask_sqlalchemy.py index 7cd5b41..508e296 100644 --- a/src/suou/flask_sqlalchemy.py +++ b/src/suou/flask_sqlalchemy.py @@ -43,9 +43,9 @@ class FlaskAuthSrc(AuthSrc): def invalid_exc(self, msg: str = 'validation failed') -> Never: abort(400, msg) def required_exc(self): - abort(401) + abort(401, 'Login required') -def require_auth(cls: type[DeclarativeBase], db: SQLAlchemy) -> Callable[Any, Callable]: +def require_auth(cls: type[DeclarativeBase], db: SQLAlchemy) -> Callable: """ Make an auth_required() decorator for Flask views. @@ -67,7 +67,12 @@ def require_auth(cls: type[DeclarativeBase], db: SQLAlchemy) -> Callable[Any, Ca def super_secret_stuff(user): pass """ - return partial(require_auth_base, cls=cls, src=FlaskAuthSrc(db)) + def auth_required(**kwargs): + return require_auth_base(cls=cls, src=FlaskAuthSrc(db), **kwargs) + + auth_required.__doc__ = require_auth_base.__doc__ + + return auth_required __all__ = ('require_auth', ) diff --git a/src/suou/sqlalchemy.py b/src/suou/sqlalchemy.py index 2019424..8ff32a4 100644 --- a/src/suou/sqlalchemy.py +++ b/src/suou/sqlalchemy.py @@ -253,8 +253,7 @@ class AuthSrc(metaclass=ABCMeta): def require_auth_base(cls: type[DeclarativeBase], *, src: AuthSrc, column: str | Column[_T] = 'id', dest: str = 'user', - required: bool = False, signed: bool = False, sig_dest: str = 'signature', validators: Callable | Iterable[Callable] | None = None, - invalid_exc: Callable | None = None, required_exc: Callable | None = None): + required: bool = False, signed: bool = False, sig_dest: str = 'signature', validators: Callable | Iterable[Callable] | None = None): ''' Inject the current user into a view, given the Authorization: Bearer header. @@ -275,11 +274,11 @@ def require_auth_base(cls: type[DeclarativeBase], *, src: AuthSrc, column: str | except Exception: return None - def _default_invalid(msg: str): + def _default_invalid(msg: str = 'validation failed'): raise ValueError(msg) - invalid_exc = invalid_exc or _default_invalid - required_exc = required_exc or (lambda: _default_invalid()) + invalid_exc = src.invalid_exc or _default_invalid + required_exc = src.required_exc or (lambda: _default_invalid()) def decorator(func: Callable): @wraps(func)