Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests.py @ 0a7a4104

History | View | Annotate | Download (57.3 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 478ece6c Kostas Papadimitriou
from contextlib import contextmanager
34 d2633501 Kostas Papadimitriou
35 9d20fe23 Kostas Papadimitriou
import copy
36 d2633501 Kostas Papadimitriou
import datetime
37 478ece6c Kostas Papadimitriou
import functools
38 478ece6c Kostas Papadimitriou
39 d2b8ec7b Christos Stavrakakis
from snf_django.utils.testing import with_settings, override_settings
40 d2633501 Kostas Papadimitriou
41 d2633501 Kostas Papadimitriou
from django.test import TestCase, Client
42 d2633501 Kostas Papadimitriou
from django.core import mail
43 478ece6c Kostas Papadimitriou
from django.http import SimpleCookie, HttpRequest, QueryDict
44 478ece6c Kostas Papadimitriou
from django.utils.importlib import import_module
45 d2633501 Kostas Papadimitriou
46 9d20fe23 Kostas Papadimitriou
from astakos.im.activation_backends import *
47 d2633501 Kostas Papadimitriou
from astakos.im.target.shibboleth import Tokens as ShibbolethTokens
48 d2633501 Kostas Papadimitriou
from astakos.im.models import *
49 d2633501 Kostas Papadimitriou
from astakos.im import functions
50 d2633501 Kostas Papadimitriou
from astakos.im import settings as astakos_settings
51 e5966bd9 Kostas Papadimitriou
from astakos.im import forms
52 d2633501 Kostas Papadimitriou
53 d2633501 Kostas Papadimitriou
from urllib import quote
54 450c7fb0 Kostas Papadimitriou
from datetime import timedelta
55 d2633501 Kostas Papadimitriou
56 2e90e3ec Kostas Papadimitriou
from astakos.im import messages
57 9d20fe23 Kostas Papadimitriou
from astakos.im import auth_providers
58 450c7fb0 Kostas Papadimitriou
from astakos.im import quotas
59 450c7fb0 Kostas Papadimitriou
60 478ece6c Kostas Papadimitriou
from django.conf import settings
61 2e90e3ec Kostas Papadimitriou
62 34a76cdb Kostas Papadimitriou
63 478ece6c Kostas Papadimitriou
# set some common settings
64 34a76cdb Kostas Papadimitriou
astakos_settings.EMAILCHANGE_ENABLED = True
65 478ece6c Kostas Papadimitriou
astakos_settings.RECAPTCHA_ENABLED = False
66 478ece6c Kostas Papadimitriou
67 478ece6c Kostas Papadimitriou
settings.LOGGING_SETUP['disable_existing_loggers'] = False
68 34a76cdb Kostas Papadimitriou
69 0a7a4104 Kostas Papadimitriou
# shortcut decorators to override provider settings
70 0a7a4104 Kostas Papadimitriou
# e.g. shibboleth_settings(ENABLED=True) will set
71 0a7a4104 Kostas Papadimitriou
# ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_ENABLED = True in global synnefo settings
72 0a7a4104 Kostas Papadimitriou
prefixes = {'providers': 'AUTH_PROVIDER_',
73 0a7a4104 Kostas Papadimitriou
            'shibboleth': 'ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_',
74 0a7a4104 Kostas Papadimitriou
            'local': 'ASTAKOS_AUTH_PROVIDER_LOCAL_'}
75 450c7fb0 Kostas Papadimitriou
im_settings = functools.partial(with_settings, astakos_settings)
76 478ece6c Kostas Papadimitriou
shibboleth_settings = functools.partial(with_settings,
77 0a7a4104 Kostas Papadimitriou
                                        settings,
78 478ece6c Kostas Papadimitriou
                                        prefix=prefixes['shibboleth'])
79 0a7a4104 Kostas Papadimitriou
localauth_settings = functools.partial(with_settings, settings,
80 478ece6c Kostas Papadimitriou
                                       prefix=prefixes['local'])
81 478ece6c Kostas Papadimitriou
82 0a7a4104 Kostas Papadimitriou
83 478ece6c Kostas Papadimitriou
class AstakosTestClient(Client):
84 478ece6c Kostas Papadimitriou
    pass
85 478ece6c Kostas Papadimitriou
86 0a7a4104 Kostas Papadimitriou
87 478ece6c Kostas Papadimitriou
class ShibbolethClient(AstakosTestClient):
88 d2633501 Kostas Papadimitriou
    """
89 d2633501 Kostas Papadimitriou
    A shibboleth agnostic client.
90 d2633501 Kostas Papadimitriou
    """
91 9d20fe23 Kostas Papadimitriou
    VALID_TOKENS = filter(lambda x: not x.startswith("_"),
92 9d20fe23 Kostas Papadimitriou
                          dir(ShibbolethTokens))
93 d2633501 Kostas Papadimitriou
94 d2633501 Kostas Papadimitriou
    def __init__(self, *args, **kwargs):
95 d2633501 Kostas Papadimitriou
        self.tokens = kwargs.pop('tokens', {})
96 d2633501 Kostas Papadimitriou
        super(ShibbolethClient, self).__init__(*args, **kwargs)
97 d2633501 Kostas Papadimitriou
98 d2633501 Kostas Papadimitriou
    def set_tokens(self, **kwargs):
99 d2633501 Kostas Papadimitriou
        for key, value in kwargs.iteritems():
100 d2633501 Kostas Papadimitriou
            key = 'SHIB_%s' % key.upper()
101 d2633501 Kostas Papadimitriou
            if not key in self.VALID_TOKENS:
102 d2633501 Kostas Papadimitriou
                raise Exception('Invalid shibboleth token')
103 d2633501 Kostas Papadimitriou
104 d2633501 Kostas Papadimitriou
            self.tokens[key] = value
105 d2633501 Kostas Papadimitriou
106 d2633501 Kostas Papadimitriou
    def unset_tokens(self, *keys):
107 d2633501 Kostas Papadimitriou
        for key in keys:
108 d2633501 Kostas Papadimitriou
            key = 'SHIB_%s' % param.upper()
109 d2633501 Kostas Papadimitriou
            if key in self.tokens:
110 d2633501 Kostas Papadimitriou
                del self.tokens[key]
111 d2633501 Kostas Papadimitriou
112 d2633501 Kostas Papadimitriou
    def reset_tokens(self):
113 d2633501 Kostas Papadimitriou
        self.tokens = {}
114 d2633501 Kostas Papadimitriou
115 d2633501 Kostas Papadimitriou
    def get_http_token(self, key):
116 d2633501 Kostas Papadimitriou
        http_header = getattr(ShibbolethTokens, key)
117 d2633501 Kostas Papadimitriou
        return http_header
118 d2633501 Kostas Papadimitriou
119 d2633501 Kostas Papadimitriou
    def request(self, **request):
120 d2633501 Kostas Papadimitriou
        """
121 d2633501 Kostas Papadimitriou
        Transform valid shibboleth tokens to http headers
122 d2633501 Kostas Papadimitriou
        """
123 d2633501 Kostas Papadimitriou
        for token, value in self.tokens.iteritems():
124 d2633501 Kostas Papadimitriou
            request[self.get_http_token(token)] = value
125 d2633501 Kostas Papadimitriou
126 d2633501 Kostas Papadimitriou
        for param in request.keys():
127 d2633501 Kostas Papadimitriou
            key = 'SHIB_%s' % param.upper()
128 d2633501 Kostas Papadimitriou
            if key in self.VALID_TOKENS:
129 d2633501 Kostas Papadimitriou
                request[self.get_http_token(key)] = request[param]
130 d2633501 Kostas Papadimitriou
                del request[param]
131 d2633501 Kostas Papadimitriou
132 d2633501 Kostas Papadimitriou
        return super(ShibbolethClient, self).request(**request)
133 d2633501 Kostas Papadimitriou
134 d2633501 Kostas Papadimitriou
135 450c7fb0 Kostas Papadimitriou
def get_user_client(username, password="password"):
136 450c7fb0 Kostas Papadimitriou
    client = Client()
137 450c7fb0 Kostas Papadimitriou
    client.login(username=username, password=password)
138 450c7fb0 Kostas Papadimitriou
    return client
139 450c7fb0 Kostas Papadimitriou
140 450c7fb0 Kostas Papadimitriou
141 d2633501 Kostas Papadimitriou
def get_local_user(username, **kwargs):
142 d2633501 Kostas Papadimitriou
        try:
143 d2633501 Kostas Papadimitriou
            return AstakosUser.objects.get(email=username)
144 d2633501 Kostas Papadimitriou
        except:
145 d2633501 Kostas Papadimitriou
            user_params = {
146 d2633501 Kostas Papadimitriou
                'username': username,
147 d2633501 Kostas Papadimitriou
                'email': username,
148 d2633501 Kostas Papadimitriou
                'is_active': True,
149 d2633501 Kostas Papadimitriou
                'activation_sent': datetime.now(),
150 d2633501 Kostas Papadimitriou
                'email_verified': True,
151 d2633501 Kostas Papadimitriou
                'provider': 'local'
152 d2633501 Kostas Papadimitriou
            }
153 d2633501 Kostas Papadimitriou
            user_params.update(kwargs)
154 d2633501 Kostas Papadimitriou
            user = AstakosUser(**user_params)
155 d2633501 Kostas Papadimitriou
            user.set_password(kwargs.get('password', 'password'))
156 d2633501 Kostas Papadimitriou
            user.save()
157 d2633501 Kostas Papadimitriou
            user.add_auth_provider('local', auth_backend='astakos')
158 d2633501 Kostas Papadimitriou
            if kwargs.get('is_active', True):
159 d2633501 Kostas Papadimitriou
                user.is_active = True
160 d2633501 Kostas Papadimitriou
            else:
161 d2633501 Kostas Papadimitriou
                user.is_active = False
162 d2633501 Kostas Papadimitriou
            user.save()
163 d2633501 Kostas Papadimitriou
            return user
164 d2633501 Kostas Papadimitriou
165 d2633501 Kostas Papadimitriou
166 d2633501 Kostas Papadimitriou
def get_mailbox(email):
167 d2633501 Kostas Papadimitriou
    mails = []
168 d2633501 Kostas Papadimitriou
    for sent_email in mail.outbox:
169 d2633501 Kostas Papadimitriou
        for recipient in sent_email.recipients():
170 d2633501 Kostas Papadimitriou
            if email in recipient:
171 d2633501 Kostas Papadimitriou
                mails.append(sent_email)
172 d2633501 Kostas Papadimitriou
    return mails
173 d2633501 Kostas Papadimitriou
174 d2633501 Kostas Papadimitriou
175 d2633501 Kostas Papadimitriou
class ShibbolethTests(TestCase):
176 d2633501 Kostas Papadimitriou
    """
177 d2633501 Kostas Papadimitriou
    Testing shibboleth authentication.
178 d2633501 Kostas Papadimitriou
    """
179 d2633501 Kostas Papadimitriou
180 d2633501 Kostas Papadimitriou
    fixtures = ['groups']
181 d2633501 Kostas Papadimitriou
182 d2633501 Kostas Papadimitriou
    def setUp(self):
183 d2633501 Kostas Papadimitriou
        self.client = ShibbolethClient()
184 9d20fe23 Kostas Papadimitriou
        astakos_settings.IM_MODULES = ['local', 'shibboleth']
185 9d20fe23 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
186 d2633501 Kostas Papadimitriou
187 0a7a4104 Kostas Papadimitriou
    @im_settings(FORCE_PROFILE_UPDATE=False)
188 d2633501 Kostas Papadimitriou
    def test_create_account(self):
189 ba50648c Kostas Papadimitriou
190 d2633501 Kostas Papadimitriou
        client = ShibbolethClient()
191 d2633501 Kostas Papadimitriou
192 d2633501 Kostas Papadimitriou
        # shibboleth views validation
193 d2633501 Kostas Papadimitriou
        # eepn required
194 d2633501 Kostas Papadimitriou
        r = client.get('/im/login/shibboleth?', follow=True)
195 e24d0e0d Kostas Papadimitriou
        self.assertContains(r, messages.SHIBBOLETH_MISSING_EPPN % {
196 e24d0e0d Kostas Papadimitriou
            'domain': astakos_settings.BASEURL,
197 31bc3a62 Kostas Papadimitriou
            'contact_email': settings.CONTACT_EMAIL
198 e24d0e0d Kostas Papadimitriou
        })
199 d2633501 Kostas Papadimitriou
        client.set_tokens(eppn="kpapeppn")
200 ba50648c Kostas Papadimitriou
201 31fdafa8 Kostas Papadimitriou
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = True
202 d2633501 Kostas Papadimitriou
        # shibboleth user info required
203 d2633501 Kostas Papadimitriou
        r = client.get('/im/login/shibboleth?', follow=True)
204 2e90e3ec Kostas Papadimitriou
        self.assertContains(r, messages.SHIBBOLETH_MISSING_NAME)
205 31fdafa8 Kostas Papadimitriou
        astakos_settings.SHIBBOLETH_REQUIRE_NAME_INFO = False
206 d2633501 Kostas Papadimitriou
207 d2633501 Kostas Papadimitriou
        # shibboleth logged us in
208 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn",
209 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou",
210 ba50648c Kostas Papadimitriou
                          ep_affiliation="Test Affiliation")
211 f47ecf6b Kostas Papadimitriou
        r = client.get('/im/login/shibboleth?', follow=True)
212 9d20fe23 Kostas Papadimitriou
        token = PendingThirdPartyUser.objects.get().token
213 9d20fe23 Kostas Papadimitriou
        self.assertRedirects(r, '/im/signup?third_party_token=%s' % token)
214 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
215 d2633501 Kostas Papadimitriou
216 d2633501 Kostas Papadimitriou
        # a new pending user created
217 d2633501 Kostas Papadimitriou
        pending_user = PendingThirdPartyUser.objects.get(
218 d2633501 Kostas Papadimitriou
            third_party_identifier="kpapeppn")
219 d2633501 Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
220 ba50648c Kostas Papadimitriou
        # keep the token for future use
221 d2633501 Kostas Papadimitriou
        token = pending_user.token
222 d2633501 Kostas Papadimitriou
        # from now on no shibboleth headers are sent to the server
223 d2633501 Kostas Papadimitriou
        client.reset_tokens()
224 d2633501 Kostas Papadimitriou
225 ba50648c Kostas Papadimitriou
        # this is the old way, it should fail, to avoid pending user take over
226 d2633501 Kostas Papadimitriou
        r = client.get('/im/shibboleth/signup/%s' % pending_user.username)
227 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
228 d2633501 Kostas Papadimitriou
229 9d20fe23 Kostas Papadimitriou
        # this is the signup unique url associated with the pending user
230 9d20fe23 Kostas Papadimitriou
        # created
231 ba50648c Kostas Papadimitriou
        r = client.get('/im/signup/?third_party_token=%s' % token)
232 9d20fe23 Kostas Papadimitriou
        identifier = pending_user.third_party_identifier
233 9d20fe23 Kostas Papadimitriou
        post_data = {'third_party_identifier': identifier,
234 d2633501 Kostas Papadimitriou
                     'first_name': 'Kostas',
235 d2633501 Kostas Papadimitriou
                     'third_party_token': token,
236 d2633501 Kostas Papadimitriou
                     'last_name': 'Mitroglou',
237 9d20fe23 Kostas Papadimitriou
                     'provider': 'shibboleth'}
238 ba50648c Kostas Papadimitriou
239 0a7a4104 Kostas Papadimitriou
        signup_url = reverse('signup')
240 0a7a4104 Kostas Papadimitriou
241 ba50648c Kostas Papadimitriou
        # invlid email
242 ba50648c Kostas Papadimitriou
        post_data['email'] = 'kpap'
243 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data)
244 8ab484ea Kostas Papadimitriou
        self.assertContains(r, token)
245 ba50648c Kostas Papadimitriou
246 ba50648c Kostas Papadimitriou
        # existing email
247 ba50648c Kostas Papadimitriou
        existing_user = get_local_user('test@test.com')
248 ba50648c Kostas Papadimitriou
        post_data['email'] = 'test@test.com'
249 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data)
250 ba50648c Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_USED)
251 ba50648c Kostas Papadimitriou
        existing_user.delete()
252 ba50648c Kostas Papadimitriou
253 ba50648c Kostas Papadimitriou
        # and finally a valid signup
254 8ab484ea Kostas Papadimitriou
        post_data['email'] = 'kpap@grnet.gr'
255 0a7a4104 Kostas Papadimitriou
        r = client.post(signup_url, post_data, follow=True)
256 e5966bd9 Kostas Papadimitriou
        self.assertContains(r, messages.NOTIFICATION_SENT)
257 ba50648c Kostas Papadimitriou
258 ba50648c Kostas Papadimitriou
        # everything is ok in our db
259 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
260 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUserAuthProvider.objects.count(), 1)
261 ba50648c Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 0)
262 d2633501 Kostas Papadimitriou
263 ba50648c Kostas Papadimitriou
        # provider info stored
264 ba50648c Kostas Papadimitriou
        provider = AstakosUserAuthProvider.objects.get(module="shibboleth")
265 ba50648c Kostas Papadimitriou
        self.assertEqual(provider.affiliation, 'Test Affiliation')
266 ba50648c Kostas Papadimitriou
        self.assertEqual(provider.info, {u'email': u'kpap@grnet.gr',
267 e5966bd9 Kostas Papadimitriou
                                         u'eppn': u'kpapeppn',
268 e5966bd9 Kostas Papadimitriou
                                         u'name': u'Kostas Papadimitriou'})
269 d2633501 Kostas Papadimitriou
270 ba50648c Kostas Papadimitriou
        # lets login (not activated yet)
271 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppn",
272 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
273 d2633501 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
274 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'is pending moderation')
275 d2633501 Kostas Papadimitriou
276 ba50648c Kostas Papadimitriou
        # admin activates our user
277 ba50648c Kostas Papadimitriou
        u = AstakosUser.objects.get(username="kpap@grnet.gr")
278 d2633501 Kostas Papadimitriou
        functions.activate(u)
279 d2633501 Kostas Papadimitriou
        self.assertEqual(u.is_active, True)
280 d2633501 Kostas Papadimitriou
281 ba50648c Kostas Papadimitriou
        # we see our profile
282 ba50648c Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
283 478ece6c Kostas Papadimitriou
        self.assertRedirects(r, '/im/landing')
284 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
285 d2633501 Kostas Papadimitriou
286 d2633501 Kostas Papadimitriou
    def test_existing(self):
287 ba50648c Kostas Papadimitriou
        """
288 ba50648c Kostas Papadimitriou
        Test adding of third party login to an existing account
289 ba50648c Kostas Papadimitriou
        """
290 ba50648c Kostas Papadimitriou
291 ba50648c Kostas Papadimitriou
        # this is our existing user
292 d2633501 Kostas Papadimitriou
        existing_user = get_local_user('kpap@grnet.gr')
293 478ece6c Kostas Papadimitriou
        existing_inactive = get_local_user('kpap-inactive@grnet.gr')
294 478ece6c Kostas Papadimitriou
        existing_inactive.is_active = False
295 478ece6c Kostas Papadimitriou
        existing_inactive.save()
296 478ece6c Kostas Papadimitriou
297 478ece6c Kostas Papadimitriou
        existing_unverified = get_local_user('kpap-unverified@grnet.gr')
298 478ece6c Kostas Papadimitriou
        existing_unverified.is_active = False
299 478ece6c Kostas Papadimitriou
        existing_unverified.activation_sent = None
300 478ece6c Kostas Papadimitriou
        existing_unverified.email_verified = False
301 478ece6c Kostas Papadimitriou
        existing_unverified.is_verified = False
302 478ece6c Kostas Papadimitriou
        existing_unverified.save()
303 d2633501 Kostas Papadimitriou
304 d2633501 Kostas Papadimitriou
        client = ShibbolethClient()
305 d2633501 Kostas Papadimitriou
        # shibboleth logged us in, notice that we use different email
306 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
307 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
308 9d20fe23 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
309 d2633501 Kostas Papadimitriou
310 d2633501 Kostas Papadimitriou
        # a new pending user created
311 d2633501 Kostas Papadimitriou
        pending_user = PendingThirdPartyUser.objects.get()
312 9d20fe23 Kostas Papadimitriou
        token = pending_user.token
313 d2633501 Kostas Papadimitriou
        self.assertEqual(PendingThirdPartyUser.objects.count(), 1)
314 d2633501 Kostas Papadimitriou
        pending_key = pending_user.token
315 d2633501 Kostas Papadimitriou
        client.reset_tokens()
316 9d20fe23 Kostas Papadimitriou
        self.assertRedirects(r, "/im/signup?third_party_token=%s" % token)
317 d2633501 Kostas Papadimitriou
318 9d20fe23 Kostas Papadimitriou
        form = r.context['form']
319 9d20fe23 Kostas Papadimitriou
        signupdata = copy.copy(form.initial)
320 9d20fe23 Kostas Papadimitriou
        signupdata['email'] = 'kpap@grnet.gr'
321 9d20fe23 Kostas Papadimitriou
        signupdata['third_party_token'] = token
322 9d20fe23 Kostas Papadimitriou
        signupdata['provider'] = 'shibboleth'
323 9d20fe23 Kostas Papadimitriou
        del signupdata['id']
324 d2633501 Kostas Papadimitriou
325 478ece6c Kostas Papadimitriou
        # the email exists to another user
326 478ece6c Kostas Papadimitriou
        r = client.post("/im/signup", signupdata)
327 478ece6c Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
328 478ece6c Kostas Papadimitriou
                               "address")
329 478ece6c Kostas Papadimitriou
        # change the case, still cannot create
330 478ece6c Kostas Papadimitriou
        signupdata['email'] = 'KPAP@grnet.GR'
331 478ece6c Kostas Papadimitriou
        r = client.post("/im/signup", signupdata)
332 478ece6c Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
333 478ece6c Kostas Papadimitriou
                               "address")
334 478ece6c Kostas Papadimitriou
        # inactive user
335 478ece6c Kostas Papadimitriou
        signupdata['email'] = 'KPAP-inactive@grnet.GR'
336 9d20fe23 Kostas Papadimitriou
        r = client.post("/im/signup", signupdata)
337 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "There is already an account with this email "
338 9d20fe23 Kostas Papadimitriou
                               "address")
339 d2633501 Kostas Papadimitriou
340 478ece6c Kostas Papadimitriou
        # unverified user, this should pass, old entry will be deleted
341 478ece6c Kostas Papadimitriou
        signupdata['email'] = 'KAPAP-unverified@grnet.GR'
342 478ece6c Kostas Papadimitriou
        r = client.post("/im/signup", signupdata)
343 478ece6c Kostas Papadimitriou
344 d2633501 Kostas Papadimitriou
        post_data = {'password': 'password',
345 9d20fe23 Kostas Papadimitriou
                     'username': 'kpap@grnet.gr'}
346 9d20fe23 Kostas Papadimitriou
        r = client.post('/im/local', post_data, follow=True)
347 9d20fe23 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
348 9d20fe23 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
349 9d20fe23 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
350 9d20fe23 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
351 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "enabled for this account")
352 9d20fe23 Kostas Papadimitriou
        client.reset_tokens()
353 9d20fe23 Kostas Papadimitriou
354 9d20fe23 Kostas Papadimitriou
        user = existing_user
355 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('shibboleth'))
356 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('local',
357 9d20fe23 Kostas Papadimitriou
                                               auth_backend='astakos'))
358 d2633501 Kostas Papadimitriou
        client.logout()
359 d2633501 Kostas Papadimitriou
360 d2633501 Kostas Papadimitriou
        # look Ma, i can login with both my shibboleth and local account
361 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
362 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
363 d2633501 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
364 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
365 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.email == "kpap@grnet.gr")
366 478ece6c Kostas Papadimitriou
        self.assertRedirects(r, '/im/landing')
367 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
368 d2633501 Kostas Papadimitriou
        client.logout()
369 d2633501 Kostas Papadimitriou
        client.reset_tokens()
370 ba50648c Kostas Papadimitriou
371 ba50648c Kostas Papadimitriou
        # logged out
372 d2633501 Kostas Papadimitriou
        r = client.get("/im/profile", follow=True)
373 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
374 d2633501 Kostas Papadimitriou
375 ba50648c Kostas Papadimitriou
        # login with local account also works
376 d2633501 Kostas Papadimitriou
        post_data = {'password': 'password',
377 d2633501 Kostas Papadimitriou
                     'username': 'kpap@grnet.gr'}
378 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local', post_data, follow=True)
379 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
380 ba50648c Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.email == "kpap@grnet.gr")
381 9d20fe23 Kostas Papadimitriou
        self.assertRedirects(r, '/im/landing')
382 ba50648c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
383 d2633501 Kostas Papadimitriou
384 ba50648c Kostas Papadimitriou
        # cannot add the same eppn
385 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn",
386 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", )
387 d2633501 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
388 478ece6c Kostas Papadimitriou
        self.assertRedirects(r, '/im/landing')
389 ba50648c Kostas Papadimitriou
        self.assertTrue(r.status_code, 200)
390 ba50648c Kostas Papadimitriou
        self.assertEquals(existing_user.auth_providers.count(), 2)
391 d2633501 Kostas Papadimitriou
392 9d20fe23 Kostas Papadimitriou
        # only one allowed by default
393 ba50648c Kostas Papadimitriou
        client.set_tokens(mail="secondary@shibboleth.gr", eppn="kpapeppn2",
394 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou", ep_affiliation="affil2")
395 9d20fe23 Kostas Papadimitriou
        prov = auth_providers.get_provider('shibboleth')
396 ba50648c Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
397 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "Failed to add")
398 ba50648c Kostas Papadimitriou
        self.assertRedirects(r, '/im/profile')
399 ba50648c Kostas Papadimitriou
        self.assertTrue(r.status_code, 200)
400 9d20fe23 Kostas Papadimitriou
        self.assertEquals(existing_user.auth_providers.count(), 2)
401 d2633501 Kostas Papadimitriou
        client.logout()
402 ba50648c Kostas Papadimitriou
        client.reset_tokens()
403 ba50648c Kostas Papadimitriou
404 ba50648c Kostas Papadimitriou
        # cannot login with another eppn
405 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@grnet.gr", eppn="kpapeppninvalid",
406 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
407 d2633501 Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
408 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
409 d2633501 Kostas Papadimitriou
410 478ece6c Kostas Papadimitriou
        # cannot
411 478ece6c Kostas Papadimitriou
412 f432088a Kostas Papadimitriou
        # lets remove local password
413 f432088a Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
414 f432088a Kostas Papadimitriou
                                       email="kpap@grnet.gr")
415 9d20fe23 Kostas Papadimitriou
        remove_local_url = user.get_auth_provider('local').get_remove_url
416 9d20fe23 Kostas Papadimitriou
        remove_shibbo_url = user.get_auth_provider('shibboleth',
417 9d20fe23 Kostas Papadimitriou
                                                   'kpapeppn').get_remove_url
418 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
419 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimtriou")
420 f432088a Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
421 f432088a Kostas Papadimitriou
        client.reset_tokens()
422 ba50648c Kostas Papadimitriou
423 ba50648c Kostas Papadimitriou
        # TODO: this view should use POST
424 ba50648c Kostas Papadimitriou
        r = client.get(remove_local_url)
425 ba50648c Kostas Papadimitriou
        # 2 providers left
426 f432088a Kostas Papadimitriou
        self.assertEqual(user.auth_providers.count(), 1)
427 ba50648c Kostas Papadimitriou
        # cannot remove last provider
428 ba50648c Kostas Papadimitriou
        r = client.get(remove_shibbo_url)
429 f432088a Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)
430 f432088a Kostas Papadimitriou
        self.client.logout()
431 ba50648c Kostas Papadimitriou
432 ba50648c Kostas Papadimitriou
        # cannot login using local credentials (notice we use another client)
433 f432088a Kostas Papadimitriou
        post_data = {'password': 'password',
434 f432088a Kostas Papadimitriou
                     'username': 'kpap@grnet.gr'}
435 f432088a Kostas Papadimitriou
        r = self.client.post('/im/local', post_data, follow=True)
436 f432088a Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
437 f432088a Kostas Papadimitriou
438 ba50648c Kostas Papadimitriou
        # we can reenable the local provider by setting a password
439 f432088a Kostas Papadimitriou
        r = client.get("/im/password_change", follow=True)
440 0a7a4104 Kostas Papadimitriou
        r = client.post("/im/password_change", {'new_password1': '111',
441 f432088a Kostas Papadimitriou
                                                'new_password2': '111'},
442 f432088a Kostas Papadimitriou
                        follow=True)
443 f432088a Kostas Papadimitriou
        user = r.context['request'].user
444 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('local'))
445 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_auth_provider('shibboleth'))
446 f432088a Kostas Papadimitriou
        self.assertTrue(user.check_password('111'))
447 f432088a Kostas Papadimitriou
        self.assertTrue(user.has_usable_password())
448 f432088a Kostas Papadimitriou
        self.client.logout()
449 ba50648c Kostas Papadimitriou
450 ba50648c Kostas Papadimitriou
        # now we can login
451 f432088a Kostas Papadimitriou
        post_data = {'password': '111',
452 f432088a Kostas Papadimitriou
                     'username': 'kpap@grnet.gr'}
453 f432088a Kostas Papadimitriou
        r = self.client.post('/im/local', post_data, follow=True)
454 f432088a Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
455 f432088a Kostas Papadimitriou
456 ba50648c Kostas Papadimitriou
        client.reset_tokens()
457 f432088a Kostas Papadimitriou
458 ba50648c Kostas Papadimitriou
        # we cannot take over another shibboleth identifier
459 f432088a Kostas Papadimitriou
        user2 = get_local_user('another@grnet.gr')
460 f432088a Kostas Papadimitriou
        user2.add_auth_provider('shibboleth', identifier='existingeppn')
461 ba50648c Kostas Papadimitriou
        # login
462 e5966bd9 Kostas Papadimitriou
        client.set_tokens(mail="kpap@shibboleth.gr", eppn="kpapeppn",
463 e5966bd9 Kostas Papadimitriou
                          cn="Kostas Papadimitriou")
464 f432088a Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
465 ba50648c Kostas Papadimitriou
        # try to assign existing shibboleth identifier of another user
466 9d20fe23 Kostas Papadimitriou
        client.set_tokens(mail="kpap_second@shibboleth.gr",
467 9d20fe23 Kostas Papadimitriou
                          eppn="existingeppn", cn="Kostas Papadimitriou")
468 f432088a Kostas Papadimitriou
        r = client.get("/im/login/shibboleth?", follow=True)
469 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "this account is already assigned")
470 2e90e3ec Kostas Papadimitriou
471 d2633501 Kostas Papadimitriou
472 478ece6c Kostas Papadimitriou
class TestLocal(TestCase):
473 d2633501 Kostas Papadimitriou
474 d2633501 Kostas Papadimitriou
    fixtures = ['groups']
475 d2633501 Kostas Papadimitriou
476 2e90e3ec Kostas Papadimitriou
    def setUp(self):
477 2e90e3ec Kostas Papadimitriou
        settings.ADMINS = (('admin', 'support@cloud.grnet.gr'),)
478 2e90e3ec Kostas Papadimitriou
        settings.SERVER_EMAIL = 'no-reply@grnet.gr'
479 9d20fe23 Kostas Papadimitriou
        self._orig_moderation = astakos_settings.MODERATION_ENABLED
480 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_MODERATION_ENABLED = True
481 9d20fe23 Kostas Papadimitriou
482 9d20fe23 Kostas Papadimitriou
    def tearDown(self):
483 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_MODERATION_ENABLED = self._orig_moderation
484 2e90e3ec Kostas Papadimitriou
485 7233d542 Kostas Papadimitriou
    def test_no_moderation(self):
486 ba50648c Kostas Papadimitriou
        # disable moderation
487 7233d542 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = False
488 ba50648c Kostas Papadimitriou
489 ba50648c Kostas Papadimitriou
        # create a new user
490 7233d542 Kostas Papadimitriou
        r = self.client.get("/im/signup")
491 7233d542 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
492 9d20fe23 Kostas Papadimitriou
        data = {'email': 'kpap@grnet.gr', 'password1': 'password',
493 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
494 7233d542 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
495 7233d542 Kostas Papadimitriou
        r = self.client.post("/im/signup", data)
496 ba50648c Kostas Papadimitriou
497 ba50648c Kostas Papadimitriou
        # user created
498 7233d542 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
499 7233d542 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
500 7233d542 Kostas Papadimitriou
                                       email="kpap@grnet.gr")
501 7233d542 Kostas Papadimitriou
        self.assertEqual(user.username, 'kpap@grnet.gr')
502 7233d542 Kostas Papadimitriou
        self.assertEqual(user.has_auth_provider('local'), True)
503 7233d542 Kostas Papadimitriou
        self.assertFalse(user.is_active)
504 7233d542 Kostas Papadimitriou
505 ba50648c Kostas Papadimitriou
        # user (but not admin) gets notified
506 7233d542 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('support@cloud.grnet.gr')), 0)
507 7233d542 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
508 7233d542 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
509 d2633501 Kostas Papadimitriou
510 e5966bd9 Kostas Papadimitriou
    def test_email_case(self):
511 e5966bd9 Kostas Papadimitriou
        data = {
512 9d20fe23 Kostas Papadimitriou
            'email': 'kPap@grnet.gr',
513 9d20fe23 Kostas Papadimitriou
            'password1': '1234',
514 9d20fe23 Kostas Papadimitriou
            'password2': '1234'
515 e5966bd9 Kostas Papadimitriou
        }
516 e5966bd9 Kostas Papadimitriou
517 e5966bd9 Kostas Papadimitriou
        form = forms.LocalUserCreationForm(data)
518 e5966bd9 Kostas Papadimitriou
        self.assertTrue(form.is_valid())
519 e5966bd9 Kostas Papadimitriou
        user = form.save()
520 e5966bd9 Kostas Papadimitriou
        form.store_user(user, {})
521 e5966bd9 Kostas Papadimitriou
522 9d20fe23 Kostas Papadimitriou
        u = AstakosUser.objects.get()
523 e5966bd9 Kostas Papadimitriou
        self.assertEqual(u.email, 'kPap@grnet.gr')
524 e5966bd9 Kostas Papadimitriou
        self.assertEqual(u.username, 'kpap@grnet.gr')
525 e5966bd9 Kostas Papadimitriou
        u.is_active = True
526 e5966bd9 Kostas Papadimitriou
        u.email_verified = True
527 e5966bd9 Kostas Papadimitriou
        u.save()
528 e5966bd9 Kostas Papadimitriou
529 e5966bd9 Kostas Papadimitriou
        data = {'username': 'kpap@grnet.gr', 'password': '1234'}
530 e5966bd9 Kostas Papadimitriou
        login = forms.LoginForm(data=data)
531 e5966bd9 Kostas Papadimitriou
        self.assertTrue(login.is_valid())
532 e5966bd9 Kostas Papadimitriou
533 e5966bd9 Kostas Papadimitriou
        data = {'username': 'KpaP@grnet.gr', 'password': '1234'}
534 e5966bd9 Kostas Papadimitriou
        login = forms.LoginForm(data=data)
535 e5966bd9 Kostas Papadimitriou
        self.assertTrue(login.is_valid())
536 e5966bd9 Kostas Papadimitriou
537 e5966bd9 Kostas Papadimitriou
        data = {
538 9d20fe23 Kostas Papadimitriou
            'email': 'kpap@grnet.gr',
539 9d20fe23 Kostas Papadimitriou
            'password1': '1234',
540 9d20fe23 Kostas Papadimitriou
            'password2': '1234'
541 e5966bd9 Kostas Papadimitriou
        }
542 e5966bd9 Kostas Papadimitriou
        form = forms.LocalUserCreationForm(data)
543 e5966bd9 Kostas Papadimitriou
        self.assertFalse(form.is_valid())
544 e5966bd9 Kostas Papadimitriou
545 0a7a4104 Kostas Papadimitriou
    @im_settings(HELPDESK=(('support', 'support@synnefo.org'),))
546 0a7a4104 Kostas Papadimitriou
    @im_settings(FORCE_PROFILE_UPDATE=False)
547 d2633501 Kostas Papadimitriou
    def test_local_provider(self):
548 19a992e3 Kostas Papadimitriou
        self.helpdesk_email = astakos_settings.HELPDESK[0][1]
549 ba50648c Kostas Papadimitriou
        # enable moderation
550 7233d542 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
551 ba50648c Kostas Papadimitriou
552 ba50648c Kostas Papadimitriou
        # create a user
553 d2633501 Kostas Papadimitriou
        r = self.client.get("/im/signup")
554 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
555 9d20fe23 Kostas Papadimitriou
        data = {'email': 'kpap@grnet.gr', 'password1': 'password',
556 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
557 d2633501 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
558 d2633501 Kostas Papadimitriou
        r = self.client.post("/im/signup", data)
559 ba50648c Kostas Papadimitriou
560 ba50648c Kostas Papadimitriou
        # user created
561 d2633501 Kostas Papadimitriou
        self.assertEqual(AstakosUser.objects.count(), 1)
562 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(username="kpap@grnet.gr",
563 d2633501 Kostas Papadimitriou
                                       email="kpap@grnet.gr")
564 d2633501 Kostas Papadimitriou
        self.assertEqual(user.username, 'kpap@grnet.gr')
565 d2633501 Kostas Papadimitriou
        self.assertEqual(user.has_auth_provider('local'), True)
566 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user.is_active)  # not activated
567 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user.email_verified)  # not verified
568 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user.activation_sent)  # activation automatically sent
569 d2633501 Kostas Papadimitriou
570 ba50648c Kostas Papadimitriou
        # admin gets notified and activates the user from the command line
571 19a992e3 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox(self.helpdesk_email)), 1)
572 31fdafa8 Kostas Papadimitriou
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
573 9d20fe23 Kostas Papadimitriou
                                           'password': 'password'})
574 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, messages.NOTIFICATION_SENT)
575 d2633501 Kostas Papadimitriou
        functions.send_activation(user)
576 d2633501 Kostas Papadimitriou
577 ba50648c Kostas Papadimitriou
        # user activation fields updated and user gets notified via email
578 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
579 d2633501 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
580 d2633501 Kostas Papadimitriou
        self.assertFalse(user.email_verified)
581 f47ecf6b Kostas Papadimitriou
        self.assertFalse(user.is_active)
582 d2633501 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 1)
583 d2633501 Kostas Papadimitriou
584 d2633501 Kostas Papadimitriou
        # user forgot she got registered and tries to submit registration
585 d2633501 Kostas Papadimitriou
        # form. Notice the upper case in email
586 9d20fe23 Kostas Papadimitriou
        data = {'email': 'KPAP@grnet.gr', 'password1': 'password',
587 9d20fe23 Kostas Papadimitriou
                'password2': 'password', 'first_name': 'Kostas',
588 d2633501 Kostas Papadimitriou
                'last_name': 'Mitroglou', 'provider': 'local'}
589 564a2292 Kostas Papadimitriou
        r = self.client.post("/im/signup", data, follow=True)
590 564a2292 Kostas Papadimitriou
        self.assertRedirects(r, reverse('index'))
591 564a2292 Kostas Papadimitriou
        self.assertContains(r, messages.NOTIFICATION_SENT)
592 564a2292 Kostas Papadimitriou
593 9d20fe23 Kostas Papadimitriou
        user = AstakosUser.objects.get()
594 9d20fe23 Kostas Papadimitriou
        functions.send_activation(user)
595 9d20fe23 Kostas Papadimitriou
596 564a2292 Kostas Papadimitriou
        # previous user replaced
597 564a2292 Kostas Papadimitriou
        self.assertTrue(user.activation_sent)
598 564a2292 Kostas Papadimitriou
        self.assertFalse(user.email_verified)
599 564a2292 Kostas Papadimitriou
        self.assertFalse(user.is_active)
600 9d20fe23 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@grnet.gr')), 1)
601 d2633501 Kostas Papadimitriou
602 f47ecf6b Kostas Papadimitriou
        # hmmm, email exists; lets request a password change
603 d2633501 Kostas Papadimitriou
        r = self.client.get('/im/local/password_reset')
604 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
605 9d20fe23 Kostas Papadimitriou
        data = {'email': 'kpap@grnet.gr'}
606 9d20fe23 Kostas Papadimitriou
        r = self.client.post('/im/local/password_reset', data, follow=True)
607 d2633501 Kostas Papadimitriou
        # she can't because account is not active yet
608 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'pending activation')
609 d2633501 Kostas Papadimitriou
610 9d20fe23 Kostas Papadimitriou
        # moderation is enabled and an activation email has already been sent
611 9d20fe23 Kostas Papadimitriou
        # so user can trigger resend of the activation email
612 9d20fe23 Kostas Papadimitriou
        r = self.client.get('/im/send/activation/%d' % user.pk, follow=True)
613 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, 'has been sent to your email address.')
614 9d20fe23 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@grnet.gr')), 2)
615 ba50648c Kostas Papadimitriou
616 d2633501 Kostas Papadimitriou
        # also she cannot login
617 9d20fe23 Kostas Papadimitriou
        data = {'username': 'kpap@grnet.gr', 'password': 'password'}
618 9d20fe23 Kostas Papadimitriou
        r = self.client.post('/im/local', data, follow=True)
619 d2633501 Kostas Papadimitriou
        self.assertContains(r, 'Resend activation')
620 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
621 d2633501 Kostas Papadimitriou
        self.assertFalse('_pithos2_a' in self.client.cookies)
622 ba50648c Kostas Papadimitriou
623 d2633501 Kostas Papadimitriou
        # user sees the message and resends activation
624 9d20fe23 Kostas Papadimitriou
        r = self.client.get('/im/send/activation/%d' % user.pk, follow=True)
625 9d20fe23 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@grnet.gr')), 3)
626 d2633501 Kostas Papadimitriou
627 d2633501 Kostas Papadimitriou
        # switch back moderation setting
628 d2633501 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
629 d2633501 Kostas Papadimitriou
        r = self.client.get(user.get_activation_url(), follow=True)
630 9d20fe23 Kostas Papadimitriou
        self.assertRedirects(r, "/im/landing")
631 9d20fe23 Kostas Papadimitriou
        r = self.client.get('/im/profile', follow=True)
632 9d20fe23 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
633 9d20fe23 Kostas Papadimitriou
        self.assertTrue('_pithos2_a' in self.client.cookies)
634 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "KPAP@grnet.gr")
635 9d20fe23 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@grnet.gr')), 4)
636 d2633501 Kostas Papadimitriou
637 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
638 d2633501 Kostas Papadimitriou
        # user activated and logged in, token cookie set
639 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
640 d2633501 Kostas Papadimitriou
        self.assertTrue('_pithos2_a' in self.client.cookies)
641 d2633501 Kostas Papadimitriou
        cookies = self.client.cookies
642 9d20fe23 Kostas Papadimitriou
        self.assertTrue(quote(user.auth_token) in
643 9d20fe23 Kostas Papadimitriou
                        cookies.get('_pithos2_a').value)
644 d2633501 Kostas Papadimitriou
        r = self.client.get('/im/logout', follow=True)
645 d2633501 Kostas Papadimitriou
        r = self.client.get('/im/')
646 d2633501 Kostas Papadimitriou
        # user logged out, token cookie removed
647 d2633501 Kostas Papadimitriou
        self.assertFalse(r.context['request'].user.is_authenticated())
648 d2633501 Kostas Papadimitriou
        self.assertFalse(self.client.cookies.get('_pithos2_a').value)
649 9d20fe23 Kostas Papadimitriou
650 9d20fe23 Kostas Papadimitriou
        #https://docs.djangoproject.com/en/dev/topics/testing/#persistent-state
651 d2633501 Kostas Papadimitriou
        del self.client.cookies['_pithos2_a']
652 d2633501 Kostas Papadimitriou
653 d2633501 Kostas Papadimitriou
        # user can login
654 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
655 d2633501 Kostas Papadimitriou
                                           'password': 'password'},
656 9d20fe23 Kostas Papadimitriou
                             follow=True)
657 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
658 d2633501 Kostas Papadimitriou
        self.assertTrue('_pithos2_a' in self.client.cookies)
659 d2633501 Kostas Papadimitriou
        cookies = self.client.cookies
660 9d20fe23 Kostas Papadimitriou
        self.assertTrue(quote(user.auth_token) in
661 9d20fe23 Kostas Papadimitriou
                        cookies.get('_pithos2_a').value)
662 d2633501 Kostas Papadimitriou
        self.client.get('/im/logout', follow=True)
663 d2633501 Kostas Papadimitriou
664 d2633501 Kostas Papadimitriou
        # user forgot password
665 d2633501 Kostas Papadimitriou
        old_pass = user.password
666 d2633501 Kostas Papadimitriou
        r = self.client.get('/im/local/password_reset')
667 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
668 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local/password_reset', {'email':
669 d2633501 Kostas Papadimitriou
                                                          'kpap@grnet.gr'})
670 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 302)
671 d2633501 Kostas Papadimitriou
        # email sent
672 9d20fe23 Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('KPAP@grnet.gr')), 5)
673 d2633501 Kostas Papadimitriou
674 d2633501 Kostas Papadimitriou
        # user visits change password link
675 d2633501 Kostas Papadimitriou
        r = self.client.get(user.get_password_reset_url())
676 d2633501 Kostas Papadimitriou
        r = self.client.post(user.get_password_reset_url(),
677 9d20fe23 Kostas Papadimitriou
                             {'new_password1': 'newpass',
678 9d20fe23 Kostas Papadimitriou
                              'new_password2': 'newpass'})
679 d2633501 Kostas Papadimitriou
680 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
681 d2633501 Kostas Papadimitriou
        self.assertNotEqual(old_pass, user.password)
682 d2633501 Kostas Papadimitriou
683 d2633501 Kostas Papadimitriou
        # old pass is not usable
684 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
685 d2633501 Kostas Papadimitriou
                                           'password': 'password'})
686 31fdafa8 Kostas Papadimitriou
        self.assertContains(r, 'Please enter a correct username and password')
687 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local', {'username': 'kpap@grnet.gr',
688 d2633501 Kostas Papadimitriou
                                           'password': 'newpass'},
689 478ece6c Kostas Papadimitriou
                             follow=True)
690 d2633501 Kostas Papadimitriou
        self.assertTrue(r.context['request'].user.is_authenticated())
691 d2633501 Kostas Papadimitriou
        self.client.logout()
692 d2633501 Kostas Papadimitriou
693 d2633501 Kostas Papadimitriou
        # tests of special local backends
694 d2633501 Kostas Papadimitriou
        user = AstakosUser.objects.get(pk=user.pk)
695 d2633501 Kostas Papadimitriou
        user.auth_providers.filter(module='local').update(auth_backend='ldap')
696 d2633501 Kostas Papadimitriou
        user.save()
697 d2633501 Kostas Papadimitriou
698 d2633501 Kostas Papadimitriou
        # non astakos local backends do not support password reset
699 d2633501 Kostas Papadimitriou
        r = self.client.get('/im/local/password_reset')
700 d2633501 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
701 d2633501 Kostas Papadimitriou
        r = self.client.post('/im/local/password_reset', {'email':
702 d2633501 Kostas Papadimitriou
                                                          'kpap@grnet.gr'})
703 d2633501 Kostas Papadimitriou
        # she can't because account is not active yet
704 9d20fe23 Kostas Papadimitriou
        self.assertContains(r, "Changing password is not")
705 9d20fe23 Kostas Papadimitriou
706 9d20fe23 Kostas Papadimitriou
707 34a76cdb Kostas Papadimitriou
class UserActionsTests(TestCase):
708 34a76cdb Kostas Papadimitriou
709 34a76cdb Kostas Papadimitriou
    def test_email_change(self):
710 34a76cdb Kostas Papadimitriou
        # to test existing email validation
711 478ece6c Kostas Papadimitriou
        get_local_user('existing@grnet.gr')
712 34a76cdb Kostas Papadimitriou
713 34a76cdb Kostas Papadimitriou
        # local user
