Revision 79b5d61b snf-astakos-app/astakos/api/__init__.py

b/snf-astakos-app/astakos/api/__init__.py
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__()

Also available in: Unified diff