Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests / auth.py @ 50f74340

History | View | Annotate | Download (60.1 kB)

1 d2633501 Kostas Papadimitriou
# Copyright 2011 GRNET S.A. All rights reserved.
2 d2633501 Kostas Papadimitriou
#
3 d2633501 Kostas Papadimitriou
# Redistribution and use in source and binary forms, with or
4 d2633501 Kostas Papadimitriou
# without modification, are permitted provided that the following
5 d2633501 Kostas Papadimitriou
# conditions are met:
6 d2633501 Kostas Papadimitriou
#
7 d2633501 Kostas Papadimitriou
#   1. Redistributions of source code must retain the above
8 d2633501 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
9 d2633501 Kostas Papadimitriou
#      disclaimer.
10 d2633501 Kostas Papadimitriou
#
11 d2633501 Kostas Papadimitriou
#   2. Redistributions in binary form must reproduce the above
12 d2633501 Kostas Papadimitriou
#      copyright notice, this list of conditions and the following
13 d2633501 Kostas Papadimitriou
#      disclaimer in the documentation and/or other materials
14 d2633501 Kostas Papadimitriou
#      provided with the distribution.
15 d2633501 Kostas Papadimitriou
#
16 d2633501 Kostas Papadimitriou
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 d2633501 Kostas Papadimitriou
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 d2633501 Kostas Papadimitriou
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 d2633501 Kostas Papadimitriou
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 d2633501 Kostas Papadimitriou
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 d2633501 Kostas Papadimitriou
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 d2633501 Kostas Papadimitriou
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 d2633501 Kostas Papadimitriou
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 d2633501 Kostas Papadimitriou
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 d2633501 Kostas Papadimitriou
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 d2633501 Kostas Papadimitriou
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 d2633501 Kostas Papadimitriou
# POSSIBILITY OF SUCH DAMAGE.
28 d2633501 Kostas Papadimitriou
#
29 d2633501 Kostas Papadimitriou
# The views and conclusions contained in the software and
30 d2633501 Kostas Papadimitriou
# documentation are those of the authors and should not be
31 d2633501 Kostas Papadimitriou
# interpreted as representing official policies, either expressed
32 d2633501 Kostas Papadimitriou
# or implied, of GRNET S.A.
33 d2633501 Kostas Papadimitriou
34 5b65fb47 Kostas Papadimitriou
import urlparse
35 5b65fb47 Kostas Papadimitriou
import urllib
36 5b65fb47 Kostas Papadimitriou
37 1ac3349d Kostas Papadimitriou
from astakos.im.tests.common import *
38 d2633501 Kostas Papadimitriou
39 5f28aa14 Kostas Papadimitriou
ui_url = lambda url: '/' + astakos_settings.BASE_PATH + '/ui/%s' % url
40 5f28aa14 Kostas Papadimitriou
41 d2633501 Kostas Papadimitriou
42 d2633501 Kostas Papadimitriou
class ShibbolethTests(TestCase):
43 d2633501 Kostas Papadimitriou
    """
44 d2633501 Kostas Papadimitriou
    Testing shibboleth authentication.
45 d2633501 Kostas Papadimitriou
    """
46 d2633501 Kostas Papadimitriou
47 d2633501 Kostas Papadimitriou
    def setUp(self):
48 d2633501 Kostas Papadimitriou
        self.client = ShibbolethClient()
49 9d20fe23 Kostas Papadimitriou
        astakos_settings.IM_MODULES = ['local', 'shibboleth']
50 9d20fe23 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
51 d2633501 Kostas Papadimitriou
52 baa9073a Kostas Papadimitriou
    def tearDown(self):
53 baa9073a Kostas Papadimitriou
        AstakosUser.objects.all().delete()
54 baa9073a Kostas Papadimitriou
55 0a7a4104 Kostas Papadimitriou
    @im_settings(FORCE_PROFILE_UPDATE=False)
56 d2633501 Kostas Papadimitriou
    def test_create_account(self):
57 ba50648c Kostas Papadimitriou
58 d2633501 Kostas Papadimitriou
        client = ShibbolethClient()
59 d2633501 Kostas Papadimitriou
60 d2633501 Kostas Papadimitriou
        # shibboleth views validation
61 d2633501 Kostas Papadimitriou
        # eepn required
62 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url('login/shibboleth?'), follow=True)
63 e24d0e0d Kostas Papadimitriou
        self.assertContains(r, messages.SHIBBOLETH_MISSING_EPPN % {
64 a248ebbb Kostas Papadimitriou
            'domain': astakos_settings.BASE_HOST,
65 31bc3a62 Kostas Papadimitriou
            'contact_email': settings.CONTACT_EMAIL
66 e24d0e0d Kostas Papadimitriou
        })
67 d2633501 Kostas Papadimitriou
        client.set_tokens(eppn="kpapeppn")
68 ba50648c Kostas Papadimitriou
69 31fdafa8 Kostas Papadimitriou
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = True
70 d2633501 Kostas Papadimitriou
        # shibboleth user info required
71 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url('login/shibboleth?'), follow=True)
72 2e90e3ec Kostas Papadimitriou
        self.assertContains(r, messages.SHIBBOLETH_MISSING_NAME)
73 31fdafa8 Kostas Papadimitriou
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = False
74 d2633501 Kostas Papadimitriou
75 d2633501 Kostas Papadimitriou
        # shibboleth logged us in
76 e7cb4085 Kostas Papadimitriou
        client.set_tokens(mail="kpap@synnefo.org", eppn="kpapeppn",
77 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou",
78 ba50648c Kostas Papadimitriou
                          ep_affiliation="Test Affiliation")
79 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url('login/shibboleth?'), follow=True)
80 9d20fe23 Kostas Papadimitriou
        token = PendingThirdPartyUser.objects.get().token
81 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('signup?third_party_token=%s' % token))
82 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
83 d2633501 Kostas Papadimitriou
84 d2633501 Kostas Papadimitriou
        # a new pending user created
85 d2633501 Kostas Papadimitriou
        pending_user = PendingThirdPartyUser.objects.get(
86 d2633501 Kostas Papadimitriou
            third_party_identifier="kpapeppn")
87 d2633501 Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
88 ba50648c Kostas Papadimitriou
        # keep the token for future use
89 d2633501 Kostas Papadimitriou
        token = pending_user.token
90 d2633501 Kostas Papadimitriou
        # from now on no shibboleth headers are sent to the server
91 d2633501 Kostas Papadimitriou
        client.reset_tokens()
92 d2633501 Kostas Papadimitriou
93 ba50648c Kostas Papadimitriou
        # this is the old way, it should fail, to avoid pending user take over
94 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url('shibboleth/signup/%s' % pending_user.username))
95 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
96 d2633501 Kostas Papadimitriou
97 9d20fe23 Kostas Papadimitriou
        # this is the signup unique url associated with the pending user
98 9d20fe23 Kostas Papadimitriou
        # created
99 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url('signup/?third_party_token=%s' % token))
100 9d20fe23 Kostas Papadimitriou
        identifier = pending_user.third_party_identifier
101 9d20fe23 Kostas Papadimitriou
        post_data = {'third_party_identifier': identifier,
102 d2633501 Kostas Papadimitriou
                     'first_name': 'Kostas',
103 d2633501 Kostas Papadimitriou
                     'third_party_token': token,
104 d2633501 Kostas Papadimitriou
                     'last_name': 'Mitroglou',
105 9d20fe23 Kostas Papadimitriou
                     'provider': 'shibboleth'}
106 ba50648c Kostas Papadimitriou
107 0a7a4104 Kostas Papadimitriou
        signup_url = reverse('signup')
108 0a7a4104 Kostas Papadimitriou
109 ba50648c Kostas Papadimitriou
        # invlid email
110 ba50648c Kostas Papadimitriou
        post_data['email'] = 'kpap'
111 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data)
112 8ab484ea Kostas Papadimitriou
        self.assertContains(r, token)
113 ba50648c Kostas Papadimitriou
114 ba50648c Kostas Papadimitriou
        # existing email
115 ba50648c Kostas Papadimitriou
        existing_user = get_local_user('test@test.com')
116 ba50648c Kostas Papadimitriou
        post_data['email'] = 'test@test.com'
117 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data)
118 ba50648c Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_USED)
119 ba50648c Kostas Papadimitriou
        existing_user.delete()
120 ba50648c Kostas Papadimitriou
121 ba50648c Kostas Papadimitriou
        # and finally a valid signup
122 e7cb4085 Kostas Papadimitriou
        post_data['email'] = 'kpap@synnefo.org'
123 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data, follow=True)
124 e7cb4085 Kostas Papadimitriou
        self.assertContains(r, messages.VERIFICATION_SENT)
125 ba50648c Kostas Papadimitriou
126 e7cb4085 Kostas Papadimitriou
        # entires commited as expected
127 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
128 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUserAuthProvider.objects.count(), 1)
129 ba50648c Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 0)
130 d2633501 Kostas Papadimitriou
131 ba50648c Kostas Papadimitriou
        # provider info stored
132 ba50648c Kostas Papadimitriou
        provider = AstakosUserAuthProvider.objects.get(module="shibboleth")
133 ba50648c Kostas Papadimitriou
        self.assertEqual(provider.affiliation, 'Test Affiliation')
134 830747d2 Kostas Papadimitriou
        self.assertEqual(provider.info['email'], u'kpap@synnefo.org')
135 830747d2 Kostas Papadimitriou
        self.assertEqual(provider.info['eppn'], u'kpapeppn')
136 830747d2 Kostas Papadimitriou
        self.assertEqual(provider.info['name'], u'Kostas Papadimitriou')
137 830747d2 Kostas Papadimitriou
        self.assertTrue('headers' in provider.info)
138 d2633501 Kostas Papadimitriou
139 e7cb4085 Kostas Papadimitriou
        # login (not activated yet)
140 e7cb4085 Kostas Papadimitriou
        client.set_tokens(mail="kpap@synnefo.org", eppn="kpapeppn",
141 830747d2 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
142 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
143 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'is pending moderation')
144 d2633501 Kostas Papadimitriou
145 e7cb4085 Kostas Papadimitriou
        # admin activates the user
146 e7cb4085 Kostas Papadimitriou
        u = AstakosUser.objects.get(username="kpap@synnefo.org")
147 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
148 e7cb4085 Kostas Papadimitriou
        activation_result = backend.verify_user(u, u.verification_code)
149 e7cb4085 Kostas Papadimitriou
        activation_result = backend.accept_user(u)
150 e7cb4085 Kostas Papadimitriou
        self.assertFalse(activation_result.is_error())
151 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(activation_result, u)
152 d2633501 Kostas Papadimitriou
        self.assertEqual(u.is_active, True)
153 d2633501 Kostas Papadimitriou
154 ba50648c Kostas Papadimitriou
        # we see our profile
155 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
156 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('landing'))
157 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
158 d2633501 Kostas Papadimitriou
159 d2633501 Kostas Papadimitriou
    def test_existing(self):
160 ba50648c Kostas Papadimitriou
        """
161 ba50648c Kostas Papadimitriou
        Test adding of third party login to an existing account
162 ba50648c Kostas Papadimitriou
        """
163 ba50648c Kostas Papadimitriou
164 ba50648c Kostas Papadimitriou
        # this is our existing user
165 e7cb4085 Kostas Papadimitriou
        existing_user = get_local_user('kpap@synnefo.org')