714 34a76cdb Kostas Papadimitriou
        user = get_local_user('kpap@grnet.gr')
715 34a76cdb Kostas Papadimitriou
716 34a76cdb Kostas Papadimitriou
        # login as kpap
717 34a76cdb Kostas Papadimitriou
        self.client.login(username='kpap@grnet.gr', password='password')
718 34a76cdb Kostas Papadimitriou
        r = self.client.get('/im/profile', follow=True)
719 34a76cdb Kostas Papadimitriou
        user = r.context['request'].user
720 34a76cdb Kostas Papadimitriou
        self.assertTrue(user.is_authenticated())
721 34a76cdb Kostas Papadimitriou
722 34a76cdb Kostas Papadimitriou
        # change email is enabled
723 34a76cdb Kostas Papadimitriou
        r = self.client.get('/im/email_change')
724 34a76cdb Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
725 34a76cdb Kostas Papadimitriou
        self.assertFalse(user.email_change_is_pending())
726 34a76cdb Kostas Papadimitriou
727 34a76cdb Kostas Papadimitriou
        # request email change to an existing email fails
728 34a76cdb Kostas Papadimitriou
        data = {'new_email_address': 'existing@grnet.gr'}
729 34a76cdb Kostas Papadimitriou
        r = self.client.post('/im/email_change', data)
730 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_USED)
731 34a76cdb Kostas Papadimitriou
732 34a76cdb Kostas Papadimitriou
        # proper email change
733 34a76cdb Kostas Papadimitriou
        data = {'new_email_address': 'kpap@gmail.com'}
734 34a76cdb Kostas Papadimitriou
        r = self.client.post('/im/email_change', data, follow=True)
735 34a76cdb Kostas Papadimitriou
        self.assertRedirects(r, '/im/profile')
736 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
737 34a76cdb Kostas Papadimitriou
        change1 = EmailChange.objects.get()
738 34a76cdb Kostas Papadimitriou
739 34a76cdb Kostas Papadimitriou
        # user sees a warning
740 34a76cdb Kostas Papadimitriou
        r = self.client.get('/im/email_change')
741 34a76cdb Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
742 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.PENDING_EMAIL_CHANGE_REQUEST)
743 34a76cdb Kostas Papadimitriou
        self.assertTrue(user.email_change_is_pending())
744 34a76cdb Kostas Papadimitriou
745 34a76cdb Kostas Papadimitriou
        # link was sent
746 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 0)
747 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@gmail.com')), 1)
748 34a76cdb Kostas Papadimitriou
749 34a76cdb Kostas Papadimitriou
        # proper email change
750 34a76cdb Kostas Papadimitriou
        data = {'new_email_address': 'kpap@yahoo.com'}
751 34a76cdb Kostas Papadimitriou
        r = self.client.post('/im/email_change', data, follow=True)
752 34a76cdb Kostas Papadimitriou
        self.assertRedirects(r, '/im/profile')
753 34a76cdb Kostas Papadimitriou
        self.assertContains(r, messages.EMAIL_CHANGE_REGISTERED)
754 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@grnet.gr')), 0)
755 34a76cdb Kostas Papadimitriou
        self.assertEqual(len(get_mailbox('kpap@yahoo.com')), 1)
756 34a76cdb Kostas Papadimitriou
        change2 = EmailChange.objects.get()
757 34a76cdb Kostas Papadimitriou
758 34a76cdb Kostas Papadimitriou
        r = self.client.get(change1.get_url())
759 34a76cdb Kostas Papadimitriou
        self.assertEquals(r.status_code, 302)
760 34a76cdb Kostas Papadimitriou
        self.client.logout()
761 34a76cdb Kostas Papadimitriou
762 34a76cdb Kostas Papadimitriou
        r = self.client.post('/im/local?next=' + change2.get_url(),
763 34a76cdb Kostas Papadimitriou
                             {'username': 'kpap@grnet.gr',
764 34a76cdb Kostas Papadimitriou
                              'password': 'password',
765 34a76cdb Kostas Papadimitriou
                              'next': change2.get_url()},
766 34a76cdb Kostas Papadimitriou
                             follow=True)
767 34a76cdb Kostas Papadimitriou
        self.assertRedirects(r, '/im/profile')
768 34a76cdb Kostas Papadimitriou
        user = r.context['request'].user
769 34a76cdb Kostas Papadimitriou
        self.assertEquals(user.email, 'kpap@yahoo.com')
770 34a76cdb Kostas Papadimitriou
        self.assertEquals(user.username, 'kpap@yahoo.com')
771 34a76cdb Kostas Papadimitriou
772 34a76cdb Kostas Papadimitriou
        self.client.logout()
773 34a76cdb Kostas Papadimitriou
        r = self.client.post('/im/local?next=' + change2.get_url(),
774 34a76cdb Kostas Papadimitriou
                             {'username': 'kpap@grnet.gr',
775 34a76cdb Kostas Papadimitriou
                              'password': 'password',
776 34a76cdb Kostas Papadimitriou
                              'next': change2.get_url()},
777 34a76cdb Kostas Papadimitriou
                             follow=True)
778 34a76cdb Kostas Papadimitriou
        self.assertContains(r, "Please enter a correct username and password")
779 34a76cdb Kostas Papadimitriou
        self.assertEqual(user.emailchanges.count(), 0)
780 34a76cdb Kostas Papadimitriou
781 9d20fe23 Kostas Papadimitriou
782 478ece6c Kostas Papadimitriou
class TestAuthProviderViews(TestCase):
783 478ece6c Kostas Papadimitriou
784 478ece6c Kostas Papadimitriou
    @shibboleth_settings(CREATION_GROUPS_POLICY=['academic-login'])
785 478ece6c Kostas Papadimitriou
    @shibboleth_settings(AUTOMODERATE_POLICY=True)
786 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['shibboleth', 'local'])
787 478ece6c Kostas Papadimitriou
    @im_settings(MODERATION_ENABLED=True)
788 0a7a4104 Kostas Papadimitriou
    @im_settings(FORCE_PROFILE_UPDATE=False)
789 478ece6c Kostas Papadimitriou
    def test_user(self):
790 478ece6c Kostas Papadimitriou
        Profile = AuthProviderPolicyProfile
791 478ece6c Kostas Papadimitriou
        Pending = PendingThirdPartyUser
792 478ece6c Kostas Papadimitriou
        User = AstakosUser
793 478ece6c Kostas Papadimitriou
794 0a7a4104 Kostas Papadimitriou
        User.objects.create(email="newuser@grnet.gr")
795 0a7a4104 Kostas Papadimitriou
        get_local_user("olduser@grnet.gr")
796 478ece6c Kostas Papadimitriou
        cl_olduser = ShibbolethClient()
797 0a7a4104 Kostas Papadimitriou
        get_local_user("olduser2@grnet.gr")
798 0a7a4104 Kostas Papadimitriou
        ShibbolethClient()
799 478ece6c Kostas Papadimitriou
        cl_newuser = ShibbolethClient()
800 478ece6c Kostas Papadimitriou
        cl_newuser2 = Client()
801 478ece6c Kostas Papadimitriou
802 478ece6c Kostas Papadimitriou
        academic_group, created = Group.objects.get_or_create(
803 478ece6c Kostas Papadimitriou
            name='academic-login')
804 478ece6c Kostas Papadimitriou
        academic_users = academic_group.user_set
805 478ece6c Kostas Papadimitriou
        assert created
806 478ece6c Kostas Papadimitriou
        policy_only_academic = Profile.objects.add_policy('academic_strict',
807 478ece6c Kostas Papadimitriou
                                                          'shibboleth',
808 478ece6c Kostas Papadimitriou
                                                          academic_group,
809 478ece6c Kostas Papadimitriou
                                                          exclusive=True,
810 478ece6c Kostas Papadimitriou
                                                          login=False,
811 478ece6c Kostas Papadimitriou
                                                          add=False)
812 478ece6c Kostas Papadimitriou
813 478ece6c Kostas Papadimitriou
814 478ece6c Kostas Papadimitriou
        # new academic user
815 478ece6c Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@grnet.gr'))
816 478ece6c Kostas Papadimitriou
        cl_newuser.set_tokens(eppn="newusereppn")
817 478ece6c Kostas Papadimitriou
        r = cl_newuser.get('/im/login/shibboleth?', follow=True)
818 478ece6c Kostas Papadimitriou
        pending = Pending.objects.get()
819 478ece6c Kostas Papadimitriou
        identifier = pending.third_party_identifier
820 478ece6c Kostas Papadimitriou
        signup_data = {'third_party_identifier': identifier,
821 478ece6c Kostas Papadimitriou
                       'first_name': 'Academic',
822 478ece6c Kostas Papadimitriou
                       'third_party_token': pending.token,
823 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
824 478ece6c Kostas Papadimitriou
                       'provider': 'shibboleth'}
825 478ece6c Kostas Papadimitriou
        r = cl_newuser.post('/im/signup', signup_data)
826 478ece6c Kostas Papadimitriou
        self.assertContains(r, "This field is required", )
827 478ece6c Kostas Papadimitriou
        signup_data['email'] = 'olduser@grnet.gr'
828 478ece6c Kostas Papadimitriou
        r = cl_newuser.post('/im/signup', signup_data)
829 478ece6c Kostas Papadimitriou
        self.assertContains(r, "already an account with this email", )
830 478ece6c Kostas Papadimitriou
        signup_data['email'] = 'newuser@grnet.gr'
831 478ece6c Kostas Papadimitriou
        r = cl_newuser.post('/im/signup', signup_data, follow=True)
832 478ece6c Kostas Papadimitriou
        r = cl_newuser.post('/im/signup', signup_data, follow=True)
833 478ece6c Kostas Papadimitriou
        self.assertEqual(r.status_code, 404)
834 478ece6c Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@grnet.gr")
835 478ece6c Kostas Papadimitriou
        activation_link = newuser.get_activation_url()
836 478ece6c Kostas Papadimitriou
        self.assertTrue(academic_users.get(email='newuser@grnet.gr'))
837 478ece6c Kostas Papadimitriou
838 478ece6c Kostas Papadimitriou
        # new non-academic user
839 478ece6c Kostas Papadimitriou
        signup_data = {'first_name': 'Non Academic',
840 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
841 478ece6c Kostas Papadimitriou
                       'provider': 'local',
842 478ece6c Kostas Papadimitriou
                       'password1': 'password',
843 478ece6c Kostas Papadimitriou
                       'password2': 'password'}
844 478ece6c Kostas Papadimitriou
        signup_data['email'] = 'olduser@grnet.gr'
845 478ece6c Kostas Papadimitriou
        r = cl_newuser2.post('/im/signup', signup_data)
846 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'There is already an account with this '
847 478ece6c Kostas Papadimitriou
                               'email address')
848 478ece6c Kostas Papadimitriou
        signup_data['email'] = 'newuser@grnet.gr'
849 478ece6c Kostas Papadimitriou
        r = cl_newuser2.post('/im/signup/', signup_data)
850 478ece6c Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@grnet.gr'))
851 478ece6c Kostas Papadimitriou
        r = self.client.get(activation_link, follow=True)
852 478ece6c Kostas Papadimitriou
        self.assertEqual(r.status_code, 400)
853 478ece6c Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@grnet.gr")
854 478ece6c Kostas Papadimitriou
        self.assertFalse(newuser.activation_sent)
855 478ece6c Kostas Papadimitriou
        r = self.client.get(newuser.get_activation_url(), follow=True)
856 478ece6c Kostas Papadimitriou
        self.assertContains(r, "pending moderation")
857 478ece6c Kostas Papadimitriou
858 478ece6c Kostas Papadimitriou
        self.assertFalse(academic_users.filter(email='newuser@grnet.gr'))
859 478ece6c Kostas Papadimitriou
        r = cl_newuser.get('/im/login/shibboleth?', follow=True)
860 478ece6c Kostas Papadimitriou
        pending = Pending.objects.get()
861 478ece6c Kostas Papadimitriou
        identifier = pending.third_party_identifier
