Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / im / api / __init__.py @ 632b6458

History | View | Annotate | Download (9.9 kB)

1 6b03a847 Sofia Papagiannaki
# Copyright 2011-2012 GRNET S.A. All rights reserved.
2 6b03a847 Sofia Papagiannaki
#
3 6b03a847 Sofia Papagiannaki
# Redistribution and use in source and binary forms, with or
4 6b03a847 Sofia Papagiannaki
# without modification, are permitted provided that the following
5 6b03a847 Sofia Papagiannaki
# conditions are met:
6 6b03a847 Sofia Papagiannaki
#
7 6b03a847 Sofia Papagiannaki
#   1. Redistributions of source code must retain the above
8 6b03a847 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
9 6b03a847 Sofia Papagiannaki
#      disclaimer.
10 6b03a847 Sofia Papagiannaki
#
11 6b03a847 Sofia Papagiannaki
#   2. Redistributions in binary form must reproduce the above
12 6b03a847 Sofia Papagiannaki
#      copyright notice, this list of conditions and the following
13 6b03a847 Sofia Papagiannaki
#      disclaimer in the documentation and/or other materials
14 6b03a847 Sofia Papagiannaki
#      provided with the distribution.
15 6b03a847 Sofia Papagiannaki
#
16 6b03a847 Sofia Papagiannaki
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 6b03a847 Sofia Papagiannaki
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 6b03a847 Sofia Papagiannaki
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 6b03a847 Sofia Papagiannaki
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 6b03a847 Sofia Papagiannaki
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 6b03a847 Sofia Papagiannaki
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 6b03a847 Sofia Papagiannaki
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 6b03a847 Sofia Papagiannaki
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 6b03a847 Sofia Papagiannaki
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 6b03a847 Sofia Papagiannaki
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 6b03a847 Sofia Papagiannaki
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 6b03a847 Sofia Papagiannaki
# POSSIBILITY OF SUCH DAMAGE.
28 6b03a847 Sofia Papagiannaki
#
29 6b03a847 Sofia Papagiannaki
# The views and conclusions contained in the software and
30 6b03a847 Sofia Papagiannaki
# documentation are those of the authors and should not be
31 6b03a847 Sofia Papagiannaki
# interpreted as representing official policies, either expressed
32 6b03a847 Sofia Papagiannaki
# or implied, of GRNET S.A.
33 6b03a847 Sofia Papagiannaki
34 14c5be5a Sofia Papagiannaki
from functools import wraps
35 14c5be5a Sofia Papagiannaki
from traceback import format_exc
36 14c5be5a Sofia Papagiannaki
from urllib import quote, unquote
37 14c5be5a Sofia Papagiannaki
38 6b03a847 Sofia Papagiannaki
from django.http import HttpResponse
39 6b03a847 Sofia Papagiannaki
from django.utils import simplejson as json
40 14c5be5a Sofia Papagiannaki
from django.conf import settings
41 14c5be5a Sofia Papagiannaki
from django.core.urlresolvers import reverse
42 14c5be5a Sofia Papagiannaki
43 14c5be5a Sofia Papagiannaki
from astakos.im.models import AstakosUser, GroupKind, Service, Resource
44 aab4d540 Sofia Papagiannaki
from astakos.im.api.faults import Fault, ItemNotFound, InternalServerError, BadRequest
45 14c5be5a Sofia Papagiannaki
from astakos.im.settings import INVITATIONS_ENABLED, COOKIE_NAME, EMAILCHANGE_ENABLED
46 6b03a847 Sofia Papagiannaki
47 14c5be5a Sofia Papagiannaki
import logging
48 14c5be5a Sofia Papagiannaki
logger = logging.getLogger(__name__)
49 6b03a847 Sofia Papagiannaki
50 6b03a847 Sofia Papagiannaki
format = ('%a, %d %b %Y %H:%M:%S GMT')
51 6b03a847 Sofia Papagiannaki
52 a88d9ec1 Sofia Papagiannaki
absolute = lambda request, url: request.build_absolute_uri(url)
53 a88d9ec1 Sofia Papagiannaki
54 5ce3ce4f Sofia Papagiannaki
55 14c5be5a Sofia Papagiannaki
def render_fault(request, fault):
56 14c5be5a Sofia Papagiannaki
    if isinstance(fault, InternalServerError) and settings.DEBUG:
57 14c5be5a Sofia Papagiannaki
        fault.details = format_exc(fault)
58 14c5be5a Sofia Papagiannaki
59 14c5be5a Sofia Papagiannaki
    request.serialization = 'text'
60 14c5be5a Sofia Papagiannaki
    data = fault.message + '\n'
61 14c5be5a Sofia Papagiannaki
    if fault.details:
62 14c5be5a Sofia Papagiannaki
        data += '\n' + fault.details
63 14c5be5a Sofia Papagiannaki
    response = HttpResponse(data, status=fault.code)
64 14c5be5a Sofia Papagiannaki
    response['Content-Length'] = len(response.content)
65 14c5be5a Sofia Papagiannaki
    return response
66 14c5be5a Sofia Papagiannaki
67 5ce3ce4f Sofia Papagiannaki
68 14c5be5a Sofia Papagiannaki
def api_method(http_method=None):
69 14c5be5a Sofia Papagiannaki
    """Decorator function for views that implement an API method."""
70 14c5be5a Sofia Papagiannaki
    def decorator(func):
71 14c5be5a Sofia Papagiannaki
        @wraps(func)
72 14c5be5a Sofia Papagiannaki
        def wrapper(request, *args, **kwargs):
73 14c5be5a Sofia Papagiannaki
            try:
74 14c5be5a Sofia Papagiannaki
                if http_method and request.method != http_method:
75 14c5be5a Sofia Papagiannaki
                    raise BadRequest('Method not allowed.')
76 14c5be5a Sofia Papagiannaki
                response = func(request, *args, **kwargs)
77 14c5be5a Sofia Papagiannaki
                return response
78 14c5be5a Sofia Papagiannaki
            except Fault, fault:
79 14c5be5a Sofia Papagiannaki
                return render_fault(request, fault)
80 14c5be5a Sofia Papagiannaki
            except BaseException, e:
81 14c5be5a Sofia Papagiannaki
                logger.exception('Unexpected error: %s' % e)
82 14c5be5a Sofia Papagiannaki
                fault = InternalServerError('Unexpected error')
83 14c5be5a Sofia Papagiannaki
                return render_fault(request, fault)
84 14c5be5a Sofia Papagiannaki
        return wrapper
85 14c5be5a Sofia Papagiannaki
    return decorator
86 14c5be5a Sofia Papagiannaki
87 5ce3ce4f Sofia Papagiannaki
88 6b03a847 Sofia Papagiannaki
def _get_user_by_username(user_id):
89 6b03a847 Sofia Papagiannaki
    try:
90 5ce3ce4f Sofia Papagiannaki
        user = AstakosUser.objects.get(username=user_id)
91 aab4d540 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
92 6b03a847 Sofia Papagiannaki
        raise ItemNotFound('Invalid userid')
93 6b03a847 Sofia Papagiannaki
    else:
94 6b03a847 Sofia Papagiannaki
        response = HttpResponse()
95 5ce3ce4f Sofia Papagiannaki
        response.status = 200
96 5ce3ce4f Sofia Papagiannaki
        user_info = {'id': user.id,
97 5ce3ce4f Sofia Papagiannaki
                     'username': user.username,
98 5ce3ce4f Sofia Papagiannaki
                     'email': [user.email],
99 5ce3ce4f Sofia Papagiannaki
                     'name': user.realname,
100 5ce3ce4f Sofia Papagiannaki
                     'auth_token_created': user.auth_token_created.strftime(format),
101 5ce3ce4f Sofia Papagiannaki
                     'auth_token_expires': user.auth_token_expires.strftime(format),
102 5ce3ce4f Sofia Papagiannaki
                     'has_credits': user.has_credits,
103 5ce3ce4f Sofia Papagiannaki
                     'enabled': user.is_active,
104 5ce3ce4f Sofia Papagiannaki
                     'groups': [g.name for g in user.groups.all()]}