166 e7cb4085 Kostas Papadimitriou
        existing_inactive = get_local_user('kpap-inactive@synnefo.org')
167 478ece6c Kostas Papadimitriou
        existing_inactive.is_active = False
168 478ece6c Kostas Papadimitriou
        existing_inactive.save()
169 478ece6c Kostas Papadimitriou
170 e7cb4085 Kostas Papadimitriou
        existing_unverified = get_local_user('kpap-unverified@synnefo.org')
171 478ece6c Kostas Papadimitriou
        existing_unverified.is_active = False
172 478ece6c Kostas Papadimitriou
        existing_unverified.activation_sent = None
173 478ece6c Kostas Papadimitriou
        existing_unverified.email_verified = False
174 478ece6c Kostas Papadimitriou
        existing_unverified.is_verified = False
175 478ece6c Kostas Papadimitriou
        existing_unverified.save()
176 d2633501 Kostas Papadimitriou
177 d2633501 Kostas Papadimitriou
        client = ShibbolethClient()
178 d2633501 Kostas Papadimitriou
        # shibboleth logged us in, notice that we use different email
179 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
180 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
181 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
182 d2633501 Kostas Papadimitriou
183 d2633501 Kostas Papadimitriou
        # a new pending user created
184 d2633501 Kostas Papadimitriou
        pending_user = PendingThirdPartyUser.objects.get()
185 9d20fe23 Kostas Papadimitriou
        token = pending_user.token
186 d2633501 Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
187 d2633501 Kostas Papadimitriou
        pending_key = pending_user.token
188 d2633501 Kostas Papadimitriou
        client.reset_tokens()
189 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url("signup?third_party_token=%s" % token))
190 d2633501 Kostas Papadimitriou
191 e585664e Christos Stavrakakis
        form = r.context['login_form']
192 9d20fe23 Kostas Papadimitriou
        signupdata = copy.copy(form.initial)
193 e7cb4085 Kostas Papadimitriou
        signupdata['email'] = 'kpap@synnefo.org'
194 9d20fe23 Kostas Papadimitriou
        signupdata['third_party_token'] = token
195 9d20fe23 Kostas Papadimitriou
        signupdata['provider'] = 'shibboleth'
196 2a88057d Christos Stavrakakis
        signupdata.pop('id', None)
197 d2633501 Kostas Papadimitriou
198 478ece6c Kostas Papadimitriou
        # the email exists to another user
199 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url("signup"), signupdata)
200 478ece6c Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
201 478ece6c Kostas Papadimitriou
                               "address")
202 478ece6c Kostas Papadimitriou
        # change the case, still cannot create
203 e7cb4085 Kostas Papadimitriou
        signupdata['email'] = 'KPAP@synnefo.org'
204 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url("signup"), signupdata)
205 478ece6c Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
206 478ece6c Kostas Papadimitriou
                               "address")
207 478ece6c Kostas Papadimitriou
        # inactive user
208 e7cb4085 Kostas Papadimitriou
        signupdata['email'] = 'KPAP-inactive@synnefo.org'
209 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url("signup"), signupdata)
210 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
211 9d20fe23 Kostas Papadimitriou
                               "address")
212 d2633501 Kostas Papadimitriou
213 478ece6c Kostas Papadimitriou
        # unverified user, this should pass, old entry will be deleted
214 e7cb4085 Kostas Papadimitriou
        signupdata['email'] = 'KAPAP-unverified@synnefo.org'
215 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url("signup"), signupdata)
216 478ece6c Kostas Papadimitriou
217 d2633501 Kostas Papadimitriou
        post_data = {'password': 'password',
218 e7cb4085 Kostas Papadimitriou
                     'username': 'kpap@synnefo.org'}
219 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url('local'), post_data, follow=True)
220 9d20fe23 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
221 9d20fe23 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
222 9d20fe23 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
223 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
224 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "enabled for this account")
225 9d20fe23 Kostas Papadimitriou
        client.reset_tokens()
226 9d20fe23 Kostas Papadimitriou
227 9d20fe23 Kostas Papadimitriou
        user = existing_user
228 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('shibboleth'))
229 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('local',
230 9d20fe23 Kostas Papadimitriou
                                               auth_backend='astakos'))
231 d2633501 Kostas Papadimitriou
        client.logout()
232 d2633501 Kostas Papadimitriou
233 d2633501 Kostas Papadimitriou
        # look Ma, i can login with both my shibboleth and local account
234 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
235 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
236 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
237 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
238 e7cb4085 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.email == "kpap@synnefo.org")
239 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('landing'))
240 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
241 d2633501 Kostas Papadimitriou
        client.logout()
242 d2633501 Kostas Papadimitriou
        client.reset_tokens()
243 ba50648c Kostas Papadimitriou
244 ba50648c Kostas Papadimitriou
        # logged out
245 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("profile"), follow=True)
246 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
247 d2633501 Kostas Papadimitriou
248 ba50648c Kostas Papadimitriou
        # login with local account also works
249 d2633501 Kostas Papadimitriou
        post_data = {'password': 'password',
250 e7cb4085 Kostas Papadimitriou
                     'username': 'kpap@synnefo.org'}
251 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), post_data, follow=True)
252 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
253 e7cb4085 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.email == "kpap@synnefo.org")
254 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('landing'))
255 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
256 d2633501 Kostas Papadimitriou
257 ba50648c Kostas Papadimitriou
        # cannot add the same eppn
258 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn",
259 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
260 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
261 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('landing'))
262 ba50648c Kostas Papadimitriou
        self.assertTrue(r.status_code, 200)
263 ba50648c Kostas Papadimitriou
        self.assertEquals(existing_user.auth_providers.count(), 2)
264 d2633501 Kostas Papadimitriou
265 9d20fe23 Kostas Papadimitriou
        # only one allowed by default
266 ba50648c Kostas Papadimitriou
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn2",
267 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", ep_affiliation="affil2")
268 9d20fe23 Kostas Papadimitriou
        prov = auth_providers.get_provider('shibboleth')
269 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
270 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "Failed to add")
271 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('profile'))
272 ba50648c Kostas Papadimitriou
        self.assertTrue(r.status_code, 200)
273 9d20fe23 Kostas Papadimitriou
        self.assertEquals(existing_user.auth_providers.count(), 2)
274 d2633501 Kostas Papadimitriou
        client.logout()
275 ba50648c Kostas Papadimitriou
        client.reset_tokens()
276 ba50648c Kostas Papadimitriou
277 ba50648c Kostas Papadimitriou
        # cannot login with another eppn
278 e7cb4085 Kostas Papadimitriou
        client.set_tokens(mail="kpap@synnefo.org", eppn="kpapeppninvalid",
279 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
280 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
281 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
282 d2633501 Kostas Papadimitriou
283 478ece6c Kostas Papadimitriou
        # cannot
284 478ece6c Kostas Papadimitriou
285 f432088a Kostas Papadimitriou
        # lets remove local password
286 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
287 e7cb4085 Kostas Papadimitriou
                                       email="kpap@synnefo.org")
288 9d20fe23 Kostas Papadimitriou
        remove_local_url = user.get_auth_provider('local').get_remove_url
289 9d20fe23 Kostas Papadimitriou
        remove_shibbo_url = user.get_auth_provider('shibboleth',
290 9d20fe23 Kostas Papadimitriou
                                                   'kpapeppn').get_remove_url
291 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
292 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimtriou")
293 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
294 f432088a Kostas Papadimitriou
        client.reset_tokens()
295 ba50648c Kostas Papadimitriou
296 17138f12 Kostas Papadimitriou
        # only POST is allowed (for CSRF protection)
297 17138f12 Kostas Papadimitriou
        r = client.get(remove_local_url, follow=True)
298 17138f12 Kostas Papadimitriou
        self.assertEqual(r.status_code, 405)
299 17138f12 Kostas Papadimitriou
300 17138f12 Kostas Papadimitriou
        r = client.post(remove_local_url, follow=True)
301 ba50648c Kostas Papadimitriou
        # 2 providers left
302 f432088a Kostas Papadimitriou
        self.assertEqual(user.auth_providers.count(), 1)
303 ba50648c Kostas Papadimitriou
        # cannot remove last provider
304 17138f12 Kostas Papadimitriou
        r = client.post(remove_shibbo_url)
305 f432088a Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)
306 f432088a Kostas Papadimitriou
        self.client.logout()
307 ba50648c Kostas Papadimitriou
308 ba50648c Kostas Papadimitriou
        # cannot login using local credentials (notice we use another client)
309 f432088a Kostas Papadimitriou
        post_data = {'password': 'password',
310 e7cb4085 Kostas Papadimitriou
                     'username': 'kpap@synnefo.org'}
311 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), post_data, follow=True)
312 f432088a Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
313 f432088a Kostas Papadimitriou
314 ba50648c Kostas Papadimitriou
        # we can reenable the local provider by setting a password
315 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("password_change"), follow=True)
316 5f28aa14 Kostas Papadimitriou
        r = client.post(ui_url("password_change"), {'new_password1': '111',
317 8fb8d0cf Giorgos Korfiatis
                                                    'new_password2': '111'},
318 f432088a Kostas Papadimitriou
                        follow=True)
319 f432088a Kostas Papadimitriou
        user = r.context['request'].user
320 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('local'))
321 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('shibboleth'))
322 f432088a Kostas Papadimitriou
        self.assertTrue(user.check_password('111'))
323 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_usable_password())
324 36f1eabb Kostas Papadimitriou
325 36f1eabb Kostas Papadimitriou
        # change password via profile form
326 36f1eabb Kostas Papadimitriou
        r = client.post(ui_url("profile"), {
327 36f1eabb Kostas Papadimitriou
            'old_password': '111',
328 36f1eabb Kostas Papadimitriou
            'new_password': '',
329 36f1eabb Kostas Papadimitriou
            'new_password2': '',
330 36f1eabb Kostas Papadimitriou
            'change_password': 'on',
331 36f1eabb Kostas Papadimitriou
        }, follow=False)
332 36f1eabb Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
333 36f1eabb Kostas Papadimitriou
        self.assertFalse(r.context['profile_form'].is_valid())
334 36f1eabb Kostas Papadimitriou
335 f432088a Kostas Papadimitriou
        self.client.logout()
336 ba50648c Kostas Papadimitriou
337 ba50648c Kostas Papadimitriou
        # now we can login
338 f432088a Kostas Papadimitriou
        post_data = {'password': '111',
339 e7cb4085 Kostas Papadimitriou
                     'username': 'kpap@synnefo.org'}
340 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), post_data, follow=True)
341 f432088a Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
342 f432088a Kostas Papadimitriou
343 ba50648c Kostas Papadimitriou
        client.reset_tokens()
344 f432088a Kostas Papadimitriou
345 ba50648c Kostas Papadimitriou
        # we cannot take over another shibboleth identifier
346 e7cb4085 Kostas Papadimitriou
        user2 = get_local_user('another@synnefo.org')
347 f432088a Kostas Papadimitriou
        user2.add_auth_provider('shibboleth', identifier='existingeppn')
348 ba50648c Kostas Papadimitriou
        # login
349 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
350 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
351 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
352 ba50648c Kostas Papadimitriou
        # try to assign existing shibboleth identifier of another user
