Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

custom converter with flask-login doesn't have access to session #4053

Closed
sileht opened this issue May 14, 2021 · 3 comments · Fixed by #4055
Closed

custom converter with flask-login doesn't have access to session #4053

sileht opened this issue May 14, 2021 · 3 comments · Fixed by #4055
Assignees
Milestone

Comments

@sileht
Copy link

sileht commented May 14, 2021

Hi there,

With the flask 2.0.0 upgrade I get the following backtrace in a test suite:

Traceback (most recent call last):
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask/app.py", line 2050, in wsgi_app
    ctx.push()
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask/ctx.py", line 381, in push
    self.match_request()
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask/ctx.py", line 349, in match_request
    result = self.url_adapter.match(return_rule=True)  # type: ignore
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/werkzeug/routing.py", line 1958, in match
    rv = rule.match(path, method)
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/werkzeug/routing.py", line 931, in match
    value = self._converters[name].to_python(value)
  File "xxxxxxxxxxxxxxxxxxxxx/xxxxx/web.py", line 61, in to_python
    if not user.is_authenticated:
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/werkzeug/local.py", line 422, in __get__
    obj = instance._get_current_object()
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/werkzeug/local.py", line 544, in _get_current_object
    return self.__local()  # type: ignore
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask_login/utils.py", line 26, in <lambda>
    current_user = LocalProxy(lambda: _get_user())
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask_login/utils.py", line 346, in _get_user
    current_app.login_manager._load_user()
  File "xxxxxxxxxxxxxxxxxxxxx/.tox/py39/lib/python3.9/site-packages/flask_login/login_manager.py", line 316, in _load_user
    user_id = session.get('_user_id')
AttributeError: 'NoneType' object has no attribute 'get'

The pseudo code in the falling test, looks like:

@app.route("/test/<installation:installation>")
@flask_login.login_required
def test_route_with_installation(installation):
    return flask.jsonify({....})

with app.test_client(use_cookies=True) as client:
    r = client.get("/test/123")

The session access that failed is done in the installation converter and it looks like:

class InstallationConverter(routing.IntegerConverter):
    def to_python(self, value: str) -> typing.Optional[Installation]:
          user = flask_login.current_user
          if not user.is_authenticated:
              return None
          ...
          return Installation(...)

Environment:

  • Python version: 3.9.5
  • Flask version: 2.0.0

If you need more info, just ask :)

@davidism davidism reopened this May 14, 2021
@davidism davidism changed the title flask 2.0.0 issue with flask-login and test_client() custom converter with flask-login doesn't have access to session May 14, 2021
@davidism
Copy link
Member

davidism commented May 14, 2021

This is because of #3776, which asked to make the matched request available when loading the session object. However, that means the session object isn't available when matching the request. It's impossible to have both. I think it makes more sense to have the session available to custom converters, so I'll roll back #3794.

cc @zeha @mbpreble

@davidism
Copy link
Member

davidism commented May 14, 2021

After rolling back #3794, if you're writing a custom session loader and need the endpoint, then you can call:

_request_ctx_stack.top.match_request()

If you need both, you'll need to write your converters so they will still match without the session, then call match_request() manually in your session code like above. That way the matching will run twice, first without the session, then with it to do the real match.

@davidism davidism added this to the 2.0.1 milestone May 14, 2021
@davidism davidism self-assigned this May 14, 2021
@zeha
Copy link

zeha commented May 14, 2021

Alright, thanks for the workaround.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 29, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants