Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / tests / api.py @ ff5edb80

History | View | Annotate | Download (31.9 kB)

1
# Copyright 2011-2014 GRNET S.A. All rights reserved.
2
#
3
# Redistribution and use in source and binary forms, with or
4
# without modification, are permitted provided that the following
5
# conditions are met:
6
#
7
#   1. Redistributions of source code must retain the above
8
#      copyright notice, this list of conditions and the following
9
#      disclaimer.
10
#
11
#   2. Redistributions in binary form must reproduce the above
12
#      copyright notice, this list of conditions and the following
13
#      disclaimer in the documentation and/or other materials
14
#      provided with the distribution.
15
#
16
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27
# POSSIBILITY OF SUCH DAMAGE.
28
#
29
# The views and conclusions contained in the software and
30
# documentation are those of the authors and should not be
31
# interpreted as representing official policies, either expressed
32
# or implied, of GRNET S.A.
33

    
34
from astakos.im.tests.common import *
35
from astakos.im.settings import astakos_services, BASE_HOST
36
from astakos.oa2.backends import DjangoBackend
37

    
38
from synnefo.lib.services import get_service_path
39
from synnefo.lib import join_urls
40

    
41
from django.core.urlresolvers import reverse
42

    
43
from datetime import date
44

    
45
#from xml.dom import minidom
46

    
47
import json
48
import time
49

    
50
ROOT = "/%s/%s/%s/" % (
51
    astakos_settings.BASE_PATH, astakos_settings.ACCOUNTS_PREFIX, 'v1.0')
52
u = lambda url: ROOT + url
53

    
54

    
55
class QuotaAPITest(TestCase):
56
    def test_0(self):
57
        client = Client()
58
        backend = activation_backends.get_backend()
59

    
60
        component1 = Component.objects.create(name="comp1")
61
        register.add_service(component1, "service1", "type1", [])
62
        # custom service resources
63
        resource11 = {"name": "service1.resource11",
64
                      "desc": "resource11 desc",
65
                      "service_type": "type1",
66
                      "service_origin": "service1",
67
                      "ui_visible": True}
68
        r, _ = register.add_resource(resource11)
69
        register.update_base_default(r, 100)
70
        resource12 = {"name": "service1.resource12",
71
                      "desc": "resource11 desc",
72
                      "service_type": "type1",
73
                      "service_origin": "service1",
74
                      "unit": "bytes"}
75
        r, _ = register.add_resource(resource12)
76
        register.update_base_default(r, 1024)
77

    
78
        # create user
79
        user = get_local_user('test@grnet.gr')
80
        backend.accept_user(user)
81
        non_moderated_user = get_local_user('nonmon@example.com',
82
                                            is_active=False)
83
        r_user = get_local_user('rej@example.com',
84
                                is_active=False, email_verified=True)
85
        backend.reject_user(r_user, "reason")
86

    
87
        component2 = Component.objects.create(name="comp2")
88
        register.add_service(component2, "service2", "type2", [])
89
        # create another service
90
        resource21 = {"name": "service2.resource21",
91
                      "desc": "resource11 desc",
92
                      "service_type": "type2",
93
                      "service_origin": "service2",
94
                      "ui_visible": False}
95
        r, _ = register.add_resource(resource21)
96
        register.update_base_default(r, 3)
97

    
98
        resource_names = [r['name'] for r in
99
                          [resource11, resource12, resource21]]
100

    
101
        # get resources
102
        r = client.get(u('resources'))
103
        self.assertEqual(r.status_code, 200)
104
        body = json.loads(r.content)
105
        for name in resource_names:
106
            assertIn(name, body)
107

    
108
        # get quota
109
        r = client.get(u('quotas'))
110
        self.assertEqual(r.status_code, 401)
111

    
112
        headers = {'HTTP_X_AUTH_TOKEN': user.auth_token}
113
        r = client.get(u('quotas/'), **headers)
114
        self.assertEqual(r.status_code, 200)
115
        body = json.loads(r.content)
116
        assertIn(user.uuid, body)
117
        base_quota = body[user.uuid]
118
        for name in resource_names:
119
            assertIn(name, base_quota)
120

    
121
        nmheaders = {'HTTP_X_AUTH_TOKEN': non_moderated_user.auth_token}
122
        r = client.get(u('quotas/'), **nmheaders)
123
        self.assertEqual(r.status_code, 401)
124

    
125
        q = quotas.get_user_quotas(non_moderated_user)
126
        self.assertEqual(q, {})
127

    
128
        q = quotas.get_user_quotas(r_user)
129
        self.assertEqual(q, {})
130

    
131
        r = client.get(u('service_quotas'))
132
        self.assertEqual(r.status_code, 401)
133

    
134
        s1_headers = {'HTTP_X_AUTH_TOKEN': component1.auth_token}
135
        r = client.get(u('service_quotas'), **s1_headers)
136
        self.assertEqual(r.status_code, 200)
137
        body = json.loads(r.content)
138
        assertIn(user.uuid, body)
139

    
140
        r = client.get(u('commissions'), **s1_headers)
141
        self.assertEqual(r.status_code, 200)
142
        body = json.loads(r.content)
143
        self.assertEqual(body, [])
144

    
145
        # issue some commissions
146
        commission_request = {
147
            "force": False,
148
            "auto_accept": False,
149
            "name": "my commission",
150
            "provisions": [
151
                {
152
                    "holder": "user:" + user.uuid,
153
                    "source": "project:" + user.uuid,
154
                    "resource": resource11['name'],
155
                    "quantity": 1
156
                },
157
                {
158
                    "holder": "user:" + user.uuid,
159
                    "source": "project:" + user.uuid,
160
                    "resource": resource12['name'],
161
                    "quantity": 30000
162
                }]}
163

    
164
        post_data = json.dumps(commission_request)
165
        r = client.post(u('commissions'), post_data,
166
                        content_type='application/json', **s1_headers)
167
        self.assertEqual(r.status_code, 413)
168

    
169
        commission_request = {
170
            "force": False,
171
            "auto_accept": False,
172
            "name": "my commission",
173
            "provisions": [
174
                {
175
                    "holder": "user:" + user.uuid,
176
                    "source": "project:" + user.uuid,
177
                    "resource": resource11['name'],
178
                    "quantity": 1
179
                },
180
                {
181
                    "holder": "user:" + user.uuid,
182
                    "source": "project:" + user.uuid,
183
                    "resource": resource12['name'],
184
                    "quantity": 100
185
                }]}
186

    
187
        post_data = json.dumps(commission_request)
188
        r = client.post(u('commissions'), post_data,
189
                        content_type='application/json', **s1_headers)
190
        self.assertEqual(r.status_code, 201)
191
        body = json.loads(r.content)
192
        serial1 = body['serial']
193
        assertGreater(serial1, 0)
194

    
195
        post_data = json.dumps(commission_request)
196
        r = client.post(u('commissions'), post_data,
197
                        content_type='application/json', **s1_headers)
198
        self.assertEqual(r.status_code, 201)
199
        body = json.loads(r.content)
200
        serial2 = body['serial']
201
        assertGreater(serial2, serial1)
202

    
203
        post_data = json.dumps(commission_request)
204
        r = client.post(u('commissions'), post_data,
205
                        content_type='application/json', **s1_headers)
206
        self.assertEqual(r.status_code, 201)
207
        body = json.loads(r.content)
208
        serial3 = body['serial']
209
        assertGreater(serial3, serial2)
210

    
211
        r = client.get(u('commissions'), **s1_headers)
212
        self.assertEqual(r.status_code, 200)
213
        body = json.loads(r.content)
214
        self.assertEqual(len(body), 3)
215

    
216
        r = client.get(u('commissions/' + str(serial1)), **s1_headers)
217
        self.assertEqual(r.status_code, 200)
218
        body = json.loads(r.content)
219
        self.assertEqual(body['serial'], serial1)
220
        assertIn('issue_time', body)
221
        provisions = sorted(body['provisions'], key=lambda p: p['resource'])
222
        self.assertEqual(provisions, commission_request['provisions'])
223
        self.assertEqual(body['name'], commission_request['name'])
224

    
225
        r = client.get(u('service_quotas?user=' + user.uuid), **s1_headers)
226
        self.assertEqual(r.status_code, 200)
227
        body = json.loads(r.content)
228
        user_quota = body[user.uuid]
229
        base_quota = user_quota[user.uuid]
230
        r11 = base_quota[resource11['name']]
231
        self.assertEqual(r11['usage'], 3)
232
        self.assertEqual(r11['pending'], 3)
233

    
234
        r = client.get(u('service_project_quotas'), **s1_headers)
235
        self.assertEqual(r.status_code, 200)
236
        body = json.loads(r.content)
237
        assertIn(user.uuid, body)
238

    
239
        # resolve pending commissions
240
        resolve_data = {
241
            "accept": [serial1, serial3],
242
            "reject": [serial2, serial3, serial3 + 1],
243
        }
244
        post_data = json.dumps(resolve_data)
245

    
246
        r = client.post(u('commissions/action'), post_data,
247
                        content_type='application/json', **s1_headers)
248
        self.assertEqual(r.status_code, 200)
249
        body = json.loads(r.content)
250
        self.assertEqual(body['accepted'], [serial1])
251
        self.assertEqual(body['rejected'], [serial2])
252
        failed = body['failed']
253
        self.assertEqual(len(failed), 2)
254

    
255
        r = client.get(u('commissions/' + str(serial1)), **s1_headers)
256
        self.assertEqual(r.status_code, 404)
257

    
258
        # auto accept
259
        commission_request = {
260
            "auto_accept": True,
261
            "name": "my commission",
262
            "provisions": [
263
                {
264
                    "holder": "user:" + user.uuid,
265
                    "source": "project:" + user.uuid,
266
                    "resource": resource11['name'],
267
                    "quantity": 1
268
                },
269
                {
270
                    "holder": "user:" + user.uuid,
271
                    "source": "project:" + user.uuid,
272
                    "resource": resource12['name'],
273
                    "quantity": 100
274
                }]}
275

    
276
        post_data = json.dumps(commission_request)
277
        r = client.post(u('commissions'), post_data,
278
                        content_type='application/json', **s1_headers)
279
        self.assertEqual(r.status_code, 201)
280
        body = json.loads(r.content)
281
        serial4 = body['serial']
282
        assertGreater(serial4, serial3)
283

    
284
        r = client.get(u('commissions/' + str(serial4)), **s1_headers)
285
        self.assertEqual(r.status_code, 404)
286

    
287
        # malformed
288
        commission_request = {
289
            "auto_accept": True,
290
            "name": "my commission",
291
            "provisions": [
292
                {
293
                    "holder": "user:" + user.uuid,
294
                    "source": "project:" + user.uuid,
295
                    "resource": resource11['name'],
296
                }
297
            ]}
298

    
299
        post_data = json.dumps(commission_request)
300
        r = client.post(u('commissions'), post_data,
301
                        content_type='application/json', **s1_headers)
302
        self.assertEqual(r.status_code, 400)
303

    
304
        commission_request = {
305
            "auto_accept": True,
306
            "name": "my commission",
307
            "provisions": "dummy"}
308

    
309
        post_data = json.dumps(commission_request)
310
        r = client.post(u('commissions'), post_data,
311
                        content_type='application/json', **s1_headers)
312
        self.assertEqual(r.status_code, 400)
313

    
314
        r = client.post(u('commissions'), commission_request,
315
                        content_type='application/json', **s1_headers)
316
        self.assertEqual(r.status_code, 400)
317

    
318
        # no holding
319
        commission_request = {
320
            "auto_accept": True,
321
            "name": "my commission",
322
            "provisions": [
323
                {
324
                    "holder": "user:" + user.uuid,
325
                    "source": "project:" + user.uuid,
326
                    "resource": "non existent",
327
                    "quantity": 1
328
                },
329
                {
330
                    "holder": "user:" + user.uuid,
331
                    "source": "project:" + user.uuid,
332
                    "resource": resource12['name'],
333
                    "quantity": 100
334
                }]}
335

    
336
        post_data = json.dumps(commission_request)
337
        r = client.post(u('commissions'), post_data,
338
                        content_type='application/json', **s1_headers)
339
        self.assertEqual(r.status_code, 404)
340

    
341
        # release
342
        commission_request = {
343
            "provisions": [
344
                {
345
                    "holder": "user:" + user.uuid,
346
                    "source": "project:" + user.uuid,
347
                    "resource": resource11['name'],
348
                    "quantity": -1
349
                }
350
            ]}
351

    
352
        post_data = json.dumps(commission_request)
353
        r = client.post(u('commissions'), post_data,
354
                        content_type='application/json', **s1_headers)
355
        self.assertEqual(r.status_code, 201)
356
        body = json.loads(r.content)
357
        serial = body['serial']
358

    
359
        accept_data = {'accept': ""}
360
        post_data = json.dumps(accept_data)
361
        r = client.post(u('commissions/' + str(serial) + '/action'), post_data,
362
                        content_type='application/json', **s1_headers)
363
        self.assertEqual(r.status_code, 200)
364

    
365
        reject_data = {'reject': ""}
366
        post_data = json.dumps(accept_data)
367
        r = client.post(u('commissions/' + str(serial) + '/action'), post_data,
368
                        content_type='application/json', **s1_headers)
369
        self.assertEqual(r.status_code, 404)
370

    
371
        # force
372
        commission_request = {
373
            "force": True,
374
            "provisions": [
375
                {
376
                    "holder": "user:" + user.uuid,
377
                    "source": "project:" + user.uuid,
378
                    "resource": resource11['name'],
379
                    "quantity": 100
380
                }]}
381

    
382
        post_data = json.dumps(commission_request)
383
        r = client.post(u('commissions'), post_data,
384
                        content_type='application/json', **s1_headers)
385
        self.assertEqual(r.status_code, 201)
386

    
387
        commission_request = {
388
            "force": True,
389
            "provisions": [
390
                {
391
                    "holder": "user:" + user.uuid,
392
                    "source": "project:" + user.uuid,
393
                    "resource": resource11['name'],
394
                    "quantity": -200
395
                }]}
396

    
397
        post_data = json.dumps(commission_request)
398
        r = client.post(u('commissions'), post_data,
399
                        content_type='application/json', **s1_headers)
400
        self.assertEqual(r.status_code, 413)
401

    
402
        r = client.get(u('quotas'), **headers)
403
        self.assertEqual(r.status_code, 200)
404
        body = json.loads(r.content)
405
        base_quota = body[user.uuid]
406
        r11 = base_quota[resource11['name']]
407
        self.assertEqual(r11['usage'], 102)
408
        self.assertEqual(r11['pending'], 101)
409

    
410
        # Bad Request
411
        r = client.head(u('commissions'))
412
        self.assertEqual(r.status_code, 405)
413
        self.assertTrue('Allow' in r)
414

    
415

    
416
class TokensApiTest(TestCase):
417
    def setUp(self):
418
        backend = activation_backends.get_backend()
419

    
420
        self.user1 = get_local_user(
421
            'test1@example.org', email_verified=True, moderated=True,
422
            is_rejected=False)
423
        backend.activate_user(self.user1)
424
        assert self.user1.is_active is True
425

    
426
        self.user2 = get_local_user(
427
            'test2@example.org', email_verified=True, moderated=True,
428
            is_rejected=False)
429
        backend.activate_user(self.user2)
430
        assert self.user2.is_active is True
431

    
432
        c1 = Component(name='component1', url='http://localhost/component1')
433
        c1.save()
434
        s1 = Service(component=c1, type='type1', name='service1')
435
        s1.save()
436
        e1 = Endpoint(service=s1)
437
        e1.save()
438
        e1.data.create(key='versionId', value='v1.0')
439
        e1.data.create(key='publicURL', value='http://localhost:8000/s1/v1.0')
440

    
441
        s2 = Service(component=c1, type='type2', name='service2')
442
        s2.save()
443
        e2 = Endpoint(service=s2)
444
        e2.save()