353 9d20fe23 Kostas Papadimitriou
        client.set_tokens(mail="kpap_second@shibboleth.gr",
354 9d20fe23 Kostas Papadimitriou
                          eppn="existingeppn", cn="Kostas Papadimitriou")
355 5f28aa14 Kostas Papadimitriou
        r = client.get(ui_url("login/shibboleth?"), follow=True)
356 c34abd9c Kostas Papadimitriou
        self.assertContains(r, "is already in use")
357 2e90e3ec Kostas Papadimitriou
358 d2633501 Kostas Papadimitriou
359 478ece6c Kostas Papadimitriou
class TestLocal(TestCase):
360 d2633501 Kostas Papadimitriou
361 2e90e3ec Kostas Papadimitriou
    def setUp(self):
362 e7cb4085 Kostas Papadimitriou
        settings.ADMINS = (('admin', 'support@cloud.synnefo.org'),)
363 e7cb4085 Kostas Papadimitriou
        settings.SERVER_EMAIL = 'no-reply@synnefo.org'
364 9d20fe23 Kostas Papadimitriou
        self._orig_moderation = astakos_settings.MODERATION_ENABLED
365 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_MODERATION_ENABLED = True
366 9d20fe23 Kostas Papadimitriou
367 9d20fe23 Kostas Papadimitriou
    def tearDown(self):
368 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_MODERATION_ENABLED = self._orig_moderation
369 baa9073a Kostas Papadimitriou
        AstakosUser.objects.all().delete()
370 2e90e3ec Kostas Papadimitriou
371 7233d542 Kostas Papadimitriou
    def test_no_moderation(self):
372 ba50648c Kostas Papadimitriou
        # disable moderation
373 7233d542 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = False
374 ba50648c Kostas Papadimitriou
375 ba50648c Kostas Papadimitriou
        # create a new user
376 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url("signup"))
377 7233d542 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
378 e7cb4085 Kostas Papadimitriou
        data = {'email': 'kpap@synnefo.org', 'password1': 'password',
379 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
380 7233d542 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
381 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url("signup"), data)
382 ba50648c Kostas Papadimitriou
383 ba50648c Kostas Papadimitriou
        # user created
384 7233d542 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
385 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
386 e7cb4085 Kostas Papadimitriou
                                       email="kpap@synnefo.org")
387 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.username, 'kpap@synnefo.org')
388 7233d542 Kostas Papadimitriou
        self.assertEqual(user.has_auth_provider('local'), True)
389 7233d542 Kostas Papadimitriou
        self.assertFalse(user.is_active)
390 7233d542 Kostas Papadimitriou
391 ba50648c Kostas Papadimitriou
        # user (but not admin) gets notified
392 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('support@cloud.synnefo.org')), 0)
393 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
394 7233d542 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
395 d2633501 Kostas Papadimitriou
396 e5966bd9 Kostas Papadimitriou
    def test_email_case(self):
397 e5966bd9 Kostas Papadimitriou
        data = {
398 e7cb4085 Kostas Papadimitriou
            'email': 'kPap@synnefo.org',
399 9d20fe23 Kostas Papadimitriou
            'password1': '1234',
400 9d20fe23 Kostas Papadimitriou
            'password2': '1234'
401 e5966bd9 Kostas Papadimitriou
        }
402 e5966bd9 Kostas Papadimitriou
403 e5966bd9 Kostas Papadimitriou
        form = forms.LocalUserCreationForm(data)
404 e5966bd9 Kostas Papadimitriou
        self.assertTrue(form.is_valid())
405 e5966bd9 Kostas Papadimitriou
        user = form.save()
406 e5966bd9 Kostas Papadimitriou
        form.store_user(user, {})
407 e5966bd9 Kostas Papadimitriou
408 9d20fe23 Kostas Papadimitriou
        u = AstakosUser.objects.get()
409 e7cb4085 Kostas Papadimitriou
        self.assertEqual(u.email, 'kPap@synnefo.org')
410 e7cb4085 Kostas Papadimitriou
        self.assertEqual(u.username, 'kpap@synnefo.org')
411 e5966bd9 Kostas Papadimitriou
        u.is_active = True
412 e5966bd9 Kostas Papadimitriou
        u.email_verified = True
413 e5966bd9 Kostas Papadimitriou
        u.save()
414 e5966bd9 Kostas Papadimitriou
415 e7cb4085 Kostas Papadimitriou
        data = {'username': 'kpap@synnefo.org', 'password': '1234'}
416 e5966bd9 Kostas Papadimitriou
        login = forms.LoginForm(data=data)
417 e5966bd9 Kostas Papadimitriou
        self.assertTrue(login.is_valid())
418 e5966bd9 Kostas Papadimitriou
419 e7cb4085 Kostas Papadimitriou
        data = {'username': 'KpaP@synnefo.org', 'password': '1234'}
420 e5966bd9 Kostas Papadimitriou
        login = forms.LoginForm(data=data)
421 e5966bd9 Kostas Papadimitriou
        self.assertTrue(login.is_valid())
422 e5966bd9 Kostas Papadimitriou
423 e5966bd9 Kostas Papadimitriou
        data = {
424 e7cb4085 Kostas Papadimitriou
            'email': 'kpap@synnefo.org',
425 9d20fe23 Kostas Papadimitriou
            'password1': '1234',
426 9d20fe23 Kostas Papadimitriou
            'password2': '1234'
427 e5966bd9 Kostas Papadimitriou
        }
428 e5966bd9 Kostas Papadimitriou
        form = forms.LocalUserCreationForm(data)
429 e5966bd9 Kostas Papadimitriou
        self.assertFalse(form.is_valid())
430 e5966bd9 Kostas Papadimitriou
431 ba27316a Kostas Papadimitriou
    @im_settings(HELPDESK=(('support', 'support@synnefo.org'),),
432 e7cb4085 Kostas Papadimitriou
                 FORCE_PROFILE_UPDATE=False, MODERATION_ENABLED=True)
433 d2633501 Kostas Papadimitriou
    def test_local_provider(self):
434 19a992e3 Kostas Papadimitriou
        self.helpdesk_email = astakos_settings.HELPDESK[0][1]
435 ba50648c Kostas Papadimitriou
436 ba50648c Kostas Papadimitriou
        # create a user
437 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url("signup"))
438 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
439 e7cb4085 Kostas Papadimitriou
        data = {'email': 'kpap@synnefo.org', 'password1': 'password',
440 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
441 d2633501 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
442 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url("signup"), data)
443 ba50648c Kostas Papadimitriou
444 ba50648c Kostas Papadimitriou
        # user created
445 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
446 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@synnefo.org",
447 e7cb4085 Kostas Papadimitriou
                                       email="kpap@synnefo.org")
448 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.username, 'kpap@synnefo.org')
449 d2633501 Kostas Papadimitriou
        self.assertEqual(user.has_auth_provider('local'), True)
450 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user.is_active)  # not activated
451 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user.email_verified)  # not verified
452 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)  # activation automatically sent
453 e7cb4085 Kostas Papadimitriou
        self.assertFalse(user.moderated)
454 e7cb4085 Kostas Papadimitriou
        self.assertFalse(user.email_verified)
455 d2633501 Kostas Papadimitriou
456 ba50648c Kostas Papadimitriou
        # admin gets notified and activates the user from the command line
457 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
458 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
459 8fb8d0cf Giorgos Korfiatis
                                               'password': 'password'},
460 e7cb4085 Kostas Papadimitriou
                             follow=True)
461 e7cb4085 Kostas Papadimitriou
        self.assertContains(r, messages.VERIFICATION_SENT)
462 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
463 e7cb4085 Kostas Papadimitriou
464 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@synnefo.org")
465 e7cb4085 Kostas Papadimitriou
        backend.send_user_verification_email(user)
466 d2633501 Kostas Papadimitriou
467 ba50648c Kostas Papadimitriou
        # user activation fields updated and user gets notified via email
468 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
469 d2633501 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
470 d2633501 Kostas Papadimitriou
        self.assertFalse(user.email_verified)
471 f47ecf6b Kostas Papadimitriou
        self.assertFalse(user.is_active)
472 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 2)
473 d2633501 Kostas Papadimitriou
474 d2633501 Kostas Papadimitriou
        # user forgot she got registered and tries to submit registration
475 d2633501 Kostas Papadimitriou
        # form. Notice the upper case in email
476 e7cb4085 Kostas Papadimitriou
        data = {'email': 'KPAP@synnefo.org', 'password1': 'password',
477 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
478 d2633501 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
479 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url("signup"), data, follow=True)
480 1ecda536 Kostas Papadimitriou
        self.assertRedirects(r, reverse('login'))
481 e7cb4085 Kostas Papadimitriou
        self.assertContains(r, messages.VERIFICATION_SENT)
482 564a2292 Kostas Papadimitriou
483 9d20fe23 Kostas Papadimitriou
        user = AstakosUser.objects.get()
484 564a2292 Kostas Papadimitriou
        # previous user replaced
485 564a2292 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
486 564a2292 Kostas Papadimitriou
        self.assertFalse(user.email_verified)
487 564a2292 Kostas Papadimitriou
        self.assertFalse(user.is_active)
488 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 1)
489 d2633501 Kostas Papadimitriou
490 f47ecf6b Kostas Papadimitriou
        # hmmm, email exists; lets request a password change
491 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('local/password_reset'))
492 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
493 e7cb4085 Kostas Papadimitriou
        data = {'email': 'kpap@synnefo.org'}
494 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local/password_reset'), data, follow=True)
495 d2633501 Kostas Papadimitriou
        # she can't because account is not active yet
496 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'pending activation')
497 d2633501 Kostas Papadimitriou
498 9d20fe23 Kostas Papadimitriou
        # moderation is enabled and an activation email has already been sent
499 9d20fe23 Kostas Papadimitriou
        # so user can trigger resend of the activation email
500 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('send/activation/%d' % user.pk),
501 5f28aa14 Kostas Papadimitriou
                            follow=True)
502 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'has been sent to your email address.')
503 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 2)
504 ba50648c Kostas Papadimitriou
505 d2633501 Kostas Papadimitriou
        # also she cannot login
506 e7cb4085 Kostas Papadimitriou
        data = {'username': 'kpap@synnefo.org', 'password': 'password'}
507 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), data, follow=True)
508 d2633501 Kostas Papadimitriou
        self.assertContains(r, 'Resend activation')
509 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
510 d2633501 Kostas Papadimitriou
        self.assertFalse('_pithos2_a' in self.client.cookies)
511 ba50648c Kostas Papadimitriou
512 d2633501 Kostas Papadimitriou
        # user sees the message and resends activation
513 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('send/activation/%d' % user.pk),
514 5f28aa14 Kostas Papadimitriou
                            follow=True)
515 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 3)
516 d2633501 Kostas Papadimitriou
517 e7cb4085 Kostas Papadimitriou
        # logged in user cannot activate another account
518 e7cb4085 Kostas Papadimitriou
        tmp_user = get_local_user("test_existing_user@synnefo.org")
519 e7cb4085 Kostas Papadimitriou
        tmp_client = Client()
520 e7cb4085 Kostas Papadimitriou
        tmp_client.login(username="test_existing_user@synnefo.org",
521 e7cb4085 Kostas Papadimitriou
                         password="password")
522 e7cb4085 Kostas Papadimitriou
        r = tmp_client.get(user.get_activation_url(), follow=True)
523 e7cb4085 Kostas Papadimitriou
        self.assertContains(r, messages.LOGGED_IN_WARNING)
