The Avatar

Every Enamel page has an instance variable avatarId which comes into play ONLY when there is a valid authentication and the user has authenticated. The avatarId is unique for each individual user session.

It's demonstration and use is simple

class Index(pages.Standard):
    childPages = {'login': pages.Login}

    def body(self):
        if self.avatarId:
            user = self.avatarId.username
        else:
            user = "Anonymous"

        return tags.div[
            tags.a(href="/login")["Login"],
            tags.br,
            "You are logged in as: ", user
        ]

The default avatarId object holds a username and password only. The Enamel class holds an instance variable avatar which should be a reference to an object to be used as an avatar. This should not be overridden without first investigating how the avatar is handled by an authenticator object.

The default avatar is authentication.UsernamePasswordAvatar?.

The first step to make your create and use a different avatar object is to create your own Authenticator. Using the provided classes this is not as hard as it sounds.

class MyAuthenticator(authentication.DatabaseAuthenticator):
    def handleAuthenticationResult(self, result, username, password):
        if result:
            return self.enamel.avatar(username, password)
        else:
            raise authentication.UnauthorizedLogin()

The handleAuthenticationResult method is called by all of the default authentication classes with the result of the database query, or LDAP lookup, and passed the origional username and password. In the case of the database authentication the database lookup was already passed the username and password so the result is None if either credential is incorrect.

Say we want to include the users unique ID as well though.

...
class MyAvatar:
    def __init__(self, username = "", password = "", id = 0):
        self.username = username
        self.password = password
        self.userId = id

class MyAuthenticator(authentication.DatabaseAuthenticator):
    def handleAuthenticationResult(self, result, username, password):
        userId = result[0]
        if result:
            return MyAvatar(username, password, userId)
        else:
            raise authentication.UnauthorizedLogin()

class Test(enamel.Enamel):
    indexPage = Index
    loginPage = pages.Login
    storage = SQLStorage('sqlite:///test.db')
    anonymousAccess = True
    authenticator = MyAuthenticator

    server = servers.TwistedWeb
    port = 8080

We are now able to access self.avatarId.userId from any Enamel page. We needn't set the Enamel avatar variable because we have already overridden it by reimplementing the handleAuthenticationResult method.

The LDAP authenticator can be used and changed in the exact same way. Look at the source code for enamel/authentication.py to gain more insight into how it can be modified.