Statistics
| Branch: | Tag: | Revision:

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

History | View | Annotate | Download (32.1 kB)

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

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

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

    
42
from django.core.urlresolvers import reverse
43

    
44
from datetime import date
45

    
46
#from xml.dom import minidom
47

    
48
import json
49
import time
50

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

    
55

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
258
        r = client.get(u('commissions/' + str(serial1)), **s1_headers)
259
        self.assertEqual(r.status_code, 404)
260

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

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

    
287
        r = client.get(u('commissions/' + str(serial4)), **s1_headers)
288
        self.assertEqual(r.status_code, 404)
289

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

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

    
307
        commission_request = {
308
            "auto_accept": True,
309
            "name": "κομίσσιον",
310
            "provisions": "dummy"}
311

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

    
317
        r = client.post(u('commissions'), commission_request,
318
                        content_type='application/json', **s1_headers)
319
        self.assertEqual(r.status_code, 400)
320

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

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

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

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

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

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

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

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

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

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

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

    
413
        # Bad Request
414
        r = client.head(u('commissions'))
415
        self.assertEqual(r.status_code, 405)
416
        self.assertTrue('Allow' in r)
417

    
418

    
419
class TokensApiTest(TestCase):
420
    def setUp(self):
421
        backend = activation_backends.get_backend()
422

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

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

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

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

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

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

    
468
    def test_authenticate(self):
469
        client = Client()
470
        url = reverse('astakos.api.tokens.authenticate')
471

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

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

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

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

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

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

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

    
547
        # Check invalid json data
548
        r = client.post(url, "not json", content_type='application/json')
549
        self.assertEqual(r.status_code, 400)
550
        body = json.loads(r.content)
551
        self.assertEqual(body['badRequest']['message'],
552
                         'Could not decode request body as JSON')
553

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

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

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

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

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

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

    
613
        self.assertEqual(token, self.user1.auth_token)
614
        self.assertEqual(user, self.user1.uuid)
615
        self.assertEqual(len(service_catalog), 3)
616

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

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

    
636
        self.assertEqual(token, self.user1.auth_token)
637
        self.assertEqual(user, self.user1.uuid)
638
        self.assertEqual(len(service_catalog), 3)
639

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

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

    
662

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

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

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

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

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

    
693
        backend = activation_backends.get_backend()
694
        backend.activate_user(self.user)
695
        assert self.user.is_active is True
696

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

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

    
714
            self.assertTrue('displayname_catalog' in data)
715
            self.assertEqual(data['displayname_catalog'],
716
                             {self.user.username: self.user.uuid})
717

    
718
        # assert Unauthorized: expired token
719
        self.user.auth_token_expires = date.today() - timedelta(1)
720
        self.user.save()
721

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

    
728
        # assert Unauthorized: expired token
729
        self.user.auth_token_expires = date.today() + timedelta(1)
730
        self.user.save()
731

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

    
739

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

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

    
761

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

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

    
781
        # valid token
782
        url = reverse('astakos.api.tokens.validate_token',
783
                      kwargs={'token_id': self.token.code})
784

    
785
        r = self.client.head(url)
786
        self.assertEqual(r.status_code, 405)
787
        r = self.client.put(url)
788
        self.assertEqual(r.status_code, 405)
789
        r = self.client.post(url)
790
        self.assertEqual(r.status_code, 405)
791

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

    
802
        # inconsistent belongsTo parameter
803
        r = self.client.get('%s?belongsTo=invalid' % url)
804
        self.assertEqual(r.status_code, 404)
805

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

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

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