524 e7cb4085 Kostas Papadimitriou
525 e7cb4085 Kostas Papadimitriou
        r = self.client.get(user.get_activation_url(), follow=True)
526 e7cb4085 Kostas Papadimitriou
        # previous code got invalidated
527 e7cb4085 Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
528 e7cb4085 Kostas Papadimitriou
529 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
530 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 0)
531 d2633501 Kostas Papadimitriou
        r = self.client.get(user.get_activation_url(), follow=True)
532 1ecda536 Kostas Papadimitriou
        self.assertRedirects(r, reverse('login'))
533 e7cb4085 Kostas Papadimitriou
        # user sees that account is pending approval from admins
534 e7cb4085 Kostas Papadimitriou
        self.assertContains(r, messages.NOTIFICATION_SENT)
535 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 1)
536 e7cb4085 Kostas Papadimitriou
537 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(email="KPAP@synnefo.org")
538 e7cb4085 Kostas Papadimitriou
        result = backend.handle_moderation(user)
539 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
540 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 4)
541 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 2)
542 e7cb4085 Kostas Papadimitriou
543 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get(email="KPAP@synnefo.org")
544 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('profile'), follow=True)
545 e7cb4085 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
546 e7cb4085 Kostas Papadimitriou
        self.assertFalse('_pithos2_a' in self.client.cookies)
547 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 4)
548 d2633501 Kostas Papadimitriou
549 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
550 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
551 5f28aa14 Kostas Papadimitriou
                                               'password': 'password'},
552 e7cb4085 Kostas Papadimitriou
                             follow=True)
553 d2633501 Kostas Papadimitriou
        # user activated and logged in, token cookie set
554 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
555 d2633501 Kostas Papadimitriou
        self.assertTrue('_pithos2_a' in self.client.cookies)
556 d2633501 Kostas Papadimitriou
        cookies = self.client.cookies
557 9d20fe23 Kostas Papadimitriou
        self.assertTrue(quote(user.auth_token) in
558 9d20fe23 Kostas Papadimitriou
                        cookies.get('_pithos2_a').value)
559 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('logout'), follow=True)
560 1ecda536 Kostas Papadimitriou
        r = self.client.get(ui_url(''), follow=True)
561 1ecda536 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('login'))
562 d2633501 Kostas Papadimitriou
        # user logged out, token cookie removed
563 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
564 d2633501 Kostas Papadimitriou
        self.assertFalse(self.client.cookies.get('_pithos2_a').value)
565 9d20fe23 Kostas Papadimitriou
566 9d20fe23 Kostas Papadimitriou
        #https://docs.djangoproject.com/en/dev/topics/testing/#persistent-state
567 d2633501 Kostas Papadimitriou
        del self.client.cookies['_pithos2_a']
568 d2633501 Kostas Papadimitriou
569 d2633501 Kostas Papadimitriou
        # user can login
570 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
571 5f28aa14 Kostas Papadimitriou
                                               'password': 'password'},
572 9d20fe23 Kostas Papadimitriou
                             follow=True)
573 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
574 d2633501 Kostas Papadimitriou
        self.assertTrue('_pithos2_a' in self.client.cookies)
575 d2633501 Kostas Papadimitriou
        cookies = self.client.cookies
576 9d20fe23 Kostas Papadimitriou
        self.assertTrue(quote(user.auth_token) in
577 9d20fe23 Kostas Papadimitriou
                        cookies.get('_pithos2_a').value)
578 5f28aa14 Kostas Papadimitriou
        self.client.get(ui_url('logout'), follow=True)
579 d2633501 Kostas Papadimitriou
580 d2633501 Kostas Papadimitriou
        # user forgot password
581 d2633501 Kostas Papadimitriou
        old_pass = user.password
582 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('local/password_reset'))
583 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
584 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local/password_reset'),
585 5f28aa14 Kostas Papadimitriou
                             {'email': 'kpap@synnefo.org'})
586 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 302)
587 d2633501 Kostas Papadimitriou
        # email sent
588 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@synnefo.org')), 5)
589 d2633501 Kostas Papadimitriou
590 d2633501 Kostas Papadimitriou
        # user visits change password link
591 126f6a55 Christos Stavrakakis
        user = AstakosUser.objects.get(pk=user.pk)
592 d2633501 Kostas Papadimitriou
        r = self.client.get(user.get_password_reset_url())
593 d2633501 Kostas Papadimitriou
        r = self.client.post(user.get_password_reset_url(),
594 9d20fe23 Kostas Papadimitriou
                             {'new_password1': 'newpass',
595 9d20fe23 Kostas Papadimitriou
                              'new_password2': 'newpass'})
596 d2633501 Kostas Papadimitriou
597 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
598 d2633501 Kostas Papadimitriou
        self.assertNotEqual(old_pass, user.password)
599 d2633501 Kostas Papadimitriou
600 d2633501 Kostas Papadimitriou
        # old pass is not usable
601 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
602 5f28aa14 Kostas Papadimitriou
                                               'password': 'password'})
603 31fdafa8 Kostas Papadimitriou
        self.assertContains(r, 'Please enter a correct username and password')
604 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local'), {'username': 'kpap@synnefo.org',
605 5f28aa14 Kostas Papadimitriou
                                               'password': 'newpass'},
606 478ece6c Kostas Papadimitriou
                             follow=True)
607 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
608 d2633501 Kostas Papadimitriou
        self.client.logout()
609 d2633501 Kostas Papadimitriou
610 d2633501 Kostas Papadimitriou
        # tests of special local backends
611 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
612 d2633501 Kostas Papadimitriou
        user.auth_providers.filter(module='local').update(auth_backend='ldap')
613 d2633501 Kostas Papadimitriou
        user.save()
614 d2633501 Kostas Papadimitriou
615 d2633501 Kostas Papadimitriou
        # non astakos local backends do not support password reset
616 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('local/password_reset'))
617 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
618 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local/password_reset'),
619 5f28aa14 Kostas Papadimitriou
                             {'email': 'kpap@synnefo.org'})
620 d2633501 Kostas Papadimitriou
        # she can't because account is not active yet
621 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "Changing password is not")
622 9d20fe23 Kostas Papadimitriou
623 9d20fe23 Kostas Papadimitriou
624 34a76cdb Kostas Papadimitriou
class UserActionsTests(TestCase):
625 34a76cdb Kostas Papadimitriou
626 34a76cdb Kostas Papadimitriou
    def test_email_change(self):
627 34a76cdb Kostas Papadimitriou
        # to test existing email validation
628 e7cb4085 Kostas Papadimitriou
        get_local_user('existing@synnefo.org')
629 34a76cdb Kostas Papadimitriou
630 34a76cdb Kostas Papadimitriou
        # local user
631 e7cb4085 Kostas Papadimitriou
        user = get_local_user('kpap@synnefo.org')
632 34a76cdb Kostas Papadimitriou
633 34a76cdb Kostas Papadimitriou
        # login as kpap
634 e7cb4085 Kostas Papadimitriou
        self.client.login(username='kpap@synnefo.org', password='password')
635 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('profile'), follow=True)
636 34a76cdb Kostas Papadimitriou
        user = r.context['request'].user
637 34a76cdb Kostas Papadimitriou
        self.assertTrue(user.is_authenticated())
638 34a76cdb Kostas Papadimitriou
639 34a76cdb Kostas Papadimitriou
        # change email is enabled
640 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('email_change'))
641 34a76cdb Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
642 34a76cdb Kostas Papadimitriou
        self.assertFalse(user.email_change_is_pending())
643 34a76cdb Kostas Papadimitriou
644 34a76cdb Kostas Papadimitriou
        # request email change to an existing email fails
645 e7cb4085 Kostas Papadimitriou
        data = {'new_email_address': 'existing@synnefo.org'}
646 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('email_change'), data)
647 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_USED)
648 34a76cdb Kostas Papadimitriou
649 34a76cdb Kostas Papadimitriou
        # proper email change
650 34a76cdb Kostas Papadimitriou
        data = {'new_email_address': 'kpap@gmail.com'}
651 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('email_change'), data, follow=True)
652 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('profile'))
653 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
654 34a76cdb Kostas Papadimitriou
        change1 = EmailChange.objects.get()
655 34a76cdb Kostas Papadimitriou
656 34a76cdb Kostas Papadimitriou
        # user sees a warning
657 5f28aa14 Kostas Papadimitriou
        r = self.client.get(ui_url('email_change'))
658 34a76cdb Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
659 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.PENDING_EMAIL_CHANGE_REQUEST)
660 34a76cdb Kostas Papadimitriou
        self.assertTrue(user.email_change_is_pending())
661 34a76cdb Kostas Papadimitriou
662 34a76cdb Kostas Papadimitriou
        # link was sent
663 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 0)
664 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@gmail.com')), 1)
665 34a76cdb Kostas Papadimitriou
666 34a76cdb Kostas Papadimitriou
        # proper email change
667 34a76cdb Kostas Papadimitriou
        data = {'new_email_address': 'kpap@yahoo.com'}
668 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('email_change'), data, follow=True)
669 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('profile'))
670 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
671 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 0)
672 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@yahoo.com')), 1)
673 34a76cdb Kostas Papadimitriou
        change2 = EmailChange.objects.get()
674 34a76cdb Kostas Papadimitriou
675 34a76cdb Kostas Papadimitriou
        r = self.client.get(change1.get_url())
676 0b817216 Kostas Papadimitriou
        self.assertEquals(r.status_code, 404)
677 34a76cdb Kostas Papadimitriou
        self.client.logout()
678 34a76cdb Kostas Papadimitriou
679 0b817216 Kostas Papadimitriou
        invalid_client = Client()
680 5f28aa14 Kostas Papadimitriou
        r = invalid_client.post(ui_url('local?'),
681 0b817216 Kostas Papadimitriou
                                {'username': 'existing@synnefo.org',
682 0b817216 Kostas Papadimitriou
                                 'password': 'password'})
683 0b817216 Kostas Papadimitriou
        r = invalid_client.get(change2.get_url(), follow=True)
684 0b817216 Kostas Papadimitriou
        self.assertEquals(r.status_code, 403)
685 0b817216 Kostas Papadimitriou
686 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local?next=' + change2.get_url()),
687 e7cb4085 Kostas Papadimitriou
                             {'username': 'kpap@synnefo.org',
688 34a76cdb Kostas Papadimitriou
                              'password': 'password',
689 34a76cdb Kostas Papadimitriou
                              'next': change2.get_url()},
690 34a76cdb Kostas Papadimitriou
                             follow=True)
691 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('profile'))
692 34a76cdb Kostas Papadimitriou
        user = r.context['request'].user
693 34a76cdb Kostas Papadimitriou
        self.assertEquals(user.email, 'kpap@yahoo.com')
694 34a76cdb Kostas Papadimitriou
        self.assertEquals(user.username, 'kpap@yahoo.com')
695 34a76cdb Kostas Papadimitriou
696 34a76cdb Kostas Papadimitriou
        self.client.logout()
697 5f28aa14 Kostas Papadimitriou
        r = self.client.post(ui_url('local?next=' + change2.get_url()),
698 e7cb4085 Kostas Papadimitriou
                             {'username': 'kpap@synnefo.org',
699 34a76cdb Kostas Papadimitriou
                              'password': 'password',
700 34a76cdb Kostas Papadimitriou
                              'next': change2.get_url()},
701 34a76cdb Kostas Papadimitriou
                             follow=True)