862 478ece6c Kostas Papadimitriou
        signup_data = {'third_party_identifier': identifier,
863 478ece6c Kostas Papadimitriou
                       'first_name': 'Academic',
864 478ece6c Kostas Papadimitriou
                       'third_party_token': pending.token,
865 478ece6c Kostas Papadimitriou
                       'last_name': 'New User',
866 478ece6c Kostas Papadimitriou
                       'provider': 'shibboleth'}
867 478ece6c Kostas Papadimitriou
        signup_data['email'] = 'newuser@grnet.gr'
868 478ece6c Kostas Papadimitriou
        r = cl_newuser.post('/im/signup', signup_data)
869 478ece6c Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@grnet.gr")
870 478ece6c Kostas Papadimitriou
        self.assertTrue(newuser.activation_sent)
871 478ece6c Kostas Papadimitriou
        activation_link = newuser.get_activation_url()
872 478ece6c Kostas Papadimitriou
        self.assertTrue(academic_users.get(email='newuser@grnet.gr'))
873 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(newuser.get_activation_url(), follow=True)
874 478ece6c Kostas Papadimitriou
        self.assertRedirects(r, '/im/landing')
875 478ece6c Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@grnet.gr")
876 478ece6c Kostas Papadimitriou
        self.assertEqual(newuser.is_active, True)
877 478ece6c Kostas Papadimitriou
        self.assertEqual(newuser.email_verified, True)
878 478ece6c Kostas Papadimitriou
        cl_newuser.logout()
879 478ece6c Kostas Papadimitriou
880 478ece6c Kostas Papadimitriou
        # cannot reactivate if suspended
881 478ece6c Kostas Papadimitriou
        newuser.is_active = False
882 478ece6c Kostas Papadimitriou
        newuser.save()
883 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(newuser.get_activation_url())
884 478ece6c Kostas Papadimitriou
        newuser = User.objects.get(email="newuser@grnet.gr")
885 478ece6c Kostas Papadimitriou
        self.assertFalse(newuser.is_active)
886 478ece6c Kostas Papadimitriou
887 478ece6c Kostas Papadimitriou
        # release suspension
888 478ece6c Kostas Papadimitriou
        newuser.is_active = True
889 478ece6c Kostas Papadimitriou
        newuser.save()
890 478ece6c Kostas Papadimitriou
891 478ece6c Kostas Papadimitriou
        cl_newuser.get('/im/login/shibboleth?', follow=True)
892 478ece6c Kostas Papadimitriou
        local = auth.get_provider('local', newuser)
893 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_add_policy, False)
894 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_login_policy, False)
895 478ece6c Kostas Papadimitriou
        r = cl_newuser.get(local.get_add_url, follow=True)
896 478ece6c Kostas Papadimitriou
        self.assertRedirects(r, '/im/profile')
897 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'disabled for your')
898 478ece6c Kostas Papadimitriou
899 478ece6c Kostas Papadimitriou
        cl_olduser.login(username='olduser@grnet.gr', password="password")
900 478ece6c Kostas Papadimitriou
        r = cl_olduser.get('/im/profile', follow=True)
901 478ece6c Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
902 478ece6c Kostas Papadimitriou
        r = cl_olduser.get('/im/login/shibboleth?', follow=True)
903 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'Your request is missing a unique token')
904 478ece6c Kostas Papadimitriou
        cl_olduser.set_tokens(eppn="newusereppn")
905 478ece6c Kostas Papadimitriou
        r = cl_olduser.get('/im/login/shibboleth?', follow=True)
906 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'is already assigned to another user')
907 478ece6c Kostas Papadimitriou
        cl_olduser.set_tokens(eppn="oldusereppn")
908 478ece6c Kostas Papadimitriou
        r = cl_olduser.get('/im/login/shibboleth?', follow=True)
909 478ece6c Kostas Papadimitriou
        self.assertContains(r, 'Academic login enabled for this account')
910 478ece6c Kostas Papadimitriou
911 478ece6c Kostas Papadimitriou
        user = User.objects.get(email="olduser@grnet.gr")
912 478ece6c Kostas Papadimitriou
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
913 478ece6c Kostas Papadimitriou
        local_provider = user.get_auth_provider('local')
914 478ece6c Kostas Papadimitriou
        self.assertEqual(shib_provider.get_remove_policy, True)
915 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_remove_policy, True)
916 478ece6c Kostas Papadimitriou
917 478ece6c Kostas Papadimitriou
918 478ece6c Kostas Papadimitriou
        policy_only_academic = Profile.objects.add_policy('academic_strict2',
919 478ece6c Kostas Papadimitriou
                                                          'shibboleth',
920 478ece6c Kostas Papadimitriou
                                                          academic_group,
921 478ece6c Kostas Papadimitriou
                                                          remove=False)
922 478ece6c Kostas Papadimitriou
        user.groups.add(academic_group)
923 478ece6c Kostas Papadimitriou
        shib_provider = user.get_auth_provider('shibboleth', 'oldusereppn')
924 478ece6c Kostas Papadimitriou
        local_provider = user.get_auth_provider('local')
925 478ece6c Kostas Papadimitriou
        self.assertEqual(shib_provider.get_remove_policy, False)
926 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_remove_policy, True)
927 478ece6c Kostas Papadimitriou
        self.assertEqual(local_provider.get_login_policy, False)
928 478ece6c Kostas Papadimitriou
929 478ece6c Kostas Papadimitriou
        cl_olduser.logout()
930 478ece6c Kostas Papadimitriou
        login_data = {'username': 'olduser@grnet.gr', 'password': 'password'}
931 478ece6c Kostas Papadimitriou
        r = cl_olduser.post('/im/local', login_data, follow=True)
932 478ece6c Kostas Papadimitriou
        self.assertContains(r, "href='/im/login/shibboleth'>Academic login")
933 9d20fe23 Kostas Papadimitriou
934 9d20fe23 Kostas Papadimitriou
935 478ece6c Kostas Papadimitriou
class TestAuthProvidersAPI(TestCase):
936 478ece6c Kostas Papadimitriou
    """
937 478ece6c Kostas Papadimitriou
    Test auth_providers module API
938 478ece6c Kostas Papadimitriou
    """
939 478ece6c Kostas Papadimitriou
940 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
941 9d20fe23 Kostas Papadimitriou
    def test_create(self):
942 9d20fe23 Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@grnet.gr")
943 9d20fe23 Kostas Papadimitriou
        user2 = AstakosUser.objects.create(email="kpap2@grnet.gr")
944 9d20fe23 Kostas Papadimitriou
945 9d20fe23 Kostas Papadimitriou
        module = 'shibboleth'
946 9d20fe23 Kostas Papadimitriou
        identifier = 'SHIB_UUID'
947 9d20fe23 Kostas Papadimitriou
        provider_params = {
948 9d20fe23 Kostas Papadimitriou
            'affiliation': 'UNIVERSITY',
949 9d20fe23 Kostas Papadimitriou
            'info': {'age': 27}
950 9d20fe23 Kostas Papadimitriou
        }
951 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user2, identifier,
952 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
953 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
954 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user, identifier,
955 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
956 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
957 9d20fe23 Kostas Papadimitriou
        user.email_verified = True
958 9d20fe23 Kostas Papadimitriou
        user.save()
959 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
960 9d20fe23 Kostas Papadimitriou
        provider = user.get_auth_provider(module, identifier)
961 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user.get_auth_provider(
962 9d20fe23 Kostas Papadimitriou
            module, identifier)._instance.info.get('age'), 27)
963 9d20fe23 Kostas Papadimitriou
964 9d20fe23 Kostas Papadimitriou
        module = 'local'
965 9d20fe23 Kostas Papadimitriou
        identifier = None
966 9d20fe23 Kostas Papadimitriou
        provider_params = {'auth_backend': 'ldap', 'info':
967 9d20fe23 Kostas Papadimitriou
                          {'office': 'A1'}}
968 9d20fe23 Kostas Papadimitriou
        provider = auth.get_provider(module, user, identifier,
969 9d20fe23 Kostas Papadimitriou
                                     **provider_params)
970 9d20fe23 Kostas Papadimitriou
        provider.add_to_user()
971 9d20fe23 Kostas Papadimitriou
        self.assertFalse(provider.get_add_policy)
972 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
973 9d20fe23 Kostas Papadimitriou
974 9d20fe23 Kostas Papadimitriou
        shib = user.get_auth_provider('shibboleth',
975 9d20fe23 Kostas Papadimitriou
                                      'SHIB_UUID')
976 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shib.get_remove_policy)
977 9d20fe23 Kostas Papadimitriou
978 9d20fe23 Kostas Papadimitriou
        local = user.get_auth_provider('local')
979 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_remove_policy)
980 9d20fe23 Kostas Papadimitriou
981 9d20fe23 Kostas Papadimitriou
        local.remove_from_user()
982 9d20fe23 Kostas Papadimitriou
        self.assertFalse(shib.get_remove_policy)
983 9d20fe23 Kostas Papadimitriou
        self.assertRaises(Exception, shib.remove_from_user)
984 9d20fe23 Kostas Papadimitriou
985 478ece6c Kostas Papadimitriou
        provider = user.get_auth_providers()[0]
986 478ece6c Kostas Papadimitriou
        self.assertRaises(Exception, provider.add_to_user)
987 478ece6c Kostas Papadimitriou
988 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
989 478ece6c Kostas Papadimitriou
    @shibboleth_settings(ADD_GROUPS_POLICY=['group1', 'group2'])
990 478ece6c Kostas Papadimitriou
    @shibboleth_settings(CREATION_GROUPS_POLICY=['group-create', 'group1',
991 478ece6c Kostas Papadimitriou
                                                 'group2'])
992 478ece6c Kostas Papadimitriou
    @localauth_settings(ADD_GROUPS_POLICY=['localgroup'])
993 478ece6c Kostas Papadimitriou
    @localauth_settings(CREATION_GROUPS_POLICY=['localgroup-create',
994 478ece6c Kostas Papadimitriou
                                                'group-create'])
995 478ece6c Kostas Papadimitriou
    def test_add_groups(self):
996 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@grnet.gr")
997 478ece6c Kostas Papadimitriou
        provider = auth.get_provider('shibboleth', user, 'test123')
998 478ece6c Kostas Papadimitriou
        provider.add_to_user()
999 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
1000 478ece6c Kostas Papadimitriou
        self.assertItemsEqual(user.groups.values_list('name', flat=True),
1001 478ece6c Kostas Papadimitriou
                              [u'group1', u'group2', u'group-create'])
1002 478ece6c Kostas Papadimitriou
1003 478ece6c Kostas Papadimitriou
        local = auth.get_provider('local', user)
1004 478ece6c Kostas Papadimitriou
        local.add_to_user()
1005 478ece6c Kostas Papadimitriou
        provider = user.get_auth_provider('shibboleth')
1006 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_add_groups_policy, ['group1', 'group2'])
1007 478ece6c Kostas Papadimitriou
        provider.remove_from_user()
1008 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
1009 478ece6c Kostas Papadimitriou
        self.assertEqual(len(user.get_auth_providers()), 1)
1010 478ece6c Kostas Papadimitriou
        self.assertItemsEqual(user.groups.values_list('name', flat=True),
1011 478ece6c Kostas Papadimitriou
                              [u'group-create', u'localgroup'])
1012 478ece6c Kostas Papadimitriou
1013 478ece6c Kostas Papadimitriou
        local = user.get_auth_provider('local')
1014 478ece6c Kostas Papadimitriou
        self.assertRaises(Exception, local.remove_from_user)
1015 478ece6c Kostas Papadimitriou
        provider = auth.get_provider('shibboleth', user, 'test123')
1016 478ece6c Kostas Papadimitriou
        provider.add_to_user()
1017 478ece6c Kostas Papadimitriou
        user = AstakosUser.objects.get()
1018 478ece6c Kostas Papadimitriou
        self.assertItemsEqual(user.groups.values_list('name', flat=True),
1019 478ece6c Kostas Papadimitriou
                              [u'group-create', u'group1', u'group2',
1020 478ece6c Kostas Papadimitriou
                               u'localgroup'])
1021 478ece6c Kostas Papadimitriou
1022 478ece6c Kostas Papadimitriou
1023 478ece6c Kostas Papadimitriou
1024 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1025 9d20fe23 Kostas Papadimitriou
    def test_policies(self):