445
        e2.data.create(key='versionId', value='v1.0')
446
        e2.data.create(key='publicURL', value='http://localhost:8000/s2/v1.0')
447

    
448
        c2 = Component(name='component2', url='http://localhost/component2')
449
        c2.save()
450
        s3 = Service(component=c2, type='type3', name='service3')
451
        s3.save()
452
        e3 = Endpoint(service=s3)
453
        e3.save()
454
        e3.data.create(key='versionId', value='v2.0')
455
        e3.data.create(key='publicURL', value='http://localhost:8000/s3/v2.0')
456

    
457
        oa2_backend = DjangoBackend()
458
        self.token = oa2_backend.token_model.create(
459
            code='12345',
460
            expires_at=datetime.now() + timedelta(seconds=5),
461
            user=self.user1,
462
            client=oa2_backend.client_model.create(type='public'),
463
            redirect_uri='https://server.com/handle_code')
464

    
465
    def test_authenticate(self):
466
        client = Client()
467
        url = reverse('astakos.api.tokens.authenticate')
468

    
469
        # Check not allowed method
470
        r = client.get(url, post_data={})
471
        self.assertEqual(r.status_code, 405)
472
        self.assertTrue('Allow' in r)
473
        self.assertEqual(r['Allow'], 'POST')
474

    
475
        # check public mode
476
        r = client.post(url, CONTENT_LENGTH=0)
477
        self.assertEqual(r.status_code, 200)
478
        self.assertTrue(r['Content-Type'].startswith('application/json'))
479
        try:
480
            body = json.loads(r.content)
481
        except Exception, e:
482
            self.fail(e)
483
        self.assertTrue('token' not in body.get('access'))
484
        self.assertTrue('user' not in body.get('access'))
485
        self.assertTrue('serviceCatalog' in body.get('access'))
486

    
487
        # Check unsupported xml input
488
        post_data = """
489
            <?xml version="1.0" encoding="UTF-8"?>
490
                <auth xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
491
                 xmlns="http://docs.openstack.org/identity/api/v2.0"
492
                 tenantName="%s">
493
                  <passwordCredentials username="%s" password="%s"/>
494
                </auth>""" % (self.user1.uuid, self.user1.uuid,
495
                              self.user1.auth_token)
496
        r = client.post(url, post_data, content_type='application/xml')
497
        self.assertEqual(r.status_code, 400)
498
        body = json.loads(r.content)
499
        self.assertEqual(body['badRequest']['message'],
500
                         "Unsupported Content-type: 'application/xml'")
501

    
502
        # Check malformed request: missing password
503
        post_data = """{"auth":{"passwordCredentials":{"username":"%s"},
504
                                "tenantName":"%s"}}""" % (
505
            self.user1.uuid, self.user1.uuid)
506
        r = client.post(url, post_data, content_type='application/json')
507
        self.assertEqual(r.status_code, 400)
508
        body = json.loads(r.content)
509
        self.assertTrue(body['badRequest']['message'].
510
                        startswith('Malformed request'))
511

    
512
        # Check malformed request: missing username
513
        post_data = """{"auth":{"passwordCredentials":{"password":"%s"},
514
                                "tenantName":"%s"}}""" % (
515
            self.user1.auth_token, self.user1.uuid)
516
        r = client.post(url, post_data, content_type='application/json')
517
        self.assertEqual(r.status_code, 400)
518
        body = json.loads(r.content)
519
        self.assertTrue(body['badRequest']['message'].
520
                        startswith('Malformed request'))
521

    
522
        # Check invalid pass
523
        post_data = """{"auth":{"passwordCredentials":{"username":"%s",
524
                                                       "password":"%s"},
525
                                "tenantName":"%s"}}""" % (
526
            self.user1.uuid, '', self.user1.uuid)
527
        r = client.post(url, post_data, content_type='application/json')
528
        self.assertEqual(r.status_code, 401)
529
        body = json.loads(r.content)
530
        self.assertEqual(body['unauthorized']['message'],
531
                         'Invalid token')
532

    
533
        # Check inconsistent pass