702 34a76cdb Kostas Papadimitriou
        self.assertContains(r, "Please enter a correct username and password")
703 34a76cdb Kostas Papadimitriou
        self.assertEqual(user.emailchanges.count(), 0)
704 34a76cdb Kostas Papadimitriou
705 5f28aa14 Kostas Papadimitriou
        AstakosUser.objects.all().delete()
706 5f28aa14 Kostas Papadimitriou
        Group.objects.all().delete()
707 5f28aa14 Kostas Papadimitriou
708 9d20fe23 Kostas Papadimitriou
709 478ece6c Kostas Papadimitriou
class TestAuthProviderViews(TestCase):
710 478ece6c Kostas Papadimitriou
711 baa9073a Kostas Papadimitriou
    def tearDown(self):
712 baa9073a Kostas Papadimitriou
        AstakosUser.objects.all().delete()
713 baa9073a Kostas Papadimitriou
714 ba27316a Kostas Papadimitriou
    @shibboleth_settings(CREATION_GROUPS_POLICY=['academic-login'],
715 ba27316a Kostas Papadimitriou
                         AUTOMODERATE_POLICY=True)
716 ba27316a Kostas Papadimitriou
    @im_settings(IM_MODULES=['shibboleth', 'local'], MODERATION_ENABLED=True,
717 ba27316a Kostas Papadimitriou
                 FORCE_PROFILE_UPDATE=False)
718 478ece6c Kostas Papadimitriou
    def test_user(self):
719 478ece6c Kostas Papadimitriou
        Profile = AuthProviderPolicyProfile
720 478ece6c Kostas Papadimitriou
        Pending = PendingThirdPartyUser
721 478ece6c Kostas Papadimitriou
        User = AstakosUser
722 478ece6c Kostas Papadimitriou
723 e7cb4085 Kostas Papadimitriou
        User.objects.create(email="newuser@synnefo.org")
724 e7cb4085 Kostas Papadimitriou
        get_local_user("olduser@synnefo.org")
725 478ece6c Kostas Papadimitriou
        cl_olduser = ShibbolethClient()
726 e7cb4085 Kostas Papadimitriou
        get_local_user("olduser2@synnefo.org")
727 0a7a4104 Kostas Papadimitriou
        ShibbolethClient()
728 478ece6c Kostas Papadimitriou
        cl_newuser = ShibbolethClient()
729 478ece6c Kostas Papadimitriou
        cl_newuser2 = Client()
730 478ece6c Kostas Papadimitriou
731 478ece6c Kostas Papadimitriou
        academic_group, created = Group.objects.get_or_create(
732 478ece6c Kostas Papadimitriou
            name='academic-login')
733 478ece6c Kostas Papadimitriou
        academic_users = academic_group.user_set
734 478ece6c Kostas Papadimitriou
        assert created
735 478ece6c Kostas Papadimitriou
        policy_only_academic = Profile.objects.add_policy('academic_strict',
736 478ece6c Kostas Papadimitriou
                                                          'shibboleth',
737 478ece6c Kostas Papadimitriou
                                                          academic_group,
738 478ece6c Kostas Papadimitriou
                                                          exclusive=True,
739 478ece6c Kostas Papadimitriou
                                                          login=False,
740 478ece6c Kostas Papadimitriou
                                                          add=False)
741 478ece6c Kostas Papadimitriou
742 478ece6c Kostas Papadimitriou
        # new academic user
743 e7cb4085 Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
744 478ece6c Kostas Papadimitriou
        cl_newuser.set_tokens(eppn="newusereppn")
745 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
746 478ece6c Kostas Papadimitriou
        pending = Pending.objects.get()
747 478ece6c Kostas Papadimitriou
        identifier = pending.third_party_identifier
748 478ece6c Kostas Papadimitriou
        signup_data = {'third_party_identifier': identifier,
749 478ece6c Kostas Papadimitriou
                       'first_name': 'Academic',
750 478ece6c Kostas Papadimitriou
                       'third_party_token': pending.token,
751 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
752 478ece6c Kostas Papadimitriou
                       'provider': 'shibboleth'}
753 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.post(ui_url('signup'), signup_data)
754 478ece6c Kostas Papadimitriou
        self.assertContains(r, "This field is required", )
755 e7cb4085 Kostas Papadimitriou
        signup_data['email'] = 'olduser@synnefo.org'
756 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.post(ui_url('signup'), signup_data)
757 478ece6c Kostas Papadimitriou
        self.assertContains(r, "already an account with this email", )
758 e7cb4085 Kostas Papadimitriou
        signup_data['email'] = 'newuser@synnefo.org'
759 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.post(ui_url('signup'), signup_data, follow=True)
760 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.post(ui_url('signup'), signup_data, follow=True)
761 478ece6c Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
762 e7cb4085 Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@synnefo.org")
763 478ece6c Kostas Papadimitriou
        activation_link = newuser.get_activation_url()
764 e7cb4085 Kostas Papadimitriou
        self.assertTrue(academic_users.get(email='newuser@synnefo.org'))
765 478ece6c Kostas Papadimitriou
766 478ece6c Kostas Papadimitriou
        # new non-academic user
767 478ece6c Kostas Papadimitriou
        signup_data = {'first_name': 'Non Academic',
768 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
769 478ece6c Kostas Papadimitriou
                       'provider': 'local',
770 478ece6c Kostas Papadimitriou
                       'password1': 'password',
771 478ece6c Kostas Papadimitriou
                       'password2': 'password'}
772 e7cb4085 Kostas Papadimitriou
        signup_data['email'] = 'olduser@synnefo.org'
773 5f28aa14 Kostas Papadimitriou
        r = cl_newuser2.post(ui_url('signup'), signup_data)
774 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'There is already an account with this '
775 478ece6c Kostas Papadimitriou
                               'email address')
776 e7cb4085 Kostas Papadimitriou
        signup_data['email'] = 'newuser@synnefo.org'
777 5f28aa14 Kostas Papadimitriou
        r = cl_newuser2.post(ui_url('signup/'), signup_data)
778 e7cb4085 Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
779 478ece6c Kostas Papadimitriou
        r = self.client.get(activation_link, follow=True)
780 e7cb4085 Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
781 e7cb4085 Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@synnefo.org")
782 e7cb4085 Kostas Papadimitriou
        self.assertTrue(newuser.activation_sent)
783 478ece6c Kostas Papadimitriou
784 e7cb4085 Kostas Papadimitriou
        # activation sent, user didn't open verification url so additional
785 e7cb4085 Kostas Papadimitriou
        # registrations invalidate the previous signups.
786 e7cb4085 Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@synnefo.org'))
787 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
788 478ece6c Kostas Papadimitriou
        pending = Pending.objects.get()
789 478ece6c Kostas Papadimitriou
        identifier = pending.third_party_identifier
790 478ece6c Kostas Papadimitriou
        signup_data = {'third_party_identifier': identifier,
791 478ece6c Kostas Papadimitriou
                       'first_name': 'Academic',
792 478ece6c Kostas Papadimitriou
                       'third_party_token': pending.token,
793 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
794 478ece6c Kostas Papadimitriou
                       'provider': 'shibboleth'}
795 e7cb4085 Kostas Papadimitriou
        signup_data['email'] = 'newuser@synnefo.org'
796 5f28aa14 Kostas Papadimitriou
        r = cl_newuser.post(ui_url('signup'), signup_data)
797 e7cb4085 Kostas Papadimitriou
        self.assertEqual(r.status_code, 302)
798 e7cb4085 Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@synnefo.org")
799 478ece6c Kostas Papadimitriou
        self.assertTrue(newuser.activation_sent)
800 478ece6c Kostas Papadimitriou
        activation_link = newuser.get_activation_url()
801 e7cb4085 Kostas Papadimitriou
        self.assertTrue(academic_users.get(email='newuser@synnefo.org'))
802 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(newuser.get_activation_url(), follow=True)
803 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('landing'))
804 e7cb4085 Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@synnefo.org")
805 478ece6c Kostas Papadimitriou
        self.assertEqual(newuser.is_active, True)
806 478ece6c Kostas Papadimitriou
        self.assertEqual(newuser.email_verified, True)
807 478ece6c Kostas Papadimitriou
        cl_newuser.logout()
808 478ece6c Kostas Papadimitriou
809 478ece6c Kostas Papadimitriou
        # cannot reactivate if suspended
810 478ece6c Kostas Papadimitriou
        newuser.is_active = False
811 478ece6c Kostas Papadimitriou
        newuser.save()
812 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(newuser.get_activation_url())
813 e7cb4085 Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@synnefo.org")
814 478ece6c Kostas Papadimitriou
        self.assertFalse(newuser.is_active)
815 478ece6c Kostas Papadimitriou
816 478ece6c Kostas Papadimitriou
        # release suspension
817 478ece6c Kostas Papadimitriou
        newuser.is_active = True
818 478ece6c Kostas Papadimitriou
        newuser.save()
819 478ece6c Kostas Papadimitriou
820 5f28aa14 Kostas Papadimitriou
        cl_newuser.get(ui_url('login/shibboleth?'), follow=True)
821 478ece6c Kostas Papadimitriou
        local = auth.get_provider('local', newuser)
822 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_add_policy, False)
823 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_login_policy, False)
824 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(local.get_add_url, follow=True)
825 5f28aa14 Kostas Papadimitriou
        self.assertRedirects(r, ui_url('profile'))
826 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'disabled for your')
827 478ece6c Kostas Papadimitriou
828 e7cb4085 Kostas Papadimitriou
        cl_olduser.login(username='olduser@synnefo.org', password="password")
829 5f28aa14 Kostas Papadimitriou
        r = cl_olduser.get(ui_url('profile'), follow=True)
830 478ece6c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
831 5f28aa14 Kostas Papadimitriou
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
832 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'Your request is missing a unique token')
833 478ece6c Kostas Papadimitriou
        cl_olduser.set_tokens(eppn="newusereppn")
834 5f28aa14 Kostas Papadimitriou
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
835 c34abd9c Kostas Papadimitriou
        self.assertContains(r, 'already in use')
836 478ece6c Kostas Papadimitriou
        cl_olduser.set_tokens(eppn="oldusereppn")
837 5f28aa14 Kostas Papadimitriou
        r = cl_olduser.get(ui_url('login/shibboleth?'), follow=True)
838 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'Academic login enabled for this account')
839 478ece6c Kostas Papadimitriou
840 e7cb4085 Kostas Papadimitriou
        user = User.objects.get(email="olduser@synnefo.org")
841 478ece6c Kostas Papadimitriou
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
842 478ece6c Kostas Papadimitriou
        local_provider = user.get_auth_provider('local')
843 478ece6c Kostas Papadimitriou
        self.assertEqual(shib_provider.get_remove_policy, True)
844 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_remove_policy, True)
845 478ece6c Kostas Papadimitriou
846 478ece6c Kostas Papadimitriou
        policy_only_academic = Profile.objects.add_policy('academic_strict2',
847 478ece6c Kostas Papadimitriou
                                                          'shibboleth',
848 478ece6c Kostas Papadimitriou
                                                          academic_group,
849 478ece6c Kostas Papadimitriou
                                                          remove=False)
850 478ece6c Kostas Papadimitriou
        user.groups.add(academic_group)
