Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / __init__.py @ 79b5d61b

History | View | Annotate | Download (6.4 kB)

1
# Copyright 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
# Decorator for API methods, using common utils.api_method decorator.
35
# It is used for 'get_services' and 'get_menu' methods that do not
36
# require any sort of authentication
37

    
38
from functools import partial
39

    
40
from django.http import HttpResponse
41
from django.utils import simplejson as json
42
from django.core.urlresolvers import reverse
43
from django.utils.translation import ugettext as _
44
from django.contrib import messages
45

    
46
from snf_django.lib import api
47
from astakos.im.models import Service
48
from astakos.im.settings import (INVITATIONS_ENABLED, QUOTAHOLDER_URL,
49
                                 PROJECTS_VISIBLE)
50

    
51
import logging
52
logger = logging.getLogger(__name__)
53

    
54
absolute = lambda request, url: request.build_absolute_uri(url)
55

    
56
api_method = partial(api.api_method, user_required=False,
57
                     token_required=False, logger=logger)
58

    
59

    
60
@api_method(http_method=None)
61
def get_services(request):
62
    callback = request.GET.get('callback', None)
63
    mimetype = 'application/json'
64
    data = json.dumps(Service.catalog().values())
65

    
66
    if callback:
67
        # Consume session messages. When get_services is loaded from an astakos
68
        # page, messages should have already been consumed in the html
69
        # response. When get_services is loaded from another domain/service we
70
        # consume them here so that no stale messages to appear if user visits
71
        # an astakos view later on.
72
        # TODO: messages could be served to other services/sites in the dict
73
        # response of get_services and/or get_menu. Services could handle those
74
        # messages respectively.
75
        messages_list = list(messages.get_messages(request))
76
        mimetype = 'application/javascript'
77
        data = '%s(%s)' % (callback, data)
78

    
79
    return HttpResponse(content=data, mimetype=mimetype)
80

    
81

    
82
@api_method()
83
def get_menu(request, with_extra_links=False, with_signout=True):
84
    user = request.user
85
    index_url = reverse('index')
86

    
87
    if user.is_authenticated():
88
        l = []
89
        append = l.append
90
        item = MenuItem
91
        item.current_path = absolute(request, request.path)
92
        append(item(url=absolute(request, reverse('index')),
93
                    name=user.email))
94
        if with_extra_links:
95
            append(item(url=absolute(request, reverse('landing')),
96
                        name="Overview"))
97
        if with_signout:
98
            append(item(url=absolute(request, reverse('landing')),
99
                        name="Dashboard"))
100
        if with_extra_links:
101
            append(item(url=absolute(request, reverse('edit_profile')),
102
                        name="Profile"))
103

    
104
        if with_extra_links:
105
            if INVITATIONS_ENABLED:
106
                append(item(url=absolute(request, reverse('invite')),
107
                            name="Invitations"))
108

    
109
            append(item(url=absolute(request, reverse('resource_usage')),
110
                        name="Usage"))
111

    
112
            if QUOTAHOLDER_URL and PROJECTS_VISIBLE:
113
                append(item(url=absolute(request, reverse('project_list')),
114
                            name="Projects"))
115
            #append(item(
116
                #url=absolute(request, reverse('api_access')),
117
                #name="API Access"))
118

    
119
            append(item(url=absolute(request, reverse('feedback')),
120
                        name="Contact"))
121
        if with_signout:
122
            append(item(url=absolute(request, reverse('logout')),
123
                        name="Sign out"))
124
    else:
125
        l = [{'url': absolute(request, index_url),
126
              'name': _("Sign in")}]
127

    
128
    callback = request.GET.get('callback', None)
129
    data = json.dumps(tuple(l))
130
    mimetype = 'application/json'
131

    
132
    if callback:
133
        mimetype = 'application/javascript'
134
        data = '%s(%s)' % (callback, data)
135

    
136
    return HttpResponse(content=data, mimetype=mimetype)
137

    
138

    
139
class MenuItem(dict):
140
    current_path = ''
141

    
142
    def __init__(self, *args, **kwargs):
143
        super(MenuItem, self).__init__(*args, **kwargs)
144
        if kwargs.get('url') or kwargs.get('submenu'):
145
            self.__set_is_active__()
146

    
147
    def __setitem__(self, key, value):
148
        super(MenuItem, self).__setitem__(key, value)
149
        if key in ('url', 'submenu'):
150
            self.__set_is_active__()
151

    
152
    def __set_is_active__(self):
153
        if self.get('is_active'):
154
            return
155
        if self.current_path.startswith(self.get('url')):
156
            self.__setitem__('is_active', True)
157
        else:
158
            submenu = self.get('submenu', ())
159
            current = (i for i in submenu if i.get('url') == self.current_path)
160
            try:
161
                current_node = current.next()
162
                if not current_node.get('is_active'):
163
                    current_node.__setitem__('is_active', True)
164
                self.__setitem__('is_active', True)
165
            except StopIteration:
166
                return
167

    
168
    def __setattribute__(self, name, value):
169
        super(MenuItem, self).__setattribute__(name, value)
170
        if name == 'current_path':
171
            self.__set_is_active__()