Authentication ************** We need to protect most pieces of our portals from unauthenticated access. Therefore users have to login to access main functionality and they are able to log out afterwards. Before we can check access we have to create an app: >>> from zope.component.hooks import setSite # only needed in tests >>> from waeup.ikoba.app import Company >>> root = getRootFolder() >>> u = Company() >>> root['app'] = u >>> setSite(root['app']) # only needed in tests To make sure, we can 'watch' pages, we first have to initialize our test browser: >>> from zope.testbrowser.testing import Browser >>> browser = Browser() >>> browser.handleErrors = False Creating officers ================= Before we can login, we have to provide a user (``principal`` in Zope terms) with a password (and optional a title or description): >>> root['app']['users'].addUser('bob', 'bobsecret', ... title='Bob', description='A sample user') We can also add complete `Account` objects. An `Account` stores the user credentials and some metadata persistently: >>> from waeup.ikoba.authentication import Account >>> alice = Account('alice', 'alicesecret',roles=['waeup.ManageDataCenter']) >>> root['app']['users'].addAccount(alice) See ``userscontainer.txt`` for details about the UsersContainer we use here. Officers and local roles ======================== Accounts also hold infos about local roles assigned to a user. In the beginning, users have the local owner role of their own account object: >>> alice.getLocalRoles() {'waeup.local.Owner': []} User automatically get the global ProductsOfficer role: >>> alice.getSiteRolesForPrincipal() ['waeup.ManageDataCenter', 'waeup.ProductsOfficer'] We can tell an account, that Alice got some role for another object: >>> chalet = object() >>> root['app']['chalet'] = chalet >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=True) Now Alice is the Big Boss: >>> alice.getLocalRoles() {'BigBoss': []} When we do not want Alice to be the Big Boss we can tell that too: >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=False) >>> alice.getLocalRoles() {'waeup.local.Owner': []} We can also use events to trigger such actions. This is recommended because we do not neccessarily know where Alice lives: >>> from waeup.ikoba.authentication import LocalRoleSetEvent >>> from zope.event import notify >>> notify(LocalRoleSetEvent(chalet, 'BigBoss', 'alice', ... granted=True)) >>> alice.getLocalRoles() {'BigBoss': []} When objects are deleted, local roles are also deleted semi-magically. This happens through event subscribers listening to IObjectRemovedEvents. The latters are naturally only fired when ZODB stored objects are removed. Furthermore this subscriber reads the internal local roles table. Logging in via side bar ======================= We can access the front page without restrictions: >>> browser.open('http://localhost/app') >>> print browser.headers['Status'] 200 Ok We have to go to one of the login pages first: >>> browser.open('http://localhost/app') >>> browser.getLink('Login').click() >>> print browser.headers['Status'] 200 Ok There is a login form on tis page: >>> 'form.login' in browser.contents True >>> 'form.logout' in browser.contents False We use this form: >>> browser.getControl(name='form.login').value = 'bob' >>> browser.getControl(name='form.password').value = 'invalidpw' >>> browser.getControl('Login').click() >>> 'You entered invalid credentials' in browser.contents True >>> browser.getControl(name='form.login').value = 'bob' >>> browser.getControl(name='form.password').value = 'bobsecret' >>> browser.getControl('Login').click() Now the login form is gone. Instead we have the opportunity to logout: >>> 'form.login' in browser.contents False >>> logout = browser.getLink('Logout') >>> logout The user title is also displayed in the sidebar: >>> 'Bob' in browser.contents True We can also log out afterwards: >>> logout.click() >>> print browser.contents