Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / tokens.py @ 9b10cb20

History | View | Annotate | Download (4.8 kB)

1
# Copyright 2011-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 collections import defaultdict
35

    
36
from django.views.decorators.csrf import csrf_exempt
37

    
38
from snf_django.lib.api import faults, utils, api_method
39
from django.core.cache import cache
40

    
41
from astakos.im import settings
42
from astakos.im.models import Service, AstakosUser
43
from .util import json_response, xml_response, validate_user,\
44
    get_content_length
45

    
46
import logging
47
logger = logging.getLogger(__name__)
48

    
49

    
50
def compute_endpoints():
51
    l = []
52
    for s in Service.objects.all().order_by("id").\
53
            prefetch_related('endpoints__data').\
54
            select_related('component'):
55
        endpoints = []
56
        for e in s.endpoints.all():
57
            endpoint = dict((ed.key, ed.value) for ed in e.data.all())
58
            endpoint["SNF:uiURL"] = s.component.url
59
            endpoint["region"] = "default"
60
            if s.name == 'astakos_weblogin':
61
                endpoint["SNF:webloginURL"] = endpoint["publicURL"]
62
            endpoints.append(endpoint)
63
        l.append({"name": s.name,
64
                  "type": s.type,
65
                  "endpoints": endpoints,
66
                  "endpoints_links": []})
67
    return l
68

    
69

    
70
def get_endpoints():
71
    key = "endpoints"
72
    result = cache.get(key)
73
    if result is None:
74
        result = compute_endpoints()
75
        cache.set(key, result, settings.ENDPOINT_CACHE_TIMEOUT)
76
    return result
77

    
78

    
79
@csrf_exempt
80
@api_method(http_method="POST", token_required=False, user_required=False,
81
            logger=logger)
82
def authenticate(request):
83
    try:
84
        content_length = get_content_length(request)
85
    except faults.LengthRequired:
86
        content_length = None
87

    
88
    public_mode = True if not content_length else False
89

    
90
    d = defaultdict(dict)
91
    if not public_mode:
92
        req = utils.get_request_dict(request)
93

    
94
        uuid = None
95
        try:
96
            token_id = req['auth']['token']['id']
97
        except KeyError:
98
            try:
99
                token_id = req['auth']['passwordCredentials']['password']
100
                uuid = req['auth']['passwordCredentials']['username']
101
            except KeyError:
102
                raise faults.BadRequest(
103
                    'Malformed request: missing credentials')
104

    
105
        tenant = req['auth'].get('tenantName')
106

    
107
        if token_id is None:
108
            raise faults.BadRequest('Malformed request: missing token')
109

    
110
        try:
111
            user = AstakosUser.objects.get(auth_token=token_id)
112
        except AstakosUser.DoesNotExist:
113
            raise faults.Unauthorized('Invalid token')
114

    
115
        validate_user(user)
116

    
117
        if uuid is not None:
118
            if user.uuid != uuid:
119
                raise faults.Unauthorized('Invalid credentials')
120

    
121
        if tenant:
122
            if user.uuid != tenant:
123
                raise faults.BadRequest('Not conforming tenantName')
124

    
125
        d["access"]["token"] = {
126
            "id": user.auth_token,
127
            "expires": utils.isoformat(user.auth_token_expires),
128
            "tenant": {"id": user.uuid, "name": user.realname}}
129
        d["access"]["user"] = {
130
            "id": user.uuid, 'name': user.realname,
131
            "roles": list(user.groups.values("id", "name")),
132
            "roles_links": []}
133

    
134
    d["access"]["serviceCatalog"] = get_endpoints()
135

    
136
    if request.serialization == 'xml':
137
        return xml_response({'d': d}, 'api/access.xml')
138
    else:
139
        return json_response(d)