source: main/waeup.kofa/trunk/src/waeup/kofa/students/tests/test_authentication.py

Last change on this file was 15606, checked in by Henrik Bettermann, 5 years ago

Parents access implementation (part 1)

  • Property svn:keywords set to Id
File size: 9.4 KB
RevLine 
[7193]1## $Id: test_authentication.py 15606 2019-09-24 17:21:28Z henrik $
[6668]2##
[7114]3## Copyright (C) 2011 Uli Fouquet & Henrik Bettermann
[6668]4## This program is free software; you can redistribute it and/or modify
5## it under the terms of the GNU General Public License as published by
6## the Free Software Foundation; either version 2 of the License, or
7## (at your option) any later version.
[7193]8##
[6668]9## This program is distributed in the hope that it will be useful,
10## but WITHOUT ANY WARRANTY; without even the implied warranty of
11## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12## GNU General Public License for more details.
[7193]13##
[6668]14## You should have received a copy of the GNU General Public License
15## along with this program; if not, write to the Free Software
16## Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17##
18import unittest
[9334]19from datetime import datetime, timedelta
[6680]20from zope.authentication.interfaces import IAuthentication
[6668]21from zope.component import provideUtility, queryUtility, getGlobalSiteManager
22from zope.interface.verify import verifyClass, verifyObject
23from zope.password.password import SSHAPasswordManager
24from zope.password.interfaces import IPasswordManager
25from zope.pluggableauth import PluggableAuthentication
[6756]26from zope.security.interfaces import Unauthorized
[6680]27from zope.securitypolicy.role import Role
28from zope.securitypolicy.interfaces import IRole, Allow
[7811]29from waeup.kofa.authentication import get_principal_role_manager
30from waeup.kofa.interfaces import IAuthPluginUtility, IUserAccount
31from waeup.kofa.students.authentication import (
[6668]32    StudentsAuthenticatorSetup, StudentAccount)
[7811]33from waeup.kofa.students.tests.test_browser import StudentsFullSetup
34from waeup.kofa.testing import FunctionalLayer
[6668]35
36class StudentsAuthenticatorSetupTests(unittest.TestCase):
37
38    def test_iface(self):
39        obj = StudentsAuthenticatorSetup()
40        verifyClass(IAuthPluginUtility, StudentsAuthenticatorSetup)
41        verifyObject(IAuthPluginUtility, obj)
42        return
43
44    def test_register(self):
45        # Make sure registration works.
46        setup = StudentsAuthenticatorSetup()
47        pau = PluggableAuthentication()
48        setup.register(pau)
49        self.assertTrue('students' in pau.authenticatorPlugins)
50        return
51
52    def test_unregister(self):
53        # Make sure deregistration works.
54        setup = StudentsAuthenticatorSetup()
55        pau = PluggableAuthentication()
56        pau.authenticatorPlugins = ('students')
57        setup.unregister(pau)
58        self.assertTrue('students' not in pau.authenticatorPlugins)
59        return
60
61
62class FakeStudent(object):
63    student_id = 'test_stud'
[7364]64    display_fullname = 'Test User'
[6668]65    password = None
[7221]66    email = None
[7233]67    phone = None
[8983]68    suspended = False
[9334]69    temp_password_minutes = 10
[6668]70
[9334]71    def setTempPassword(self, user, password):
72        passwordmanager = queryUtility(IPasswordManager, 'SSHA')
73        self.temp_password = {}
74        self.temp_password[
75            'password'] = passwordmanager.encodePassword(password)
76        self.temp_password['user'] = user
77        self.temp_password['timestamp'] = datetime.utcnow()
[6680]78
[9334]79    def getTempPassword(self):
80        temp_password_dict = getattr(self, 'temp_password', None)
81        if temp_password_dict is not None:
82            delta = timedelta(minutes=self.temp_password_minutes)
83            now = datetime.utcnow()
84            if now < temp_password_dict.get('timestamp') + delta:
85                return temp_password_dict.get('password')
86            else:
87                # Unset temporary password if expired
88                self.temp_password = None
89        return None
90
[15606]91    def getParentsPassword(self):
92        parents_password_dict = getattr(self, 'parents_password', None)
93        if parents_password_dict is not None:
94            delta = timedelta(minutes=self.temp_password_minutes)
95            now = datetime.utcnow()
96            if now < parents_password_dict.get('timestamp') + delta:
97                return parents_password_dict.get('password')
98            else:
99                # Unset temporary password if expired
100                self.parents_password = None
101        return None
[9334]102
[15606]103
104
[6680]105class MinimalPAU(PluggableAuthentication):
106    def getPrincipal(self, id):
107        return 'faked principal'
108
[6668]109class StudentAccountTests(unittest.TestCase):
110
111    def setUp(self):
112        self.fake_stud = FakeStudent()
113        self.account = StudentAccount(self.fake_stud)
[6680]114
115        # We provide a minimal PAU
116        pau = MinimalPAU()
117        provideUtility(pau, IAuthentication)
118
119        # We register a role
120        test_role = Role('waeup.test.Role', 'Testing Role')
121        provideUtility(test_role, IRole, name='waeup.test.Role')
122
[6668]123        # We have to setup a password manager utility manually as we
124        # have no functional test. In functional tests this would
125        # happen automatically, but it would take a lot more time to
126        # run the tests.
127        provideUtility(
128            SSHAPasswordManager(), IPasswordManager, 'SSHA')
129        return
130
131    def tearDown(self):
[6680]132        self.account.roles = [] # make sure roles are reset
133        gsm = getGlobalSiteManager()
134        to_clean = []
135        # Clear up utilities registered in setUp
136        to_clean.append(
137            (IPasswordManager, queryUtility(
138                    IPasswordManager, name='SSHA', default=None)))
139        to_clean.append(
140            (IAuthentication, queryUtility(IAuthentication, default=None)))
141        to_clean.append(
142            (IRole, queryUtility(IRole, name='test.Role', default=None)))
143        for iface, elem in to_clean:
144            if elem is not None:
145                gsm.unregisterUtility(elem, iface)
[6668]146        return
147
148    def test_iface(self):
149        verifyClass(IUserAccount, StudentAccount)
150        verifyObject(IUserAccount, self.account)
151        return
152
153    def test_set_password(self):
154        # make sure we can set a password.
155        self.account.setPassword('secret')
156        self.assertTrue(self.fake_stud.password is not None)
157        # we do not store plaintext passwords
158        self.assertTrue(self.fake_stud.password != 'secret')
[8351]159        # passwords are stored as bytestreams
160        self.assertTrue(isinstance(self.fake_stud.password, basestring))
161        self.assertFalse(isinstance(self.fake_stud.password, unicode))
[6668]162        return
163
164    def test_check_password(self):
165        # make sure we can check a password.
166        self.account.setPassword('secret')
167        result1 = self.account.checkPassword(None)
168        result2 = self.account.checkPassword('nonsense')
169        result3 = self.account.checkPassword('secret')
170        self.assertEqual(result1, False)
171        self.assertEqual(result2, False)
172        self.assertEqual(result3, True)
173        return
[6680]174
[9334]175    def test_check_temp_password(self):
176        # make sure that, if a temp password is set,
177        # this password is used for authentication
178        self.account.setPassword('secret')
179        self.fake_stud.setTempPassword(user='beate', password='temp_secret')
180        result1 = self.account.checkPassword('secret')
181        result2 = self.account.checkPassword(None)
182        result3 = self.account.checkPassword('nonsense')
183        result4 = self.account.checkPassword('temp_secret')
184        self.assertEqual(result1, False)
185        self.assertEqual(result2, False)
186        self.assertEqual(result3, False)
187        self.assertEqual(result4, True)
188        # if the temp password is expired, the original password
189        # is used again
190        delta = timedelta(minutes=11)
191        self.fake_stud.temp_password['timestamp'] = datetime.utcnow() - delta
192        result5 = self.account.checkPassword('temp_secret')
193        result6 = self.account.checkPassword('secret')
194        self.assertEqual(result5, False)
195        self.assertEqual(result6, True)
196        return
197
[7138]198    def test_check_unset_password(self):
199        # empty and unset passwords do not match anything
200        self.fake_stud.password = None
201        result1 = self.account.checkPassword('')
202        self.fake_stud.password = ''
203        result2 = self.account.checkPassword('')
204        self.assertEqual(result1, False)
205        self.assertEqual(result2, False)
206        return
207
208    def test_check_password_no_string(self):
209        # if passed in password is not a string, we gain no access
210        self.fake_stud.password = 'secret'
211        result1 = self.account.checkPassword(None)
212        result2 = self.account.checkPassword(object())
213        self.assertEqual(result1, False)
214        self.assertEqual(result2, False)
215        return
216
[6680]217    def test_role_set(self):
218        # make sure we can set roles for principals denoted by account
219        prm = get_principal_role_manager()
220        self.assertEqual(prm.getPrincipalsAndRoles(), [])
221        self.account.roles = ['waeup.test.Role']
222        self.assertEqual(
223            prm.getPrincipalsAndRoles(),
224            [('waeup.test.Role', 'test_stud', Allow)])
225        return
226
227    def test_role_get(self):
228        # make sure we can get roles set for an account
229        self.assertEqual(self.account.roles, [])
230        self.account.roles = ['waeup.test.Role',] # set a role
231        self.assertEqual(self.account.roles, ['waeup.test.Role'])
232        return
[6756]233
234
235
236class FunctionalStudentAuthTests(StudentsFullSetup):
237
238    layer = FunctionalLayer
239
240    def setUp(self):
241        super(FunctionalStudentAuthTests, self).setUp()
242        return
243
244    def tearDown(self):
245        super(FunctionalStudentAuthTests, self).tearDown()
246        return
247
248    def test_reset_protected_anonymous(self):
249        # anonymous users cannot reset others passwords
250        self.assertRaises(
251            Unauthorized,
[7114]252            self.browser.open, self.student_path + '/change_password')
[6756]253        return
Note: See TracBrowser for help on using the repository browser.