1026 9d20fe23 Kostas Papadimitriou
        group_old, created = Group.objects.get_or_create(name='olduser')
1027 9d20fe23 Kostas Papadimitriou
1028 9d20fe23 Kostas Papadimitriou
        astakos_settings.MODERATION_ENABLED = True
1029 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATION_GROUPS_POLICY = \
1030 9d20fe23 Kostas Papadimitriou
            ['academic-user']
1031 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_GOOGLE_ADD_GROUPS_POLICY = \
1032 9d20fe23 Kostas Papadimitriou
            ['google-user']
1033 9d20fe23 Kostas Papadimitriou
1034 9d20fe23 Kostas Papadimitriou
        user = AstakosUser.objects.create(email="kpap@grnet.gr")
1035 9d20fe23 Kostas Papadimitriou
        user.groups.add(group_old)
1036 9d20fe23 Kostas Papadimitriou
        user.add_auth_provider('local')
1037 9d20fe23 Kostas Papadimitriou
1038 9d20fe23 Kostas Papadimitriou
        user2 = AstakosUser.objects.create(email="kpap2@grnet.gr")
1039 9d20fe23 Kostas Papadimitriou
        user2.add_auth_provider('shibboleth', identifier='shibid')
1040 9d20fe23 Kostas Papadimitriou
1041 9d20fe23 Kostas Papadimitriou
        user3 = AstakosUser.objects.create(email="kpap3@grnet.gr")
1042 9d20fe23 Kostas Papadimitriou
        user3.groups.add(group_old)
1043 9d20fe23 Kostas Papadimitriou
        user3.add_auth_provider('local')
1044 9d20fe23 Kostas Papadimitriou
        user3.add_auth_provider('shibboleth', identifier='1234')
1045 9d20fe23 Kostas Papadimitriou
1046 9d20fe23 Kostas Papadimitriou
        self.assertTrue(user2.groups.get(name='academic-user'))
1047 9d20fe23 Kostas Papadimitriou
        self.assertFalse(user2.groups.filter(name='olduser').count())
1048 9d20fe23 Kostas Papadimitriou
1049 9d20fe23 Kostas Papadimitriou
        local = auth_providers.get_provider('local')
1050 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
1051 9d20fe23 Kostas Papadimitriou
1052 9d20fe23 Kostas Papadimitriou
        academic_group = Group.objects.get(name='academic-user')
1053 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1054 9d20fe23 Kostas Papadimitriou
                                                     academic_group,
1055 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
1056 9d20fe23 Kostas Papadimitriou
                                                     add=False,
1057 9d20fe23 Kostas Papadimitriou
                                                     login=False)
1058 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1059 9d20fe23 Kostas Papadimitriou
                                                     academic_group,
1060 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
1061 9d20fe23 Kostas Papadimitriou
                                                     login=False,
1062 9d20fe23 Kostas Papadimitriou
                                                     add=False)
1063 9d20fe23 Kostas Papadimitriou
        # no duplicate entry gets created
1064 9d20fe23 Kostas Papadimitriou
        self.assertEqual(academic_group.authpolicy_profiles.count(), 1)
1065 9d20fe23 Kostas Papadimitriou
1066 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user2.authpolicy_profiles.count(), 0)
1067 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1068 9d20fe23 Kostas Papadimitriou
                                                     user2,
1069 9d20fe23 Kostas Papadimitriou
                                                     remove=False)
1070 9d20fe23 Kostas Papadimitriou
        self.assertEqual(user2.authpolicy_profiles.count(), 1)
1071 9d20fe23 Kostas Papadimitriou
1072 9d20fe23 Kostas Papadimitriou
        local = auth_providers.get_provider('local', user2)
1073 9d20fe23 Kostas Papadimitriou
        google = auth_providers.get_provider('google', user2)
1074 9d20fe23 Kostas Papadimitriou
        shibboleth = auth_providers.get_provider('shibboleth', user2)
1075 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shibboleth.get_login_policy)
1076 9d20fe23 Kostas Papadimitriou
        self.assertFalse(shibboleth.get_remove_policy)
1077 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_add_policy)
1078 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_add_policy)
1079 9d20fe23 Kostas Papadimitriou
        self.assertFalse(google.get_add_policy)
1080 9d20fe23 Kostas Papadimitriou
1081 9d20fe23 Kostas Papadimitriou
        user2.groups.remove(Group.objects.get(name='academic-user'))
1082 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
1083 9d20fe23 Kostas Papadimitriou
        self.assertTrue(google.get_add_policy)
1084 9d20fe23 Kostas Papadimitriou
        user2.groups.add(Group.objects.get(name='academic-user'))
1085 9d20fe23 Kostas Papadimitriou
1086 9d20fe23 Kostas Papadimitriou
        AuthProviderPolicyProfile.objects.add_policy('academic', 'shibboleth',
1087 9d20fe23 Kostas Papadimitriou
                                                     user2,
1088 9d20fe23 Kostas Papadimitriou
                                                     exclusive=True,
1089 9d20fe23 Kostas Papadimitriou
                                                     add=True)
1090 9d20fe23 Kostas Papadimitriou
        self.assertTrue(local.get_add_policy)
1091 9d20fe23 Kostas Papadimitriou
        self.assertTrue(google.get_add_policy)
1092 9d20fe23 Kostas Papadimitriou
1093 9d20fe23 Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_AUTOMODERATE_POLICY = True
1094 9d20fe23 Kostas Papadimitriou
        self.assertFalse(local.get_automoderate_policy)
1095 9d20fe23 Kostas Papadimitriou
        self.assertFalse(google.get_automoderate_policy)
1096 9d20fe23 Kostas Papadimitriou
        self.assertTrue(shibboleth.get_automoderate_policy)
1097 9d20fe23 Kostas Papadimitriou
1098 9d20fe23 Kostas Papadimitriou
        for s in ['SHIBBOLETH_CREATION_GROUPS_POLICY',
1099 9d20fe23 Kostas Papadimitriou
                  'GOOGLE_ADD_GROUPS_POLICY']:
1100 9d20fe23 Kostas Papadimitriou
            delattr(settings, 'ASTAKOS_AUTH_PROVIDER_%s' % s)
1101 478ece6c Kostas Papadimitriou
1102 478ece6c Kostas Papadimitriou
1103 478ece6c Kostas Papadimitriou
    @shibboleth_settings(CREATE_POLICY=True)
1104 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1105 478ece6c Kostas Papadimitriou
    def test_create_http(self):
1106 478ece6c Kostas Papadimitriou
        # this should be wrapped inside a transaction
1107 478ece6c Kostas Papadimitriou
        user = AstakosUser(email="test@test.com")
1108 478ece6c Kostas Papadimitriou
        user.save()
1109 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user,
1110 478ece6c Kostas Papadimitriou
                                               'test@academia.test')
1111 478ece6c Kostas Papadimitriou
        provider.add_to_user()
1112 478ece6c Kostas Papadimitriou
        user.get_auth_provider('shibboleth', 'test@academia.test')
1113 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('local', user)
1114 478ece6c Kostas Papadimitriou
        provider.add_to_user()
1115 478ece6c Kostas Papadimitriou
        user.get_auth_provider('local')
1116 478ece6c Kostas Papadimitriou
1117 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = False
1118 478ece6c Kostas Papadimitriou
        user = AstakosUser(email="test2@test.com")
1119 478ece6c Kostas Papadimitriou
        user.save()
1120 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user,
1121 478ece6c Kostas Papadimitriou
                                               'test@shibboleth.com',
1122 478ece6c Kostas Papadimitriou
                                               **{'info': {'name':
1123 478ece6c Kostas Papadimitriou
                                                                'User Test'}})
1124 478ece6c Kostas Papadimitriou
        self.assertFalse(provider.get_create_policy)
1125 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_CREATE_POLICY = True
1126 478ece6c Kostas Papadimitriou
        self.assertTrue(provider.get_create_policy)
1127 478ece6c Kostas Papadimitriou
        academic = provider.add_to_user()
1128 478ece6c Kostas Papadimitriou
1129 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1130 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1131 478ece6c Kostas Papadimitriou
    def test_policies(self):
1132 478ece6c Kostas Papadimitriou
        user = get_local_user('kpap@grnet.gr')
1133 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1134 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1135 478ece6c Kostas Papadimitriou
1136 478ece6c Kostas Papadimitriou
        # default limit is 1
1137 478ece6c Kostas Papadimitriou
        local = user.get_auth_provider('local')
1138 478ece6c Kostas Papadimitriou
        self.assertEqual(local.get_add_policy, False)
1139 478ece6c Kostas Papadimitriou
1140 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 3
1141 478ece6c Kostas Papadimitriou
        academic = user.get_auth_provider('shibboleth',
1142 478ece6c Kostas Papadimitriou
                                          identifier='1234')
1143 478ece6c Kostas Papadimitriou
        self.assertEqual(academic.get_add_policy, False)
1144 478ece6c Kostas Papadimitriou
        newacademic = auth_providers.get_provider('shibboleth', user,
1145 478ece6c Kostas Papadimitriou
                                                  identifier='123456')
1146 478ece6c Kostas Papadimitriou
        self.assertEqual(newacademic.get_add_policy, True)
1147 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='123456')
1148 478ece6c Kostas Papadimitriou
        self.assertEqual(academic.get_add_policy, False)
1149 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_LIMIT_POLICY = 1
1150 478ece6c Kostas Papadimitriou
1151 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1152 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1153 478ece6c Kostas Papadimitriou
    def test_messages(self):
1154 478ece6c Kostas Papadimitriou
        user = get_local_user('kpap@grnet.gr')
1155 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1156 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1157 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1158 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('title'), 'Academic')
1159 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = 'New title'
1160 478ece6c Kostas Papadimitriou
        # regenerate messages cache
1161 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1162 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('title'), 'New title')
1163 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_message('login_title'),
1164 478ece6c Kostas Papadimitriou
                         'New title LOGIN')
1165 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_login_title_msg, 'New title LOGIN')
1166 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_module_icon,
1167 478ece6c Kostas Papadimitriou
                         settings.MEDIA_URL + 'im/auth/icons/shibboleth.png')
1168 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_module_medium_icon,
1169 478ece6c Kostas Papadimitriou
                         settings.MEDIA_URL +
1170 478ece6c Kostas Papadimitriou
                         'im/auth/icons-medium/shibboleth.png')
1171 478ece6c Kostas Papadimitriou
1172 478ece6c Kostas Papadimitriou
        settings.ASTAKOS_AUTH_PROVIDER_SHIBBOLETH_TITLE = None
1173 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '12345')
1174 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_method_details_msg,
1175 478ece6c Kostas Papadimitriou
                         'Account: 12345')
1176 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1177 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_method_details_msg,
1178 478ece6c Kostas Papadimitriou
                         'Account: 1234')
1179 478ece6c Kostas Papadimitriou
1180 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth', user, '1234')
1181 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_not_active_msg,
1182 478ece6c Kostas Papadimitriou
                         "'Academic login' is disabled.")
1183 478ece6c Kostas Papadimitriou
1184 478ece6c Kostas Papadimitriou
    @im_settings(IM_MODULES=['local', 'shibboleth'])
1185 478ece6c Kostas Papadimitriou
    @shibboleth_settings(LIMIT_POLICY=2)
1186 478ece6c Kostas Papadimitriou
    def test_templates(self):
1187 478ece6c Kostas Papadimitriou
        user = get_local_user('kpap@grnet.gr')
1188 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='1234')
1189 478ece6c Kostas Papadimitriou
        user.add_auth_provider('shibboleth', identifier='12345')
1190 478ece6c Kostas Papadimitriou
1191 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('shibboleth')
1192 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_template('login'),
1193 478ece6c Kostas Papadimitriou
                         'im/auth/shibboleth_login.html')
1194 478ece6c Kostas Papadimitriou
        provider = auth_providers.get_provider('google')
1195 478ece6c Kostas Papadimitriou
        self.assertEqual(provider.get_template('login'),
1196 478ece6c Kostas Papadimitriou
                         'im/auth/generic_login.html')
