adriangb / xpresso

A composable Python ASGI web framework
https://xpresso-api.dev/
MIT License
178 stars 4 forks source link

feat: rework security models #24

Closed adriangb closed 2 years ago

adriangb commented 2 years ago

At this point, Security models are directly pulled from FastAPI. Interestingly, they already reflect some of the Binder concepts we have here:

  1. Every model has a .model attribute that is the OpenAPI model.
  2. Every model has a __call__ so that it can serve as a dependency..

So I think we should try to formalize this by making a creating a Binder Protocol for them. Something like:

class SecurityGuard(Protocol):
     @overload
    def verify(self, connection: HTTPConnection) -> Any:
         ...
    @overload
    def verify(self, request: Request) -> Any:
        ...

class SecurityGuardMarker(Protocol):
    def register_parameter(self, param: inspect.Parameter) -> SecurityGuard:
        ...

class SecurityOpenAPI(Protocol):
    def get_openapi(self, model_name_map: ModelNameMap, schemas: Schemas) -> SecurityModel:
        ...

class SecurityOpenAPIMarker(Protocol):
    def register_parameter(self, param: inspect.Parameter) -> SecurityOpenAPI:
        ...

I think as part of this we may want remove the ability to create security models via the dependency injection system. Yes, it is possible, but it ads a lot of complexity. Yet the original use case of lazy-loading models is still valuable. A good compromise would be to accept an instance or a callable that returns an instance.

adriangb commented 2 years ago

On the other hand, it is pretty useful to say "this auth model depends on a dynamic config" and to be able to swap that out in tests. But that config is (hopefully) just some env vars, so setting those env vars before a test would not be a huge deal.

What does need dependency injection is something that actually validates tokens. But I reckon that'd be a 3rd party lib anyway