pahrohfit / sanic-beskar

Strong, Simple, and Precise, (and now async!) security for Sanic APIs
http://sanic-beskar.readthedocs.io/en/latest/
MIT License
12 stars 2 forks source link

Error Running Registration Example #69

Open debarone opened 1 month ago

debarone commented 1 month ago

Error Running Registration Example

A sanic_beskar.exceptions.BeskarError(from an initial async_sender.api.SenderError) is raised when registering a new user on the /register endpoint of the example\register.py example with the following details: SenderError: Does not specify any recipients(to,cc,bcc) (401).

Your environment

Steps to reproduce

  1. Clone and checkout the master branch of the sanic_beskar repo
  2. Setup an environment for a particular python version in the .python-version file
  3. Install all dependencies via poetry
  4. Run the registration example as follows: poetry run python example/register.py

    Note: Line 246 of example/register has been edited to include the confirmation_sender kwarg as follows: await _guard.send_registration_email(email, user=new_user, confirmation_sender="you@whatever.com") Without the confirmation_sender kwarg, a sanic_beskar.exceptions.BeskarError is raised with details: A sender is required to send confirmation email (401)

  5. Test the /register endpoint with curl
    curl localhost:8000/register -X POST -d '{"username": "Sidius", "password": "str0ng_p4ssw0rd", "email": "sidius@gc.com"}' | jq '.'

Expected behaviour

A JSON response below should be returned with a status code of 200.

{
  "message": "successfully sent registration email to user Sidius"
}

Actual behaviour

Instead a sanic_beskar.exceptions.BeskarError is raised, returning JSON response with a status code of 401 as shown below.

Paths have been redacted but the line numbers should be accurate

{
"description": "Unauthorized",
"status": 401,
"message": "BeskarError: fail sending email -- SenderError: Does not specify any recipients(to,cc,bcc) (401)",
"path": "/register",
"args": {},
"exceptions": [
{
"type": "SenderError",
"exception": "Does not specify any recipients(to,cc,bcc)",
"frames": [
{
"file": "<venv_path>/buzz/tools.py",
"line": 289,
"name": "handle_errors",
"src": "yield"
},
{
"file": "<project_path>/sanic-beskar/sanic_beskar/base.py",
"line": 1811,
"name": "send_token_email",
"src": "notification[\"result\"] = await self.app.ctx.mail.send_message(msg)"
},
{
"file": "<venv_path>/async_sender/api.py",
"line": 112,
"name": "send_message",
"src": "await self.send(Message(*args, **kwargs))"
},
{
"file": "<venv_path>/async_sender/api.py",
"line": 107,
"name": "send",
"src": "message.validate()"
},
{
"file": "<venv_path>async_sender/api.py",
"line": 176,
"name": "validate",
"src": "raise SenderError(\"Does not specify any recipients(to,cc,bcc)\")"
}
]
},
{
"type": "BeskarError",
"exception": "BeskarError: fail sending email -- SenderError: Does not specify any recipients(to,cc,bcc) (401)",
"frames": [
{
"file": "<venv_path>/sanic/app.py",
"line": 1385,
"name": "handle_request",
"src": "response = await response"
},
{
"file": "<project_path>/example/register.py",
"line": 246,
"name": "register",
"src": "await _guard.send_registration_email(email, user=new_user, confirmation_sender=\"you@whatever.com\")"
},
{
"file": "<project_path>/sanic-beskar/sanic_beskar/base.py",
"line": 1646,
"name": "send_registration_email",
"src": "_return: dict = await self.send_token_email("
},
{
"file": "<project_path>/sanic-beskar/sanic_beskar/base.py",
"line": 1797,
"name": "send_token_email",
"src": "with BeskarError.handle_errors(\"fail sending email\"):"
},
{
"file": "<pyenv_path>/contextlib.py",
"line": 158,
"name": "__exit__",
"src": "self.gen.throw(typ, value, traceback)"
},
{
"file": "<venv_path>/buzz/tools.py",
"line": 304,
"name": "handle_errors",
"src": "raise exc_builder(raise_exc_class, final_message, *args, **kwargs).with_traceback(trace) from err"
},
{
"file": "<venv_path>/buzz/tools.py",
"line": 289,
"name": "handle_errors",
"src": "yield"
},
{
"file": "<project_path>/sanic-beskar/sanic_beskar/base.py",
"line": 1811,
"name": "send_token_email",
"src": "notification[\"result\"] = await self.app.ctx.mail.send_message(msg)"
},
{
"file": "<venv_path>/async_sender/api.py",
"line": 112,
"name": "send_message",
"src": "await self.send(Message(*args, **kwargs))"
},
{
"file": "<venv_path>/async_sender/api.py",
"line": 107,
"name": "send",
"src": "message.validate()"
},
{
"file": "<venv_path>/async_sender/api.py",
"line": 176,
"name": "validate",
"src": "raise SenderError(\"Does not specify any recipients(to,cc,bcc)\")"
}
]
}
]
}
debarone commented 1 month ago

Some More Context on the Error

The async_sender.api.SenderError happens because the async_sender.api.Message seems to be initialised twice by the code at sanic_beskar/base.py; once at Line 1802 and the second time at Line 1811

Your Environment

Demonstration

  1. Add debug logging to async_sender library(this was done in my virtualenv) below is the diff
    11a12,14
    > import logging
    > logging.basicConfig(level=logging.DEBUG)
    > logger = logging.getLogger(__name__)
    167a171
    >         logger.debug(f"Initiliasation: {self.message_id} - {(self.to, self.cc, self.bcc)}")
    174a179
    >         logger.debug(f"Validation: {self.message_id} - {(self.to, self.cc, self.bcc)}")
  2. Run the registration example as follows: poetry run python example/register.py
  3. Test the /register endpoint with curl
    curl localhost:8000/register -X POST -d '{"username": "Sidius", "password": "str0ng_p4ssw0rd", "email": "sidius@gc.com"}' | jq '.'

Analysis