1197 478ece6c Kostas Papadimitriou
1198 478ece6c Kostas Papadimitriou
1199 450c7fb0 Kostas Papadimitriou
class TestProjects(TestCase):
1200 450c7fb0 Kostas Papadimitriou
    """
1201 450c7fb0 Kostas Papadimitriou
    Test projects.
1202 450c7fb0 Kostas Papadimitriou
    """
1203 450c7fb0 Kostas Papadimitriou
    def setUp(self):
1204 450c7fb0 Kostas Papadimitriou
        self.service = Service.objects.create(name="service1",
1205 450c7fb0 Kostas Papadimitriou
                                              api_url="http://service.api")
1206 450c7fb0 Kostas Papadimitriou
        self.resource = Resource.objects.create(name="service1.resource",
1207 0a7a4104 Kostas Papadimitriou
                                                uplimit=100,
1208 0a7a4104 Kostas Papadimitriou
                                                service=self.service)
1209 450c7fb0 Kostas Papadimitriou
        self.admin = get_local_user("projects-admin@synnefo.org")
1210 450c7fb0 Kostas Papadimitriou
        self.admin.uuid = 'uuid1'
1211 450c7fb0 Kostas Papadimitriou
        self.admin.save()
1212 450c7fb0 Kostas Papadimitriou
1213 450c7fb0 Kostas Papadimitriou
        self.user = get_local_user("user@synnefo.org")
1214 450c7fb0 Kostas Papadimitriou
        self.member = get_local_user("member@synnefo.org")
1215 450c7fb0 Kostas Papadimitriou
        self.member2 = get_local_user("member2@synnefo.org")
1216 450c7fb0 Kostas Papadimitriou
1217 450c7fb0 Kostas Papadimitriou
        self.admin_client = get_user_client("projects-admin@synnefo.org")
1218 450c7fb0 Kostas Papadimitriou
        self.user_client = get_user_client("user@synnefo.org")
1219 450c7fb0 Kostas Papadimitriou
        self.member_client = get_user_client("member@synnefo.org")
1220 450c7fb0 Kostas Papadimitriou
        self.member2_client = get_user_client("member2@synnefo.org")
1221 450c7fb0 Kostas Papadimitriou
1222 450c7fb0 Kostas Papadimitriou
    @im_settings(PENDING_APPLICATION_LIMIT=0, PROJECT_ADMINS=['uuid1'])
1223 450c7fb0 Kostas Papadimitriou
    def test_application_limit(self):
1224 450c7fb0 Kostas Papadimitriou
        # user cannot create a project
1225 450c7fb0 Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
1226 450c7fb0 Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
1227 450c7fb0 Kostas Papadimitriou
        self.assertContains(r, "You are not allowed to create a new project")
1228 450c7fb0 Kostas Papadimitriou
1229 450c7fb0 Kostas Papadimitriou
        # but admin can
1230 450c7fb0 Kostas Papadimitriou
        r = self.admin_client.get(reverse('project_add'), follow=True)
1231 450c7fb0 Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_add'))
1232 450c7fb0 Kostas Papadimitriou
1233 450c7fb0 Kostas Papadimitriou
    @im_settings(PENDING_APPLICATION_LIMIT=2, PROJECT_ADMINS=['uuid1'])
1234 450c7fb0 Kostas Papadimitriou
    def test_applications(self):
1235 450c7fb0 Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
1236 450c7fb0 Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_add'))
1237 450c7fb0 Kostas Papadimitriou
1238 450c7fb0 Kostas Papadimitriou
        # user fills the project application form
1239 450c7fb0 Kostas Papadimitriou
        post_url = reverse('project_add') + '?verify=1'
1240 450c7fb0 Kostas Papadimitriou
        dfrom = datetime.now()
1241 450c7fb0 Kostas Papadimitriou
        dto = datetime.now() + timedelta(days=30)
1242 450c7fb0 Kostas Papadimitriou
        application_data = {
1243 450c7fb0 Kostas Papadimitriou
            'name': 'project.synnefo.org',
1244 450c7fb0 Kostas Papadimitriou
            'homepage': 'https://www.synnefo.org',
1245 450c7fb0 Kostas Papadimitriou
            'start_date': dfrom.strftime("%Y-%m-%d"),
1246 450c7fb0 Kostas Papadimitriou
            'end_date': dto.strftime("%Y-%m-%d"),
1247 450c7fb0 Kostas Papadimitriou
            'member_join_policy': 2,
1248 450c7fb0 Kostas Papadimitriou
            'member_leave_policy': 1,
1249 450c7fb0 Kostas Papadimitriou
            'service1.resource_uplimit': 100,
1250 450c7fb0 Kostas Papadimitriou
            'is_selected_service1.resource': 1,
1251 450c7fb0 Kostas Papadimitriou
            'user': self.user.pk
1252 450c7fb0 Kostas Papadimitriou
        }
1253 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
1254 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1255 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.context['form'].is_valid(), True)
1256 450c7fb0 Kostas Papadimitriou
1257 450c7fb0 Kostas Papadimitriou
        # confirm request
1258 450c7fb0 Kostas Papadimitriou
        post_url = reverse('project_add') + '?verify=0&edit=0'
1259 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
1260 450c7fb0 Kostas Papadimitriou
        self.assertContains(r, "The project application has been received")
1261 450c7fb0 Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
1262 450c7fb0 Kostas Papadimitriou
        self.assertEqual(ProjectApplication.objects.count(), 1)
1263 450c7fb0 Kostas Papadimitriou
        app1_id = ProjectApplication.objects.filter().order_by('pk')[0].pk
1264 450c7fb0 Kostas Papadimitriou
1265 450c7fb0 Kostas Papadimitriou
        # create another one
1266 450c7fb0 Kostas Papadimitriou
        application_data['name'] = 'project2.synnefo.org'
1267 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(post_url, data=application_data, follow=True)
1268 450c7fb0 Kostas Papadimitriou
        app2_id = ProjectApplication.objects.filter().order_by('pk')[1].pk
1269 450c7fb0 Kostas Papadimitriou
1270 450c7fb0 Kostas Papadimitriou
        # no more applications (LIMIT is 2)
1271 450c7fb0 Kostas Papadimitriou
        r = self.user_client.get(reverse('project_add'), follow=True)
1272 450c7fb0 Kostas Papadimitriou
        self.assertRedirects(r, reverse('project_list'))
1273 450c7fb0 Kostas Papadimitriou
        self.assertContains(r, "You are not allowed to create a new project")
1274 450c7fb0 Kostas Papadimitriou
1275 450c7fb0 Kostas Papadimitriou
        # login
1276 450c7fb0 Kostas Papadimitriou
        self.admin_client.get(reverse("edit_profile"))
1277 450c7fb0 Kostas Papadimitriou
        # admin approves
1278 450c7fb0 Kostas Papadimitriou
        r = self.admin_client.post(reverse('project_app_approve',
1279 450c7fb0 Kostas Papadimitriou
                                           kwargs={'application_id': app1_id}),
1280 450c7fb0 Kostas Papadimitriou
                                   follow=True)
1281 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1282 450c7fb0 Kostas Papadimitriou
1283 450c7fb0 Kostas Papadimitriou
        # project created
1284 450c7fb0 Kostas Papadimitriou
        self.assertEqual(Project.objects.count(), 1)
1285 450c7fb0 Kostas Papadimitriou
1286 450c7fb0 Kostas Papadimitriou
        # login
1287 450c7fb0 Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
1288 450c7fb0 Kostas Papadimitriou
        # cannot join app2 (not approved yet)
1289 450c7fb0 Kostas Papadimitriou
        join_url = reverse("project_join", kwargs={'chain_id': app2_id})
1290 450c7fb0 Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
1291 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 403)
1292 450c7fb0 Kostas Papadimitriou
1293 450c7fb0 Kostas Papadimitriou
        # can join app1
1294 450c7fb0 Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
1295 450c7fb0 Kostas Papadimitriou
        join_url = reverse("project_join", kwargs={'chain_id': app1_id})
1296 450c7fb0 Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
1297 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1298 450c7fb0 Kostas Papadimitriou
1299 450c7fb0 Kostas Papadimitriou
        self.assertEqual(ProjectMembership.objects.count(), 1)
1300 450c7fb0 Kostas Papadimitriou
1301 450c7fb0 Kostas Papadimitriou
        reject_member_url = reverse('project_reject_member',
1302 450c7fb0 Kostas Papadimitriou
                                    kwargs={'chain_id': app1_id, 'user_id':
1303 450c7fb0 Kostas Papadimitriou
                                            self.member.pk})
1304 450c7fb0 Kostas Papadimitriou
        accept_member_url = reverse('project_accept_member',
1305 450c7fb0 Kostas Papadimitriou
                                    kwargs={'chain_id': app1_id, 'user_id':
1306 450c7fb0 Kostas Papadimitriou
                                            self.member.pk})
1307 450c7fb0 Kostas Papadimitriou
1308 450c7fb0 Kostas Papadimitriou
        # only project owner is allowed to reject
1309 450c7fb0 Kostas Papadimitriou
        r = self.member_client.post(reject_member_url, follow=True)
1310 450c7fb0 Kostas Papadimitriou
        self.assertContains(r, "You do not have the permissions")
1311 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1312 450c7fb0 Kostas Papadimitriou
1313 450c7fb0 Kostas Papadimitriou
        # user (owns project) rejects membership
1314 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(reject_member_url, follow=True)
1315 450c7fb0 Kostas Papadimitriou
        self.assertEqual(ProjectMembership.objects.count(), 0)
1316 450c7fb0 Kostas Papadimitriou
1317 450c7fb0 Kostas Papadimitriou
        # user rejoins
1318 450c7fb0 Kostas Papadimitriou
        self.member_client.get(reverse("edit_profile"))
1319 450c7fb0 Kostas Papadimitriou
        join_url = reverse("project_join", kwargs={'chain_id': app1_id})
1320 450c7fb0 Kostas Papadimitriou
        r = self.member_client.post(join_url, follow=True)
1321 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1322 450c7fb0 Kostas Papadimitriou
        self.assertEqual(ProjectMembership.objects.count(), 1)
1323 450c7fb0 Kostas Papadimitriou
1324 450c7fb0 Kostas Papadimitriou
        # user (owns project) accepts membership
1325 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(accept_member_url, follow=True)
1326 450c7fb0 Kostas Papadimitriou
        self.assertEqual(ProjectMembership.objects.count(), 1)
1327 450c7fb0 Kostas Papadimitriou
        membership = ProjectMembership.objects.get()
1328 450c7fb0 Kostas Papadimitriou
        self.assertEqual(membership.state, ProjectMembership.ACCEPTED)
1329 450c7fb0 Kostas Papadimitriou
1330 450c7fb0 Kostas Papadimitriou
        user_quotas = quotas.get_users_quotas([self.member])
1331 450c7fb0 Kostas Papadimitriou
        resource = 'service1.resource'
1332 450c7fb0 Kostas Papadimitriou
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
1333 450c7fb0 Kostas Papadimitriou
        # 100 from initial uplimit + 100 from project
1334 450c7fb0 Kostas Papadimitriou
        self.assertEqual(newlimit, 200)
1335 450c7fb0 Kostas Papadimitriou
1336 450c7fb0 Kostas Papadimitriou
        remove_member_url = reverse('project_remove_member',
1337 450c7fb0 Kostas Papadimitriou
                                    kwargs={'chain_id': app1_id, 'user_id':
1338 450c7fb0 Kostas Papadimitriou
                                            self.member.pk})
1339 450c7fb0 Kostas Papadimitriou
        r = self.user_client.post(remove_member_url, follow=True)
1340 450c7fb0 Kostas Papadimitriou
        self.assertEqual(r.status_code, 200)
1341 450c7fb0 Kostas Papadimitriou
1342 450c7fb0 Kostas Papadimitriou
        user_quotas = quotas.get_users_quotas([self.member])
1343 450c7fb0 Kostas Papadimitriou
        resource = 'service1.resource'
1344 450c7fb0 Kostas Papadimitriou
        newlimit = user_quotas[self.member.uuid]['system'][resource]['limit']
1345 450c7fb0 Kostas Papadimitriou
        # 200 - 100 from project
1346 450c7fb0 Kostas Papadimitriou
        self.assertEqual(newlimit, 100)