Search code examples
pythongoogle-app-enginesessionwebapp2

How to have usernames with webapp2's User model?


I successfully with webapp2 can authenticate and login/logout users and I have a decorator to know whether a user is logged in and this works:

class MyPageHandler(NewBaseHandler):
    """
    Only accessible to users that are logged in
    """
    @user_required
    def get(self):
        user = self.auth.get_user_by_session()
        self.render_template('mypage.htm', {'user': self.auth.get_user_by_session()})

Now I want to add something basic as a username and I suspect that I might not have to subclass the User model provided with webapp2_extras since it is an Expando model. Could you tell me how to add a username or update a user with a username? I didn't try but I believe I can display an auth_id but it's not the same thing as the username?

Thanks

Update

It seems as the User model is an expando model you "just add proprties" like this for example when creating a user:

    username = self.request.POST.get('username')
    password = self.request.POST.get('password')
    # Passing password_raw=password so password will be hashed
    # Returns a tuple, where first value is BOOL. If True ok, If False no new user is created
    user = self.auth.store.user_model.create_user(username, password_raw=password)
    user.name = username

I didn't thoroughly test the code above but it seems that with webapp2 we won't need to subclass the User class to get the functionality.

Solution / Workaround

class SecureRequestHandler(BaseHandler):
    """
        Only accessible to users that are logged in
    """
    @user_required
    def get(self, **kwargs):
        a = self.app.config.get('foo')
        auser = self.auth.get_user_by_session() 
        userid = auser['user_id']
        user = auth_models.User.get_by_id(auser['user_id'])
        try:
            return "Secure zone %s <a href='%s'>Logout</a>" % (user.name, self.auth_config['logout_url'])
        except (AttributeError, KeyError), e:
            return "Secure zone"

Solution

  • hope this help

    from webapp2_extras.appengine.auth.models import User
    from ndb import key, model
    
    class MUser(User): # child class of User
        displayname = model.StringProperty() # show on screen, auto create 'user-{id}'
        lastaccess = model.DateTimeProperty(auto_now=True)
    
        @classmethod
        def update_or_insert_user(cls, user):
            """update some user's prop if exited else create new muser
            return : MUser object or None
            """
            u = MUser.get_by_auth_id(user.email())
            if u is None:                               
                ok, u = MUser.create_user(user.email(), id=newid)
                if ok == True:
                    u.displayname = 'user-'+str(u.get_id())
                else:
                    log.error('create new user error : ' + user.email())
                    u = None
            else :          
                u.put() # Update last access (auto fill def in model class)
    
            return u
    
    class MyPageHandler(NewBaseHandler):
        """
        Only accessible to users that are logged in
        """
        @user_required
        def get(self):
            user = self.get_current_muser()
            self.render_template('mypage.htm', {'user': user.displayname })
    
        def get_current_muser(self):
            # come from gae login page, convert current gae user to muser
            user = users.get_current_user() # google users
            if user:
                # user have login, try to create or update
                log.info('create user')
                mu = MUser.update_or_insert_user(user)
                if mu:
                    # save to session
                    self.session['muserid'] = mu.key.id()
                    return mu
    
            return None