Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (32 kB)

1
# Copyright 2011, 2012, 2013 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'],
549
                         'Could not decode request body as JSON')
550

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

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

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

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

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

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

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

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

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

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

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

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

    
659

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

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

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

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

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

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

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

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

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

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

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

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

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

    
736

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

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

    
758

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

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

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

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

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

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

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

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

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