851 478ece6c Kostas Papadimitriou
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
852 478ece6c Kostas Papadimitriou
        local_provider = user.get_auth_provider('local')
853 478ece6c Kostas Papadimitriou
        self.assertEqual(shib_provider.get_remove_policy, False)
854 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_remove_policy, True)
855 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_login_policy, False)
856 478ece6c Kostas Papadimitriou
857 478ece6c Kostas Papadimitriou
        cl_olduser.logout()
858 0b817216 Kostas Papadimitriou
        login_data = {'username': 'olduser@synnefo.org',
859 0b817216 Kostas Papadimitriou
                      'password': 'password'}
860 5f28aa14 Kostas Papadimitriou
        r = cl_olduser.post(ui_url('local'), login_data, follow=True)
861 5f28aa14 Kostas Papadimitriou
        self.assertContains(r, "login/shibboleth'>Academic login")
862 39e16ecc Kostas Papadimitriou
        Group.objects.all().delete()
863 9d20fe23 Kostas Papadimitriou
864 9d20fe23 Kostas Papadimitriou
865 478ece6c Kostas Papadimitriou
class TestAuthProvidersAPI(TestCase):
866 478ece6c Kostas Papadimitriou
    """
867 478ece6c Kostas Papadimitriou
    Test auth_providers module API
868 478ece6c Kostas Papadimitriou
    """
869 478ece6c Kostas Papadimitriou
870 c34abd9c Kostas Papadimitriou
    def tearDown(self):
871 c34abd9c Kostas Papadimitriou
        Group.objects.all().delete()
872 c34abd9c Kostas Papadimitriou
873 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
874 9d20fe23 Kostas Papadimitriou
    def test_create(self):
875 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@synnefo.org")
876 e7cb4085 Kostas Papadimitriou
        user2 = AstakosUser.objects.create(email="kpap2@synnefo.org")
877 9d20fe23 Kostas Papadimitriou
878 9d20fe23 Kostas Papadimitriou
        module = 'shibboleth'
879 9d20fe23 Kostas Papadimitriou
        identifier = 'SHIB_UUID'
880 9d20fe23 Kostas Papadimitriou
        provider_params = {
881 9d20fe23 Kostas Papadimitriou
            'affiliation': 'UNIVERSITY',
882 9d20fe23 Kostas Papadimitriou
            'info': {'age': 27}
883 9d20fe23 Kostas Papadimitriou
        }
884 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user2, identifier,
885 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
886 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
887 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user, identifier,
888 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
889 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
890 9d20fe23 Kostas Papadimitriou
        user.email_verified = True
891 9d20fe23 Kostas Papadimitriou
        user.save()
892 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
893 9d20fe23 Kostas Papadimitriou
        provider = user.get_auth_provider(module, identifier)
894 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user.get_auth_provider(
895 9d20fe23 Kostas Papadimitriou
            module, identifier)._instance.info.get('age'), 27)
896 9d20fe23 Kostas Papadimitriou
897 9d20fe23 Kostas Papadimitriou
        module = 'local'
898 9d20fe23 Kostas Papadimitriou
        identifier = None
899 9d20fe23 Kostas Papadimitriou
        provider_params = {'auth_backend': 'ldap', 'info':
900 9d20fe23 Kostas Papadimitriou
                          {'office': 'A1'}}
901 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user, identifier,
902 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
903 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
904 9d20fe23 Kostas Papadimitriou
        self.assertFalse(provider.get_add_policy)
905 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
906 9d20fe23 Kostas Papadimitriou
907 9d20fe23 Kostas Papadimitriou
        shib = user.get_auth_provider('shibboleth',
908 9d20fe23 Kostas Papadimitriou
                                      'SHIB_UUID')
909 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shib.get_remove_policy)
910 9d20fe23 Kostas Papadimitriou
911 9d20fe23 Kostas Papadimitriou
        local = user.get_auth_provider('local')
912 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_remove_policy)
913 9d20fe23 Kostas Papadimitriou
914 9d20fe23 Kostas Papadimitriou
        local.remove_from_user()
915 9d20fe23 Kostas Papadimitriou
        self.assertFalse(shib.get_remove_policy)
916 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, shib.remove_from_user)
917 9d20fe23 Kostas Papadimitriou
918 478ece6c Kostas Papadimitriou
        provider = user.get_auth_providers()[0]
919 478ece6c Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
920 478ece6c Kostas Papadimitriou
921 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
922 ba27316a Kostas Papadimitriou
    @shibboleth_settings(ADD_GROUPS_POLICY=['group1', 'group2'],
923 ba27316a Kostas Papadimitriou
                         CREATION_GROUPS_POLICY=['group-create', 'group1',
924 478ece6c Kostas Papadimitriou
                                                 'group2'])
925 ba27316a Kostas Papadimitriou
    @localauth_settings(ADD_GROUPS_POLICY=['localgroup'],
926 ba27316a Kostas Papadimitriou
                        CREATION_GROUPS_POLICY=['localgroup-create',
927 478ece6c Kostas Papadimitriou
                                                'group-create'])
928 478ece6c Kostas Papadimitriou
    def test_add_groups(self):
929 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@synnefo.org")
930 478ece6c Kostas Papadimitriou
        provider = auth.get_provider('shibboleth', user, 'test123')
931 478ece6c Kostas Papadimitriou
        provider.add_to_user()
932 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
933 2a88057d Christos Stavrakakis
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
934 8fb8d0cf Giorgos Korfiatis
                         sorted([u'group1', u'group2', u'group-create']))
935 478ece6c Kostas Papadimitriou
936 478ece6c Kostas Papadimitriou
        local = auth.get_provider('local', user)
937 478ece6c Kostas Papadimitriou
        local.add_to_user()
938 478ece6c Kostas Papadimitriou
        provider = user.get_auth_provider('shibboleth')
939 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_add_groups_policy, ['group1', 'group2'])
940 478ece6c Kostas Papadimitriou
        provider.remove_from_user()
941 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
942 478ece6c Kostas Papadimitriou
        self.assertEqual(len(user.get_auth_providers()), 1)
943 2a88057d Christos Stavrakakis
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
944 8fb8d0cf Giorgos Korfiatis
                         sorted([u'group-create', u'localgroup']))
945 478ece6c Kostas Papadimitriou
946 478ece6c Kostas Papadimitriou
        local = user.get_auth_provider('local')
947 478ece6c Kostas Papadimitriou
        self.assertRaises(Exception, local.remove_from_user)
948 478ece6c Kostas Papadimitriou
        provider = auth.get_provider('shibboleth', user, 'test123')
949 478ece6c Kostas Papadimitriou
        provider.add_to_user()
950 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
951 2a88057d Christos Stavrakakis
        self.assertEqual(sorted(user.groups.values_list('name', flat=True)),
952 8fb8d0cf Giorgos Korfiatis
                         sorted([u'group-create', u'group1', u'group2',
953 8fb8d0cf Giorgos Korfiatis
                                 u'localgroup']))
954 39e16ecc Kostas Papadimitriou
        Group.objects.all().delete()
955 e7cb4085 Kostas Papadimitriou
956 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
957 9d20fe23 Kostas Papadimitriou
    def test_policies(self):
958 9d20fe23 Kostas Papadimitriou
        group_old, created = Group.objects.get_or_create(name='olduser')
959 9d20fe23 Kostas Papadimitriou
960 9d20fe23 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
961 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATION_GROUPS_POLICY = \
962 9d20fe23 Kostas Papadimitriou
            ['academic-user']
963 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_GOOGLE_ADD_GROUPS_POLICY = \
964 9d20fe23 Kostas Papadimitriou
            ['google-user']
965 9d20fe23 Kostas Papadimitriou
966 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@synnefo.org")
967 9d20fe23 Kostas Papadimitriou
        user.groups.add(group_old)
968 9d20fe23 Kostas Papadimitriou
        user.add_auth_provider('local')
969 9d20fe23 Kostas Papadimitriou
970 e7cb4085 Kostas Papadimitriou
        user2 = AstakosUser.objects.create(email="kpap2@synnefo.org")
971 9d20fe23 Kostas Papadimitriou
        user2.add_auth_provider('shibboleth', identifier='shibid')
972 9d20fe23 Kostas Papadimitriou
973 e7cb4085 Kostas Papadimitriou
        user3 = AstakosUser.objects.create(email="kpap3@synnefo.org")
974 9d20fe23 Kostas Papadimitriou
        user3.groups.add(group_old)
975 9d20fe23 Kostas Papadimitriou
        user3.add_auth_provider('local')
976 9d20fe23 Kostas Papadimitriou
        user3.add_auth_provider('shibboleth', identifier='1234')
977 9d20fe23 Kostas Papadimitriou
978 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user2.groups.get(name='academic-user'))
979 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user2.groups.filter(name='olduser').count())
980 9d20fe23 Kostas Papadimitriou
981 9d20fe23 Kostas Papadimitriou
        local = auth_providers.get_provider('local')
982 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
983 9d20fe23 Kostas Papadimitriou
984 9d20fe23 Kostas Papadimitriou
        academic_group = Group.objects.get(name='academic-user')
985 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
986 9d20fe23 Kostas Papadimitriou
                                                     academic_group,
987 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
988 9d20fe23 Kostas Papadimitriou
                                                     add=False,
989 9d20fe23 Kostas Papadimitriou
                                                     login=False)
990 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
991 9d20fe23 Kostas Papadimitriou
                                                     academic_group,
992 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
993 9d20fe23 Kostas Papadimitriou
                                                     login=False,
994 9d20fe23 Kostas Papadimitriou
                                                     add=False)
995 9d20fe23 Kostas Papadimitriou
        # no duplicate entry gets created
996 9d20fe23 Kostas Papadimitriou
        self.assertEqual(academic_group.authpolicy_profiles.count(), 1)
997 9d20fe23 Kostas Papadimitriou
998 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user2.authpolicy_profiles.count(), 0)
999 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1000 9d20fe23 Kostas Papadimitriou
                                                     user2,
1001 9d20fe23 Kostas Papadimitriou
                                                     remove=False)
1002 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user2.authpolicy_profiles.count(), 1)
1003 9d20fe23 Kostas Papadimitriou
1004 9d20fe23 Kostas Papadimitriou
        local = auth_providers.get_provider('local', user2)
1005 9d20fe23 Kostas Papadimitriou
        google = auth_providers.get_provider('google', user2)
1006 9d20fe23 Kostas Papadimitriou
        shibboleth = auth_providers.get_provider('shibboleth', user2)
1007 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shibboleth.get_login_policy)
1008 9d20fe23 Kostas Papadimitriou
        self.assertFalse(shibboleth.get_remove_policy)
1009 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_add_policy)
1010 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_add_policy)
1011 9d20fe23 Kostas Papadimitriou
        self.assertFalse(google.get_add_policy)
1012 9d20fe23 Kostas Papadimitriou
1013 9d20fe23 Kostas Papadimitriou
        user2.groups.remove(Group.objects.get(name='academic-user'))
1014 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
1015 9d20fe23 Kostas Papadimitriou
        self.assertTrue(google.get_add_policy)
1016 9d20fe23 Kostas Papadimitriou
        user2.groups.add(Group.objects.get(name='academic-user'))
1017 9d20fe23 Kostas Papadimitriou
1018 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1019 9d20fe23 Kostas Papadimitriou
                                                     user2,