534
        post_data = """{"auth":{"passwordCredentials":{"username":"%s",
535
                                                       "password":"%s"},
536
                                "tenantName":"%s"}}""" % (
537
            self.user1.uuid, self.user2.auth_token, self.user2.uuid)
538
        r = client.post(url, post_data, content_type='application/json')
539
        self.assertEqual(r.status_code, 401)
540
        body = json.loads(r.content)
541
        self.assertEqual(body['unauthorized']['message'],
542
                         'Invalid credentials')
543

    
544
        # Check invalid json data
545
        r = client.post(url, "not json", content_type='application/json')
546
        self.assertEqual(r.status_code, 400)
547
        body = json.loads(r.content)
548
        self.assertEqual(body['badRequest']['message'], 'Invalid JSON data')
549

    
550
        # Check auth with token
551
        post_data = """{"auth":{"token": {"id":"%s"},
552
                        "tenantName":"%s"}}""" % (
553
            self.user1.auth_token, self.user1.uuid)
554
        r = client.post(url, post_data, content_type='application/json')
555
        self.assertEqual(r.status_code, 200)
556
        self.assertTrue(r['Content-Type'].startswith('application/json'))
557
        try:
558
            body = json.loads(r.content)
559
        except Exception, e:
560
            self.fail(e)
561

    
562
        # Check malformed request: missing token
563
        post_data = """{"auth":{"auth_token":{"id":"%s"},
564
                                "tenantName":"%s"}}""" % (
565
            self.user1.auth_token, self.user1.uuid)
566
        r = client.post(url, post_data, content_type='application/json')
567
        self.assertEqual(r.status_code, 400)
568
        body = json.loads(r.content)
569
        self.assertTrue(body['badRequest']['message'].
570
                        startswith('Malformed request'))
571

    
572
        # Check bad request: inconsistent tenant
573
        post_data = """{"auth":{"token":{"id":"%s"},
574
                                "tenantName":"%s"}}""" % (
575
            self.user1.auth_token, self.user2.uuid)
576
        r = client.post(url, post_data, content_type='application/json')
577
        self.assertEqual(r.status_code, 400)
578
        body = json.loads(r.content)
579
        self.assertEqual(body['badRequest']['message'],
580
                         'Not conforming tenantName')
581

    
582
        # Check bad request: inconsistent tenant
583
        post_data = """{"auth":{"token":{"id":"%s"},
584
                                "tenantName":""}}""" % (
585
            self.user1.auth_token)
586
        r = client.post(url, post_data, content_type='application/json')
587
        self.assertEqual(r.status_code, 200)
588

    
589
        # Check successful json response: user credential auth
590
        post_data = """{"auth":{"passwordCredentials":{"username":"%s",
591
                                                       "password":"%s"},
592
                                "tenantName":"%s"}}""" % (
593
            self.user1.uuid, self.user1.auth_token, self.user1.uuid)
594
        r = client.post(url, post_data, content_type='application/json')
595
        self.assertEqual(r.status_code, 200)
596
        self.assertTrue(r['Content-Type'].startswith('application/json'))
597
        try:
598
            body = json.loads(r.content)
599
        except Exception, e:
600
            self.fail(e)
601

    
602
        try:
603
            token = body['access']['token']['id']
604
            user = body['access']['user']['id']
605
            service_catalog = body['access']['serviceCatalog']
606
        except KeyError:
607
            self.fail('Invalid response')
608

    
609
        self.assertEqual(token, self.user1.auth_token)
610
        self.assertEqual(user, self.user1.uuid)
611
        self.assertEqual(len(service_catalog), 3)
612

    
613
        # Check successful json response: token auth
614
        post_data = """{"auth":{"token":{"id":"%s"},
615
                                "tenantName":"%s"}}""" % (
616
            self.user1.auth_token, self.user1.uuid)
617
        r = client.post(url, post_data, content_type='application/json')
618
        self.assertEqual(r.status_code, 200)
619
        self.assertTrue(r['Content-Type'].startswith('application/json'))
620
        try:
621
            body = json.loads(r.content)
622
        except Exception, e:
623
            self.fail(e)
624

    
625
        try:
626
            token = body['access']['token']['id']
627
            user = body['access']['user']['id']
628
            service_catalog = body['access']['serviceCatalog']
629
        except KeyError:
630
            self.fail('Invalid response')
631

    
632
        self.assertEqual(token, self.user1.auth_token)
633
        self.assertEqual(user, self.user1.uuid)
634
        self.assertEqual(len(service_catalog), 3)
635

    
636
        # Check successful xml response
637
        headers = {'HTTP_ACCEPT': 'application/xml'}
638
        post_data = """{"auth":{"passwordCredentials":{"username":"%s",
639
                                                       "password":"%s"},
640
                                "tenantName":"%s"}}""" % (
641
            self.user1.uuid, self.user1.auth_token, self.user1.uuid)
642
        r = client.post(url, post_data, content_type='application/json',
643
                        **headers)
644
        self.assertEqual(r.status_code, 200)
645
        self.assertTrue(r['Content-Type'].startswith('application/xml'))
646
#        try:
647
#            body = minidom.parseString(r.content)
648
#        except Exception, e:
649
#            self.fail(e)
650

    
651
        # oath access token authorization
652
        post_data = """{"auth":{"token":{"id":"%s"},
653
                                "tenantName":"%s"}}""" % (
654
            self.token.code, self.user1.uuid)
655
        r = client.post(url, post_data, content_type='application/json')
656
        self.assertEqual(r.status_code, 401)
657

    
658

    
659
class UserCatalogsTest(TestCase):
660
    def test_get_uuid_displayname_catalogs(self):
661
        self.user = get_local_user(
662
            'test1@example.org', email_verified=True, moderated=True,
663
            is_rejected=False, is_active=False)
664

    
665
        client = Client()
666
        url = reverse('astakos.api.user.get_uuid_displayname_catalogs')
667
        d = dict(uuids=[self.user.uuid], displaynames=[self.user.username])
668

    
669
        # assert Unauthorized: missing authentication token
670
        r = client.post(url,
671
                        data=json.dumps(d),
672
                        content_type='application/json')
673
        self.assertEqual(r.status_code, 401)
674

    
675
        # assert Unauthorized: invalid authentication token
676
        r = client.post(url,
677
                        data=json.dumps(d),
678
                        content_type='application/json',
679
                        HTTP_X_AUTH_TOKEN='1234')
680
        self.assertEqual(r.status_code, 401)
681

    
682
        # assert Unauthorized: inactive token holder
683
        r = client.post(url,
684
                        data=json.dumps(d),
685
                        content_type='application/json',
686
                        HTTP_X_AUTH_TOKEN=self.user.auth_token)
687
        self.assertEqual(r.status_code, 401)
688

    
689
        backend = activation_backends.get_backend()
690
        backend.activate_user(self.user)
691
        assert self.user.is_active is True
692

    
693
        r = client.post(url,
694
                        data=json.dumps(d),
695
                        content_type='application/json',
696
                        HTTP_X_AUTH_TOKEN=self.user.auth_token)
697
        self.assertEqual(r.status_code, 200)
698
        try:
699
            data = json.loads(r.content)
700
        except:
701
            self.fail('Response body should be json formatted')
702
        else:
703
            if not isinstance(data, dict):
704
                self.fail('Response body should be json formatted dictionary')
705

    
706
            self.assertTrue('uuid_catalog' in data)
707
            self.assertEqual(data['uuid_catalog'],
708
                             {self.user.uuid: self.user.username})
709

    
710
            self.assertTrue('displayname_catalog' in data)
711
            self.assertEqual(data['displayname_catalog'],
712
                             {self.user.username: self.user.uuid})
713

    
714
        # assert Unauthorized: expired token
715
        self.user.auth_token_expires = date.today() - timedelta(1)
716
        self.user.save()
717

    
718
        r = client.post(url,
719
                        data=json.dumps(d),
720
                        content_type='application/json',
721
                        HTTP_X_AUTH_TOKEN=self.user.auth_token)
722
        self.assertEqual(r.status_code, 401)
723

    
724
        # assert Unauthorized: expired token