105 6b03a847 Sofia Papagiannaki
        response.content = json.dumps(user_info)
106 6b03a847 Sofia Papagiannaki
        response['Content-Type'] = 'application/json; charset=UTF-8'
107 6b03a847 Sofia Papagiannaki
        response['Content-Length'] = len(response.content)
108 6b03a847 Sofia Papagiannaki
        return response
109 6b03a847 Sofia Papagiannaki
110 5ce3ce4f Sofia Papagiannaki
111 6b03a847 Sofia Papagiannaki
def _get_user_by_email(email):
112 6b03a847 Sofia Papagiannaki
    if not email:
113 6b03a847 Sofia Papagiannaki
        raise BadRequest('Email missing')
114 6b03a847 Sofia Papagiannaki
    try:
115 789a5951 Sofia Papagiannaki
        user = AstakosUser.objects.get(email__iexact=email)
116 aab4d540 Sofia Papagiannaki
    except AstakosUser.DoesNotExist:
117 6b03a847 Sofia Papagiannaki
        raise ItemNotFound('Invalid email')
118 5ce3ce4f Sofia Papagiannaki
119 6b03a847 Sofia Papagiannaki
    if not user.is_active:
120 6b03a847 Sofia Papagiannaki
        raise ItemNotFound('Inactive user')
121 6b03a847 Sofia Papagiannaki
    else:
122 6b03a847 Sofia Papagiannaki
        response = HttpResponse()
123 5ce3ce4f Sofia Papagiannaki
        response.status = 200
124 5ce3ce4f Sofia Papagiannaki
        user_info = {'id': user.id,
125 5ce3ce4f Sofia Papagiannaki
                     'username': user.username,
126 5ce3ce4f Sofia Papagiannaki
                     'email': [user.email],
127 5ce3ce4f Sofia Papagiannaki
                     'enabled': user.is_active,
128 5ce3ce4f Sofia Papagiannaki
                     'name': user.realname,
129 5ce3ce4f Sofia Papagiannaki
                     'auth_token_created': user.auth_token_created.strftime(format),
130 5ce3ce4f Sofia Papagiannaki
                     'auth_token_expires': user.auth_token_expires.strftime(format),
131 5ce3ce4f Sofia Papagiannaki
                     'has_credits': user.has_credits,
132 5ce3ce4f Sofia Papagiannaki
                     'groups': [g.name for g in user.groups.all()],
133 5ce3ce4f Sofia Papagiannaki
                     'user_permissions': [p.codename for p in user.user_permissions.all()]}
134 6b03a847 Sofia Papagiannaki
        response.content = json.dumps(user_info)
135 6b03a847 Sofia Papagiannaki
        response['Content-Type'] = 'application/json; charset=UTF-8'
136 6b03a847 Sofia Papagiannaki
        response['Content-Length'] = len(response.content)
137 14c5be5a Sofia Papagiannaki
        return response
138 14c5be5a Sofia Papagiannaki
139 5ce3ce4f Sofia Papagiannaki
140 14c5be5a Sofia Papagiannaki
@api_method(http_method='GET')
141 14c5be5a Sofia Papagiannaki
def get_services(request):
142 14c5be5a Sofia Papagiannaki
    callback = request.GET.get('callback', None)
143 14c5be5a Sofia Papagiannaki
    services = Service.objects.all()
144 5ce3ce4f Sofia Papagiannaki
    data = tuple({'id': s.pk, 'name': s.name, 'url': s.url, 'icon':
145 5ce3ce4f Sofia Papagiannaki
                 s.icon} for s in services)
146 14c5be5a Sofia Papagiannaki
    data = json.dumps(data)
147 14c5be5a Sofia Papagiannaki
    mimetype = 'application/json'
148 14c5be5a Sofia Papagiannaki
149 14c5be5a Sofia Papagiannaki
    if callback:
150 14c5be5a Sofia Papagiannaki
        mimetype = 'application/javascript'
151 14c5be5a Sofia Papagiannaki
        data = '%s(%s)' % (callback, data)
