Search code examples
pythonflaskstormpath

How to implement "login as" admin function with `stormpath-flask`


I'm implementing a "login as" feature for our admin dashboard.

Basically I'd love to allow our admins to see and use the website as if she has logged in as a specific customer. For example, if Trish rang us up and asked a question, our admin should be able to login as Trish and see exactly what Trish is seeing.

And here is the code I've written assuming we have a valid email:

from app import stormpath_manager
from flask.ext.stormpath import login_user
... 
main_cloud_directory = stormpath_manager.client.directories.search({
    'name': 'Directory Name'})[0]
accounts = main_cloud_directory.accounts.search({'email': email})
if accounts.size == 1:
    account = accounts[0]
    login_user(account, remember=False)
    return redirect('/settings')
else:
    abort(404)

When I run the code, I got AttributeError: Account has no attribute 'is_active' back.

To set the context for this:

  1. I understand that login_user is expecting to see an User object which extends stormpath.resource.Account whereas the account object we received have no is_active defined.

  2. I have code in other part of the app working just fine if I send login_user the User object returned by stormpath_account = StormpathUser.create(...) method.

  3. I am also aware that I am mixing the stormpath-flask with the raw stormpath-python-sdk and I guess that I really should be using stormpath-flask methods.

  4. I can see that with Account.email, I can create a User object using User.from_login but this won't work because we don't store password on our end.

I'm wondering are there any way I can take an Account returned by the search method and turn it into a User? What would you do to make this working?

Thanks,

Alex


Solution

  • I'm the author of this library, so wanted to hop in here =)

    The answer is yes: you can indeed transform a normal Account object into a valid Flask-Stormpath User object. Here's how:

    from flask.ext.stormpath import login_user
    from flask.ext.stormpath.models import User
    
    from app import stormpath_manager
    
    
    # ...
    
    
    main_cloud_directory = stormpath_manager.client.directories.search({
        'name': 'Directory Name'
    })[0]
    accounts = main_cloud_directory.accounts.search({'email': email})
    
    if accounts.size == 1:
        account = accounts[0]
        account.__class__ = User
        login_user(account, remember=False)
    
        return redirect('/settings')
    else:
        abort(404)
    

    The important bit is the account.__class__ = User. This uses some meta magic to convert the class into a User object =) This is what I do behind the scenes in the library as well, for instance: https://github.com/stormpath/stormpath-flask/blob/4185f2f41574156870ce1aa990d34e4ad84357be/flask_stormpath/models.py#L125-L126

    Hope that helps!