725
        self.user.auth_token_expires = date.today() + timedelta(1)
726
        self.user.save()
727

    
728
        # assert badRequest
729
        r = client.post(url,
730
                        data=json.dumps(str(d)),
731
                        content_type='application/json',
732
                        HTTP_X_AUTH_TOKEN=self.user.auth_token)
733
        self.assertEqual(r.status_code, 400)
734

    
735

    
736
class WrongPathAPITest(TestCase):
737
    def test_catch_wrong_account_paths(self, *args):
738
        path = get_service_path(astakos_services, 'account', 'v1.0')
739
        path = join_urls(BASE_HOST, path, 'nonexistent')
740
        response = self.client.get(path)
741
        self.assertEqual(response.status_code, 400)
742
        try:
743
            error = json.loads(response.content)
744
        except ValueError:
745
            self.assertTrue(False)
746

    
747
    def test_catch_wrong_identity_paths(self, *args):
748
        path = get_service_path(astakos_services, 'identity', 'v2.0')
749
        path = join_urls(BASE_HOST, path, 'nonexistent')
750
        response = self.client.get(path)
751
        self.assertEqual(response.status_code, 400)
752
        try:
753
            json.loads(response.content)
754
        except ValueError:
755
            self.assertTrue(False)
756

    
757

    
758
class ValidateAccessToken(TestCase):
759
    def setUp(self):
760
        self.oa2_backend = DjangoBackend()
761
        self.user = get_local_user("user@synnefo.org")
762
        self.token = self.oa2_backend.token_model.create(
763
            code='12345',
764
            expires_at=datetime.now() + timedelta(seconds=5),
765
            user=self.user,
766
            client=self.oa2_backend.client_model.create(type='public'),
767
            redirect_uri='https://server.com/handle_code',
768
            scope='user-scope')
769

    
770
    def test_validate_token(self):
771
        # invalid token
772
        url = reverse('astakos.api.tokens.validate_token',
773
                      kwargs={'token_id': 'invalid'})
774
        r = self.client.get(url)
775
        self.assertEqual(r.status_code, 404)
776

    
777
        # valid token
778
        url = reverse('astakos.api.tokens.validate_token',
779
                      kwargs={'token_id': self.token.code})
780

    
781
        r = self.client.head(url)
782
        self.assertEqual(r.status_code, 405)
783
        r = self.client.put(url)
784
        self.assertEqual(r.status_code, 405)
785
        r = self.client.post(url)
786
        self.assertEqual(r.status_code, 405)
787

    
788
        r = self.client.get(url)
789
        self.assertEqual(r.status_code, 200)
790
        self.assertTrue(r['Content-Type'].startswith('application/json'))
791
        try:
792
            body = json.loads(r.content)
793
            user = body['access']['user']['id']
794
            self.assertEqual(user, self.user.uuid)
795
        except Exception:
796
            self.fail('Unexpected response content')
797

    
798
        # inconsistent belongsTo parameter
799
        r = self.client.get('%s?belongsTo=invalid' % url)
800
        self.assertEqual(r.status_code, 404)
801

    
802
        # consistent belongsTo parameter
803
        r = self.client.get('%s?belongsTo=%s' % (url, self.token.scope))
804
        self.assertEqual(r.status_code, 200)
805
        self.assertTrue(r['Content-Type'].startswith('application/json'))
806
        try:
807
            body = json.loads(r.content)
808
            user = body['access']['user']['id']
809
            self.assertEqual(user, self.user.uuid)
810
        except Exception:
811
            self.fail('Unexpected response content')
812

    
813
        # expired token
814
        sleep_time = (self.token.expires_at - datetime.now()).total_seconds()
815
        time.sleep(max(sleep_time, 0))
816
        r = self.client.get(url)
817
        self.assertEqual(r.status_code, 404)
818
        # assert expired token has been deleted
819
        self.assertEqual(self.oa2_backend.token_model.count(), 0)
820

    
821
        # user authentication token
822
        url = reverse('astakos.api.tokens.validate_token',
823
                      kwargs={'token_id': self.user.auth_token})
824
        self.assertEqual(r.status_code, 404)