152 14c5be5a Sofia Papagiannaki
153 14c5be5a Sofia Papagiannaki
    return HttpResponse(content=data, mimetype=mimetype)
154 14c5be5a Sofia Papagiannaki
155 5ce3ce4f Sofia Papagiannaki
156 14c5be5a Sofia Papagiannaki
@api_method()
157 ed4a91be Olga Brani
def get_menu(request, with_extra_links=False, with_signout=True):
158 304acb60 Olga Brani
    user = request.user
159 c0b26605 Sofia Papagiannaki
    index_url = reverse('index')
160 c0b26605 Sofia Papagiannaki
    l = [{'url': absolute(request, index_url), 'name': "Sign in"}]
161 c0b26605 Sofia Papagiannaki
    if user.is_authenticated():
162 14c5be5a Sofia Papagiannaki
        l = []
163 a88d9ec1 Sofia Papagiannaki
        append = l.append
164 a88d9ec1 Sofia Papagiannaki
        item = MenuItem
165 a88d9ec1 Sofia Papagiannaki
        item.current_path = absolute(request, request.path)
166 54213d7a Sofia Papagiannaki
        append(item(
167 9a06d96f Olga Brani
               url=absolute(request, reverse('index')),
168 9a06d96f Olga Brani
               name=user.email))
169 54213d7a Sofia Papagiannaki
        append(item(url=absolute(request, reverse('edit_profile')),
170 54213d7a Sofia Papagiannaki
               name="My account"))
171 14c5be5a Sofia Papagiannaki
        if with_extra_links:
172 632b6458 Olga Brani
#            if user.has_usable_password() and user.provider in ('local', ''):
173 632b6458 Olga Brani
#                append(item(
174 632b6458 Olga Brani
#                       url=absolute(request, reverse('password_change')),
175 632b6458 Olga Brani
#                       name="Change password"))
176 632b6458 Olga Brani
#            if EMAILCHANGE_ENABLED:
177 632b6458 Olga Brani
#                append(item(
178 632b6458 Olga Brani
#                       url=absolute(request, reverse('email_change')),
179 632b6458 Olga Brani
#                       name="Change email"))
180 632b6458 Olga Brani
#            if INVITATIONS_ENABLED:
181 632b6458 Olga Brani
#                append(item(
182 632b6458 Olga Brani
#                       url=absolute(request, reverse('invite')),
183 632b6458 Olga Brani
#                       name="Invitations"))
184 a3e77c69 Olga Brani
            
185 54213d7a Sofia Papagiannaki
            append(item(
186 9a06d96f Olga Brani
                   url=absolute(request, reverse('group_list')),
187 59728d4e Olga Brani
                   name="Projects",
188 632b6458 Olga Brani
#                   submenu=(item(
189 632b6458 Olga Brani
#                            url=absolute(request,
190 632b6458 Olga Brani
#                                         reverse('group_list')),
191 632b6458 Olga Brani
#                            name="Overview"),
192 632b6458 Olga Brani
#                            item(
193 632b6458 Olga Brani
#                                url=absolute(request,
194 632b6458 Olga Brani
#                                             reverse('group_create_list')),
195 632b6458 Olga Brani
#                                name="Create"),
196 632b6458 Olga Brani
#                            item(
197 632b6458 Olga Brani
#                                url=absolute(request,
198 632b6458 Olga Brani
#                                             reverse('group_search')),
199 632b6458 Olga Brani
#                                name="Join"),)
200 632b6458 Olga Brani
                        ))
201 54213d7a Sofia Papagiannaki
            append(item(
202 9a06d96f Olga Brani
                   url=absolute(request, reverse('resource_list')),
203 a3e77c69 Olga Brani
                   name="Report"))
204 a3e77c69 Olga Brani
            append(item(
205 a3e77c69 Olga Brani
                   url=absolute(request, reverse('feedback')),
206 a3e77c69 Olga Brani
                   name="Feedback"))
207 f70da940 root
#            append(item(
208 f70da940 root
#                   url=absolute(request, reverse('billing')),
209 f70da940 root
#                   name="Billing"))
210 f70da940 root
#            append(item(
211 f70da940 root
#                   url=absolute(request, reverse('timeline')),
212 f70da940 root
#                   name="Timeline"))
213 14c5be5a Sofia Papagiannaki
        if with_signout:
214 54213d7a Sofia Papagiannaki
            append(item(
215 9a06d96f Olga Brani
                   url=absolute(request, reverse('logout')),
216 9a06d96f Olga Brani
                   name="Sign out"))
217 5ce3ce4f Sofia Papagiannaki
218 14c5be5a Sofia Papagiannaki
    callback = request.GET.get('callback', None)
219 14c5be5a Sofia Papagiannaki
    data = json.dumps(tuple(l))
220 14c5be5a Sofia Papagiannaki
    mimetype = 'application/json'
221 14c5be5a Sofia Papagiannaki
222 14c5be5a Sofia Papagiannaki
    if callback:
223 14c5be5a Sofia Papagiannaki
        mimetype = 'application/javascript'
224 14c5be5a Sofia Papagiannaki
        data = '%s(%s)' % (callback, data)
225 14c5be5a Sofia Papagiannaki
226 a88d9ec1 Sofia Papagiannaki
    return HttpResponse(content=data, mimetype=mimetype)
227 a88d9ec1 Sofia Papagiannaki
228 5ce3ce4f Sofia Papagiannaki
229 a88d9ec1 Sofia Papagiannaki
class MenuItem(dict):
230 a88d9ec1 Sofia Papagiannaki
    current_path = ''
231 5ce3ce4f Sofia Papagiannaki
232 a88d9ec1 Sofia Papagiannaki
    def __init__(self, *args, **kwargs):
233 a88d9ec1 Sofia Papagiannaki
        super(MenuItem, self).__init__(*args, **kwargs)
234 a88d9ec1 Sofia Papagiannaki
        if kwargs.get('url') or kwargs.get('submenu'):
235 a88d9ec1 Sofia Papagiannaki
            self.__set_is_active__()
236 5ce3ce4f Sofia Papagiannaki
237 a88d9ec1 Sofia Papagiannaki
    def __setitem__(self, key, value):
238 a88d9ec1 Sofia Papagiannaki
        super(MenuItem, self).__setitem__(key, value)
239 a88d9ec1 Sofia Papagiannaki
        if key in ('url', 'submenu'):
240 a88d9ec1 Sofia Papagiannaki
            self.__set_is_active__()
241 5ce3ce4f Sofia Papagiannaki
242 a88d9ec1 Sofia Papagiannaki
    def __set_is_active__(self):
243 2ef68a58 Sofia Papagiannaki
        if self.get('is_active'):
244 2ef68a58 Sofia Papagiannaki
            return
245 a88d9ec1 Sofia Papagiannaki
        if self.current_path == self.get('url'):
246 a88d9ec1 Sofia Papagiannaki
            self.__setitem__('is_active', True)
247 a88d9ec1 Sofia Papagiannaki
        else:
248 2ef68a58 Sofia Papagiannaki
            submenu = self.get('submenu', ())
249 2ef68a58 Sofia Papagiannaki
            current = (i for i in submenu if i.get('url') == self.current_path)
250 2ef68a58 Sofia Papagiannaki
            try:
251 2ef68a58 Sofia Papagiannaki
                current_node = current.next()
252 2ef68a58 Sofia Papagiannaki
                if not current_node.get('is_active'):
253 2ef68a58 Sofia Papagiannaki
                    current_node.__setitem__('is_active', True)
254 2ef68a58 Sofia Papagiannaki
                self.__setitem__('is_active', True)
255 2ef68a58 Sofia Papagiannaki
            except StopIteration:
256 2ef68a58 Sofia Papagiannaki
                return
257 5ce3ce4f Sofia Papagiannaki
258 2ef68a58 Sofia Papagiannaki
    def __setattribute__(self, name, value):
259 2ef68a58 Sofia Papagiannaki
        super(MenuItem, self).__setattribute__(name, value)
260 2ef68a58 Sofia Papagiannaki
        if name == 'current_path':
261 5ce3ce4f Sofia Papagiannaki
            self.__set_is_active__()