1020 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
1021 9d20fe23 Kostas Papadimitriou
                                                     add=True)
1022 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
1023 9d20fe23 Kostas Papadimitriou
        self.assertTrue(google.get_add_policy)
1024 9d20fe23 Kostas Papadimitriou
1025 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_AUTOMODERATE_POLICY = True
1026 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_automoderate_policy)
1027 9d20fe23 Kostas Papadimitriou
        self.assertFalse(google.get_automoderate_policy)
1028 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shibboleth.get_automoderate_policy)
1029 9d20fe23 Kostas Papadimitriou
1030 9d20fe23 Kostas Papadimitriou
        for s in ['SHIBBOLETH_CREATION_GROUPS_POLICY',
1031 9d20fe23 Kostas Papadimitriou
                  'GOOGLE_ADD_GROUPS_POLICY']:
1032 9d20fe23 Kostas Papadimitriou
            delattr(settings, 'ASTAKOS_AUTH_PROVIDER_%s' % s)
1033 478ece6c Kostas Papadimitriou
1034 478ece6c Kostas Papadimitriou
    @shibboleth_settings(CREATE_POLICY=True)
1035 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1036 478ece6c Kostas Papadimitriou
    def test_create_http(self):
1037 478ece6c Kostas Papadimitriou
        # this should be wrapped inside a transaction
1038 478ece6c Kostas Papadimitriou
        user = AstakosUser(email="test@test.com")
1039 478ece6c Kostas Papadimitriou
        user.save()
1040 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user,
1041 478ece6c Kostas Papadimitriou
                                               'test@academia.test')
1042 478ece6c Kostas Papadimitriou
        provider.add_to_user()
1043 478ece6c Kostas Papadimitriou
        user.get_auth_provider('shibboleth', 'test@academia.test')
1044 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('local', user)
1045 478ece6c Kostas Papadimitriou
        provider.add_to_user()
1046 478ece6c Kostas Papadimitriou
        user.get_auth_provider('local')
1047 478ece6c Kostas Papadimitriou
1048 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = False
1049 478ece6c Kostas Papadimitriou
        user = AstakosUser(email="test2@test.com")
1050 478ece6c Kostas Papadimitriou
        user.save()
1051 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user,
1052 478ece6c Kostas Papadimitriou
                                               'test@shibboleth.com',
1053 478ece6c Kostas Papadimitriou
                                               **{'info': {'name':
1054 8fb8d0cf Giorgos Korfiatis
                                                           'User Test'}})
1055 478ece6c Kostas Papadimitriou
        self.assertFalse(provider.get_create_policy)
1056 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = True
1057 478ece6c Kostas Papadimitriou
        self.assertTrue(provider.get_create_policy)
1058 478ece6c Kostas Papadimitriou
        academic = provider.add_to_user()
1059 478ece6c Kostas Papadimitriou
1060 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1061 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1062 478ece6c Kostas Papadimitriou
    def test_policies(self):
1063 e7cb4085 Kostas Papadimitriou
        user = get_local_user('kpap@synnefo.org')
1064 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1065 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1066 478ece6c Kostas Papadimitriou
1067 478ece6c Kostas Papadimitriou
        # default limit is 1
1068 478ece6c Kostas Papadimitriou
        local = user.get_auth_provider('local')
1069 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_add_policy, False)
1070 478ece6c Kostas Papadimitriou
1071 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 3
1072 478ece6c Kostas Papadimitriou
        academic = user.get_auth_provider('shibboleth',
1073 478ece6c Kostas Papadimitriou
                                          identifier='1234')
1074 478ece6c Kostas Papadimitriou
        self.assertEqual(academic.get_add_policy, False)
1075 478ece6c Kostas Papadimitriou
        newacademic = auth_providers.get_provider('shibboleth', user,
1076 478ece6c Kostas Papadimitriou
                                                  identifier='123456')
1077 478ece6c Kostas Papadimitriou
        self.assertEqual(newacademic.get_add_policy, True)
1078 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='123456')
1079 478ece6c Kostas Papadimitriou
        self.assertEqual(academic.get_add_policy, False)
1080 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 1
1081 478ece6c Kostas Papadimitriou
1082 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1083 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1084 478ece6c Kostas Papadimitriou
    def test_messages(self):
1085 e7cb4085 Kostas Papadimitriou
        user = get_local_user('kpap@synnefo.org')
1086 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1087 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1088 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1089 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('title'), 'Academic')
1090 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = 'New title'
1091 478ece6c Kostas Papadimitriou
        # regenerate messages cache
1092 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1093 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('title'), 'New title')
1094 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('login_title'),
1095 478ece6c Kostas Papadimitriou
                         'New title LOGIN')
1096 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_login_title_msg, 'New title LOGIN')
1097 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_module_icon,
1098 478ece6c Kostas Papadimitriou
                         settings.MEDIA_URL + 'im/auth/icons/shibboleth.png')
1099 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_module_medium_icon,
1100 478ece6c Kostas Papadimitriou
                         settings.MEDIA_URL +
1101 478ece6c Kostas Papadimitriou
                         'im/auth/icons-medium/shibboleth.png')
1102 478ece6c Kostas Papadimitriou
1103 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = None
1104 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '12345')
1105 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_method_details_msg,
1106 478ece6c Kostas Papadimitriou
                         'Account: 12345')
1107 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1108 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_method_details_msg,
1109 478ece6c Kostas Papadimitriou
                         'Account: 1234')
1110 478ece6c Kostas Papadimitriou
1111 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1112 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_not_active_msg,
1113 478ece6c Kostas Papadimitriou
                         "'Academic login' is disabled.")
1114 478ece6c Kostas Papadimitriou
1115 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1116 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1117 478ece6c Kostas Papadimitriou
    def test_templates(self):
1118 e7cb4085 Kostas Papadimitriou
        user = get_local_user('kpap@synnefo.org')
1119 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1120 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1121 478ece6c Kostas Papadimitriou
1122 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1123 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_template('login'),
1124 478ece6c Kostas Papadimitriou
                         'im/auth/shibboleth_login.html')
1125 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('google')
1126 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_template('login'),
1127 478ece6c Kostas Papadimitriou
                         'im/auth/generic_login.html')
1128 478ece6c Kostas Papadimitriou
1129 478ece6c Kostas Papadimitriou
1130 e7cb4085 Kostas Papadimitriou
class TestActivationBackend(TestCase):
1131 e7cb4085 Kostas Papadimitriou
1132 e7cb4085 Kostas Papadimitriou
    def setUp(self):
1133 e7cb4085 Kostas Papadimitriou
        # dummy call to pass through logging middleware
1134 5f28aa14 Kostas Papadimitriou
        self.client.get(ui_url(''))
1135 e7cb4085 Kostas Papadimitriou
1136 e7cb4085 Kostas Papadimitriou
    @im_settings(RE_USER_EMAIL_PATTERNS=['.*@synnefo.org'])
1137 e7cb4085 Kostas Papadimitriou
    @shibboleth_settings(AUTOMODERATE_POLICY=True)
1138 e7cb4085 Kostas Papadimitriou
    def test_policies(self):
1139 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
1140 e7cb4085 Kostas Papadimitriou
1141 e7cb4085 Kostas Papadimitriou
        # email matches RE_USER_EMAIL_PATTERNS
1142 e7cb4085 Kostas Papadimitriou
        user1 = get_local_user('kpap@synnefo.org', moderated=False,
1143 e7cb4085 Kostas Papadimitriou
                               is_active=False, email_verified=False)
1144 e7cb4085 Kostas Papadimitriou
        backend.handle_verification(user1, user1.verification_code)
1145 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user1.accepted_policy, 'email')
1146 e7cb4085 Kostas Papadimitriou
1147 e7cb4085 Kostas Papadimitriou
        # manually moderated
1148 e7cb4085 Kostas Papadimitriou
        user2 = get_local_user('kpap@synnefo-bad.org', moderated=False,
1149 e7cb4085 Kostas Papadimitriou
                               is_active=False, email_verified=False)
1150 e7cb4085 Kostas Papadimitriou
1151 e7cb4085 Kostas Papadimitriou
        backend.handle_verification(user2, user2.verification_code)
1152 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user2.moderated, False)
1153 e7cb4085 Kostas Papadimitriou
        backend.handle_moderation(user2)
1154 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user2.moderated, True)
1155 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user2.accepted_policy, 'manual')
1156 e7cb4085 Kostas Papadimitriou
1157 e7cb4085 Kostas Papadimitriou
        # autoaccept due to provider automoderate policy
1158 e7cb4085 Kostas Papadimitriou
        user3 = get_local_user('kpap2@synnefo-bad.org', moderated=False,
1159 e7cb4085 Kostas Papadimitriou
                               is_active=False, email_verified=False)
1160 e7cb4085 Kostas Papadimitriou
        user3.auth_providers.all().delete()
1161 e7cb4085 Kostas Papadimitriou
        user3.add_auth_provider('shibboleth', identifier='shib123')
1162 e7cb4085 Kostas Papadimitriou
        backend.handle_verification(user3, user3.verification_code)
1163 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user3.moderated, True)
1164 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user3.accepted_policy, 'auth_provider_shibboleth')
1165 e7cb4085 Kostas Papadimitriou
1166 e7cb4085 Kostas Papadimitriou
    @im_settings(MODERATION_ENABLED=False,
1167 e7cb4085 Kostas Papadimitriou
                 MANAGERS=(('Manager',
1168 e7cb4085 Kostas Papadimitriou
                            'manager@synnefo.org'),),
1169 e7cb4085 Kostas Papadimitriou
                 HELPDESK=(('Helpdesk',
1170 e7cb4085 Kostas Papadimitriou
                            'helpdesk@synnefo.org'),),
1171 e7cb4085 Kostas Papadimitriou
                 ADMINS=(('Admin', 'admin@synnefo.org'), ))
1172 e7cb4085 Kostas Papadimitriou
    def test_without_moderation(self):
1173 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
1174 e7cb4085 Kostas Papadimitriou
        form = backend.get_signup_form('local')
1175 e7cb4085 Kostas Papadimitriou
        self.assertTrue(isinstance(form, forms.LocalUserCreationForm))
1176 e7cb4085 Kostas Papadimitriou
1177 e7cb4085 Kostas Papadimitriou
        user_data = {
1178 e7cb4085 Kostas Papadimitriou
            'email': 'kpap@synnefo.org',
1179 e7cb4085 Kostas Papadimitriou
            'first_name': 'Kostas Papas',
1180 e7cb4085 Kostas Papadimitriou
            'password1': '123',
1181 e7cb4085 Kostas Papadimitriou
            'password2': '123'
1182 e7cb4085 Kostas Papadimitriou
        }
1183 e7cb4085 Kostas Papadimitriou
        form = backend.get_signup_form('local', user_data)
1184 e7cb4085 Kostas Papadimitriou
        user = form.save(commit=False)
1185 e7cb4085 Kostas Papadimitriou
        form.store_user(user)
1186 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1187 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, False)
1188 e7cb4085 Kostas Papadimitriou
1189 e7cb4085 Kostas Papadimitriou
        # step one, registration
1190 e7cb4085 Kostas Papadimitriou
        result = backend.handle_registration(user)
1191 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1192 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1193 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, False)
1194 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.verification_code)
1195 e7cb4085 Kostas Papadimitriou
        self.assertEqual(result.status, backend.Result.PENDING_VERIFICATION)
