pallets-eco / flask-security

Quick and simple security for Flask applications
MIT License
635 stars 155 forks source link

Adding user attributes after successful login? #796

Closed esranonff closed 1 year ago

esranonff commented 1 year ago

Hello!

When a user logs in successfully, I want to query the database for various relationship data and add it to the current_user object.

I thought the following would work, but that turns out to be for the login view rather than post-successful login, so I'm wondering if there's another view that I should be decorating because I can't see one that would work from the docs?

# Add fields to the user when they log in
@app.security.login_context_processor
def add_user_attributes():
        current_user.play_partner_count = PlayPartner.query.filter_by(initiator_user_id=current_user.id).count()

The error I am getting is:

AttributeError: 'AnonymousUser' object has no attribute 'id'

and I get this before I can even display the log in form.

if I update the code as follows:

# Add fields to the user when they log in
@app.security.login_context_processor
def add_user_attributes():
        if current_user.is_anonymous is False:
                current_user.play_partner_count = PlayPartner.query.filter_by(initiator_user_id=current_user.id).count()

Then I get

TypeError: 'NoneType' object is not iterable

Presumably there's a way to do this without having to override the entire login function?

jwag956 commented 1 year ago

I am not quite certain what you are trying to accomplish. If you simply want to provide information to your front-end based on the current user - why not create an endpoint that your front-end calls after successful login?

Note that 'currrent_user' isn't a database object nor does it persist after the request is done.

esranonff commented 1 year ago

Note that 'currrent_user' isn't a database object nor does it persist after the request is done.

Ah, then that's me holding it upside down and doing it wrong :rofl:

Thanks, I'll close this and find another approach.

jwag956 commented 1 year ago

And to be more precise/accurate - current_user is a proxy to the User model which is a DB object - but one you have to manage - if you want to update a field in your user model (say if you have added fields to it) you can start with current_user.my_added_field = "something great" - then you need to 'commit' it - for SQLAlchemy style databases - you need to do a userdatastore.put().

A context manager is not the correct place for this - if you need to update the User model as part of successful login - you should subscribe to the 'user_authenticated' signal (see docs for info about signals).