source: main/waeup.sirp/trunk/src/waeup/sirp/authentication.txt @ 6954

Last change on this file since 6954 was 6746, checked in by uli, 13 years ago

Register main authentication.txt manually.

File size: 6.0 KB
Line 
1WAeUP portal authentication
2***************************
3
4We need to protect most pieces of our portals from unauthenticated
5access.
6
7Therefore users have to login to access main functionality and they
8are able to log out afterwards.
9
10Before we can check access we have to create an app:
11
12  >>> from zope.component.hooks import setSite # only needed in tests
13  >>> from waeup.sirp.app import University
14  >>> root = getRootFolder()
15  >>> u = University()
16  >>> root['app'] = u
17  >>> setSite(root['app'])                     # only needed in tests
18
19To make sure, we can 'watch' pages, we first have to initialize our
20test browser:
21
22  >>> from zope.testbrowser.testing import Browser
23  >>> browser = Browser()
24  >>> browser.handleErrors = False
25
26Creating users (principals)
27===========================
28
29Before we can login, we have to provide a user (``principal`` in Zope
30terms) with a password (and optional a title or description):
31
32  >>> root['app']['users'].addUser('bob', 'bobsecret',
33  ...                           title='Bob', description='A sample user')
34
35We can also add complete `Account` objects. An `Account` stores the
36user credentials and some metadata persistently:
37
38  >>> from waeup.sirp.authentication import Account
39  >>> alice = Account('alice', 'alicesecret')
40  >>> root['app']['users'].addAccount(alice)
41
42See ``users.txt`` for details about the UserContainer we use here.
43
44Users and local roles
45=====================
46
47Accounts also hold infos about local roles assigned to a user. In the
48beginning, users have no local roles at all:
49
50  >>> alice.getLocalRoles()
51  {}
52
53But we can tell an account, that Alice got some role for a certain
54object:
55
56  >>> chalet = object()
57  >>> root['app']['chalet'] = chalet
58  >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=True)
59
60Now Alice is the Big Boss:
61
62  >>> alice.getLocalRoles()
63  {'BigBoss': [<object object at 0x...>]}
64
65When we do not want Alice to be the Big Boss we can tell that too:
66
67  >>> alice.notifyLocalRoleChanged(chalet, 'BigBoss', granted=False)
68  >>> alice.getLocalRoles()
69  {}
70
71We can also use events to trigger such actions. This is recommended
72because we do not neccessarily know where Alice lives:
73
74  >>> from waeup.sirp.users import LocalRoleSetEvent
75  >>> from zope.event import notify
76  >>> notify(LocalRoleSetEvent(chalet, 'BigBoss', 'alice',
77  ...                          granted=True))
78  >>> alice.getLocalRoles()
79  {'BigBoss': [<object object at 0x...>]}
80
81When objects are deleted, local roles are also deleted
82semi-magically. This happens through event subscribers listening to
83IObjectRemovedEvents. The latters are naturally only fired when ZODB
84stored objects are removed. Furthermore this subscriber reads the
85internal local roles table.
86
87We create a faculty and grant Bob a local role:
88
89   >>> from zope.securitypolicy.interfaces import IPrincipalRoleManager
90   >>> from waeup.sirp.university.faculty import Faculty
91   >>> faculty = Faculty()
92   >>> root['app']['bobs_fac'] = faculty
93   >>> role_manager = IPrincipalRoleManager(faculty)
94   >>> role_manager.assignRoleToPrincipal(
95   ...    'waeup.PortalManager', 'bob')
96
97We notify the machinery about that fact:
98
99   >>> notify(LocalRoleSetEvent(faculty, 'waeup.PortalManager', 'bob',
100   ...                          granted=True))
101   >>> bob = root['app']['users']['bob']
102   >>> bob.getLocalRoles()
103   {'waeup.PortalManager': [<waeup.sirp...Faculty object at 0x...>]}
104
105When we delete the faculty from ZODB, also Bobs roles are modified:
106
107   >>> del root['app']['bobs_fac']
108   >>> bob.getLocalRoles()
109   {}
110
111If one notifies the machinery of a local role removal for an object
112that cannot have local roles, this will cause no trouble:
113
114   >>> mycontext = None #object()
115   >>> notify(LocalRoleSetEvent(
116   ...   mycontext, 'waeup.PortalManager', 'bob', granted=False
117   ... )) is None
118   True
119
120When an account get deleted, also the local roles of the owner get
121removed. Let's setup a local role for `alice`:
122
123   >>> faculty = Faculty()
124   >>> root['app']['alice_fac'] = faculty
125   >>> role_manager = IPrincipalRoleManager(faculty)
126   >>> role_manager.assignRoleToPrincipal(
127   ...    'waeup.PortalManager', 'alice')
128   >>> notify(LocalRoleSetEvent(faculty, 'waeup.PortalManager', 'alice',
129   ...                          granted=True))
130
131The local role is set now:
132
133   >>> from zope.securitypolicy.interfaces import IPrincipalRoleMap
134   >>> IPrincipalRoleMap(faculty).getPrincipalsAndRoles()
135   [('waeup.PortalManager', 'alice', PermissionSetting: Allow)]
136
137But when we delete Alices account from ZODB:
138
139   >>> del root['app']['users']['alice']
140   >>> IPrincipalRoleMap(faculty).getPrincipalsAndRoles()
141   []
142
143the local role has gone.
144
145
146Logging in via side bar
147=======================
148
149We can access the front page without restrictions:
150
151  >>> browser.open('http://localhost/app')
152  >>> print browser.headers['Status']
153  200 Ok
154
155We have to go to one of the login pages first:
156
157  >>> browser.open('http://localhost/app')
158  >>> browser.getLink('Login').click()
159  >>> print browser.headers['Status']
160  200 Ok
161
162There is a login form on tis page:
163
164  >>> 'form.login' in browser.contents
165  True
166
167  >>> 'form.logout' in browser.contents
168  False
169
170We use this form:
171
172  >>> browser.getControl(name='form.login').value = 'bob'
173  >>> browser.getControl(name='form.password').value = 'invalidpw'
174  >>> browser.getControl('Login').click()
175  >>> 'You entered wrong credentials' in browser.contents
176  True
177
178  >>> browser.getControl(name='form.login').value = 'bob'
179  >>> browser.getControl(name='form.password').value = 'bobsecret'
180  >>> browser.getControl('Login').click()
181
182Now the login form is gone. Instead we have the opportunity to logout:
183
184  >>> 'form.login' in browser.contents
185  False
186
187  >>> logout = browser.getLink('Logout')
188  >>> logout
189  <Link text='Logout' url='http://localhost/app/@@logout'>
190
191The user title is also displayed in the sidebar:
192
193  >>> 'Bob' in browser.contents
194  True
195
196We can also log out afterwards:
197
198  >>> logout.click()
199  >>> print browser.contents
200  <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"...
201  ...Login
202  ...
203
Note: See TracBrowser for help on using the repository browser.