1196 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1197 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
1198 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(mail.outbox), 1)
1199 e7cb4085 Kostas Papadimitriou
1200 e7cb4085 Kostas Papadimitriou
        # step two, verify email (automatically
1201 e7cb4085 Kostas Papadimitriou
        # moderates/accepts user, since moderation is disabled)
1202 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1203 e7cb4085 Kostas Papadimitriou
        valid_code = user.verification_code
1204 e7cb4085 Kostas Papadimitriou
1205 e7cb4085 Kostas Papadimitriou
        # test invalid code
1206 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, valid_code)
1207 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1208 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('manager@synnefo.org')), 1)
1209 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('helpdesk@synnefo.org')), 1)
1210 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('admin@synnefo.org')), 1)
1211 e7cb4085 Kostas Papadimitriou
        # verification + activated + greeting = 3
1212 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(mail.outbox), 3)
1213 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1214 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, True)
1215 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated, True)
1216 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.moderated_at)
1217 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, True)
1218 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
1219 e7cb4085 Kostas Papadimitriou
1220 e7cb4085 Kostas Papadimitriou
    @im_settings(MODERATION_ENABLED=True,
1221 e7cb4085 Kostas Papadimitriou
                 MANAGERS=(('Manager',
1222 e7cb4085 Kostas Papadimitriou
                            'manager@synnefo.org'),),
1223 e7cb4085 Kostas Papadimitriou
                 HELPDESK=(('Helpdesk',
1224 e7cb4085 Kostas Papadimitriou
                            'helpdesk@synnefo.org'),),
1225 e7cb4085 Kostas Papadimitriou
                 ADMINS=(('Admin', 'admin@synnefo.org'), ))
1226 e7cb4085 Kostas Papadimitriou
    def test_with_moderation(self):
1227 e7cb4085 Kostas Papadimitriou
1228 e7cb4085 Kostas Papadimitriou
        backend = activation_backends.get_backend()
1229 e7cb4085 Kostas Papadimitriou
        form = backend.get_signup_form('local')
1230 e7cb4085 Kostas Papadimitriou
        self.assertTrue(isinstance(form, forms.LocalUserCreationForm))
1231 e7cb4085 Kostas Papadimitriou
1232 e7cb4085 Kostas Papadimitriou
        user_data = {
1233 e7cb4085 Kostas Papadimitriou
            'email': 'kpap@synnefo.org',
1234 e7cb4085 Kostas Papadimitriou
            'first_name': 'Kostas Papas',
1235 e7cb4085 Kostas Papadimitriou
            'password1': '123',
1236 e7cb4085 Kostas Papadimitriou
            'password2': '123'
1237 e7cb4085 Kostas Papadimitriou
        }
1238 e7cb4085 Kostas Papadimitriou
        form = backend.get_signup_form(provider='local',
1239 e7cb4085 Kostas Papadimitriou
                                       initial_data=user_data)
1240 e7cb4085 Kostas Papadimitriou
        user = form.save(commit=False)
1241 e7cb4085 Kostas Papadimitriou
        form.store_user(user)
1242 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1243 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, False)
1244 e7cb4085 Kostas Papadimitriou
1245 e7cb4085 Kostas Papadimitriou
        # step one, registration
1246 e7cb4085 Kostas Papadimitriou
        result = backend.handle_registration(user)
1247 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1248 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1249 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, False)
1250 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.verification_code)
1251 e7cb4085 Kostas Papadimitriou
        self.assertEqual(result.status, backend.Result.PENDING_VERIFICATION)
1252 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1253 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@synnefo.org')), 1)
1254 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(mail.outbox), 1)
1255 e7cb4085 Kostas Papadimitriou
1256 e7cb4085 Kostas Papadimitriou
        # step two, verifying email
1257 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1258 e7cb4085 Kostas Papadimitriou
        valid_code = user.verification_code
1259 e7cb4085 Kostas Papadimitriou
        invalid_code = user.verification_code + 'invalid'
1260 e7cb4085 Kostas Papadimitriou
1261 e7cb4085 Kostas Papadimitriou
        # test invalid code
1262 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, invalid_code)
1263 e7cb4085 Kostas Papadimitriou
        self.assertEqual(result.status, backend.Result.ERROR)
1264 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1265 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1266 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1267 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated, False)
1268 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated_at, None)
1269 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, False)
1270 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
1271 e7cb4085 Kostas Papadimitriou
1272 e7cb4085 Kostas Papadimitriou
        # test valid code
1273 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1274 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, valid_code)
1275 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1276 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('manager@synnefo.org')), 1)
1277 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('helpdesk@synnefo.org')), 1)
1278 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('admin@synnefo.org')), 1)
1279 e7cb4085 Kostas Papadimitriou
        self.assertEqual(len(mail.outbox), 2)
1280 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1281 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated, False)
1282 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated_at, None)
1283 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, True)
1284 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
1285 e7cb4085 Kostas Papadimitriou
1286 e7cb4085 Kostas Papadimitriou
        # test code reuse
1287 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, valid_code)
1288 e7cb4085 Kostas Papadimitriou
        self.assertEqual(result.status, backend.Result.ERROR)
1289 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1290 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, False)
1291 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated, False)
1292 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated_at, None)
1293 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, True)
1294 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
1295 e7cb4085 Kostas Papadimitriou
1296 e7cb4085 Kostas Papadimitriou
        # valid code on verified user
1297 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1298 e7cb4085 Kostas Papadimitriou
        valid_code = user.verification_code
1299 e7cb4085 Kostas Papadimitriou
        result = backend.handle_verification(user, valid_code)
1300 e7cb4085 Kostas Papadimitriou
        self.assertEqual(result.status, backend.Result.ERROR)
1301 e7cb4085 Kostas Papadimitriou
1302 e7cb4085 Kostas Papadimitriou
        # step three, moderation user
1303 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1304 e7cb4085 Kostas Papadimitriou
        result = backend.handle_moderation(user)
1305 e7cb4085 Kostas Papadimitriou
        backend.send_result_notifications(result, user)
1306 e7cb4085 Kostas Papadimitriou
1307 e7cb4085 Kostas Papadimitriou
        user = AstakosUser.objects.get()
1308 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.is_active, True)
1309 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.moderated, True)
1310 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.moderated_at)
1311 e7cb4085 Kostas Papadimitriou
        self.assertEqual(user.email_verified, True)
1312 e7cb4085 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
1313 5b65fb47 Kostas Papadimitriou
1314 5b65fb47 Kostas Papadimitriou
1315 5b65fb47 Kostas Papadimitriou
class TestWebloginRedirect(TestCase):
1316 5b65fb47 Kostas Papadimitriou
1317 5b65fb47 Kostas Papadimitriou
    @with_settings(settings, COOKIE_DOMAIN='.astakos.synnefo.org')
1318 5b65fb47 Kostas Papadimitriou
    def test_restricts_domains(self):
1319 5b65fb47 Kostas Papadimitriou
        get_local_user('user1@synnefo.org')
1320 5b65fb47 Kostas Papadimitriou
1321 5b65fb47 Kostas Papadimitriou
        # next url construct helpers
1322 5b65fb47 Kostas Papadimitriou
        weblogin = lambda nxt: reverse('weblogin') + '?next=%s' % nxt
1323 5b65fb47 Kostas Papadimitriou
        weblogin_quoted = lambda nxt: reverse('weblogin') + '?next=%s' % \
1324 5b65fb47 Kostas Papadimitriou
            urllib.quote_plus(nxt)
1325 5b65fb47 Kostas Papadimitriou
1326 5b65fb47 Kostas Papadimitriou
        # common cases
1327 5b65fb47 Kostas Papadimitriou
        invalid_domain = weblogin("https://www.invaliddomain.synnefo.org")
1328 5b65fb47 Kostas Papadimitriou
        invalid_scheme = weblogin("customscheme://localhost")
1329 5b65fb47 Kostas Papadimitriou
        invalid_scheme_with_valid_domain = \
1330 8fb8d0cf Giorgos Korfiatis
            weblogin("http://www.invaliddomain.com")
1331 5b65fb47 Kostas Papadimitriou
        valid_scheme = weblogin("pithos://localhost/")
1332 5b65fb47 Kostas Papadimitriou
        # to be used in assertRedirects
1333 5b65fb47 Kostas Papadimitriou
        valid_scheme_quoted = weblogin_quoted("pithos://localhost/")
1334 5b65fb47 Kostas Papadimitriou
1335 5b65fb47 Kostas Papadimitriou
        # not authenticated, redirects to login which contains next param with
1336 5b65fb47 Kostas Papadimitriou
        # additional nested quoted next params
1337 5b65fb47 Kostas Papadimitriou
        r = self.client.get(valid_scheme, follow=True)
1338 1ecda536 Kostas Papadimitriou
        login_redirect = reverse('login') + '?next=' + \
1339 5b65fb47 Kostas Papadimitriou
            urllib.quote_plus("http://testserver" + valid_scheme_quoted)
1340 5b65fb47 Kostas Papadimitriou
        self.assertRedirects(r, login_redirect)
1341 5b65fb47 Kostas Papadimitriou
1342 5b65fb47 Kostas Papadimitriou
        # authenticate client
1343 5b65fb47 Kostas Papadimitriou
        self.client.login(username="user1@synnefo.org", password="password")
1344 5b65fb47 Kostas Papadimitriou
1345 5b65fb47 Kostas Papadimitriou
        # valid scheme
1346 5b65fb47 Kostas Papadimitriou
        r = self.client.get(valid_scheme, follow=True)
1347 5b65fb47 Kostas Papadimitriou
        url = r.redirect_chain[1][0]
1348 5b65fb47 Kostas Papadimitriou
        # scheme preserved
1349 5b65fb47 Kostas Papadimitriou
        self.assertTrue(url.startswith('pithos://localhost/'))
1350 5b65fb47 Kostas Papadimitriou
        # redirect contains token param
1351 28a890d3 Kostas Papadimitriou
        params = urlparse.urlparse(url.replace('pithos', 'https'),
1352 28a890d3 Kostas Papadimitriou
                                   scheme='https').query
1353 5b65fb47 Kostas Papadimitriou
        params = urlparse.parse_qs(params)
1354 5b65fb47 Kostas Papadimitriou
        self.assertEqual(params['token'][0],
1355 5b65fb47 Kostas Papadimitriou
                         AstakosUser.objects.get().auth_token)
1356 5b65fb47 Kostas Papadimitriou
        # does not contain uuid
1357 387eee94 Kostas Papadimitriou
        # reverted for 0.14.2 to support old pithos desktop clients
1358 387eee94 Kostas Papadimitriou
        #self.assertFalse('uuid' in params)
1359 5b65fb47 Kostas Papadimitriou
1360 5b65fb47 Kostas Papadimitriou
        # invalid cases
1361 5b65fb47 Kostas Papadimitriou
        r = self.client.get(invalid_scheme, follow=True)
1362 5b65fb47 Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)
1363 5b65fb47 Kostas Papadimitriou
1364 5b65fb47 Kostas Papadimitriou
        r = self.client.get(invalid_scheme_with_valid_domain, follow=True)
1365 5b65fb47 Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)
1366 5b65fb47 Kostas Papadimitriou
1367 5b65fb47 Kostas Papadimitriou
        r = self.client.get(invalid_domain, follow=True)
1368 5b65fb47 Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)