Statistics
| Branch: | Tag: | Revision:

root / snf-astakos-app / astakos / api / util.py @ 4b805d30

History | View | Annotate | Download (7.1 kB)

1 18f21257 Giorgos Korfiatis
# Copyright 2013 GRNET S.A. All rights reserved.
2 18f21257 Giorgos Korfiatis
#
3 18f21257 Giorgos Korfiatis
# Redistribution and use in source and binary forms, with or
4 18f21257 Giorgos Korfiatis
# without modification, are permitted provided that the following
5 18f21257 Giorgos Korfiatis
# conditions are met:
6 18f21257 Giorgos Korfiatis
#
7 18f21257 Giorgos Korfiatis
#   1. Redistributions of source code must retain the above
8 18f21257 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
9 18f21257 Giorgos Korfiatis
#      disclaimer.
10 18f21257 Giorgos Korfiatis
#
11 18f21257 Giorgos Korfiatis
#   2. Redistributions in binary form must reproduce the above
12 18f21257 Giorgos Korfiatis
#      copyright notice, this list of conditions and the following
13 18f21257 Giorgos Korfiatis
#      disclaimer in the documentation and/or other materials
14 18f21257 Giorgos Korfiatis
#      provided with the distribution.
15 18f21257 Giorgos Korfiatis
#
16 18f21257 Giorgos Korfiatis
# THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 18f21257 Giorgos Korfiatis
# OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 18f21257 Giorgos Korfiatis
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 18f21257 Giorgos Korfiatis
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 18f21257 Giorgos Korfiatis
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 18f21257 Giorgos Korfiatis
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 18f21257 Giorgos Korfiatis
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 18f21257 Giorgos Korfiatis
# USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 18f21257 Giorgos Korfiatis
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 18f21257 Giorgos Korfiatis
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 18f21257 Giorgos Korfiatis
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 18f21257 Giorgos Korfiatis
# POSSIBILITY OF SUCH DAMAGE.
28 18f21257 Giorgos Korfiatis
#
29 18f21257 Giorgos Korfiatis
# The views and conclusions contained in the software and
30 18f21257 Giorgos Korfiatis
# documentation are those of the authors and should not be
31 18f21257 Giorgos Korfiatis
# interpreted as representing official policies, either expressed
32 18f21257 Giorgos Korfiatis
# or implied, of GRNET S.A.
33 18f21257 Giorgos Korfiatis
34 79b5d61b Sofia Papagiannaki
from functools import wraps
35 79b5d61b Sofia Papagiannaki
from time import time, mktime
36 bd20edc6 Giorgos Korfiatis
import datetime
37 79b5d61b Sofia Papagiannaki
38 18f21257 Giorgos Korfiatis
from django.http import HttpResponse
39 18f21257 Giorgos Korfiatis
from django.utils import simplejson as json
40 7ac2131c Sofia Papagiannaki
from django.template.loader import render_to_string
41 18f21257 Giorgos Korfiatis
42 bea584e1 Giorgos Korfiatis
from astakos.im.models import AstakosUser, Component
43 79b5d61b Sofia Papagiannaki
from snf_django.lib.api import faults
44 bd20edc6 Giorgos Korfiatis
from snf_django.lib.api.utils import isoformat
45 79b5d61b Sofia Papagiannaki
46 79b5d61b Sofia Papagiannaki
from astakos.im.forms import FeedbackForm
47 79b5d61b Sofia Papagiannaki
from astakos.im.functions import send_feedback as send_feedback_func
48 79b5d61b Sofia Papagiannaki
49 79b5d61b Sofia Papagiannaki
import logging
50 79b5d61b Sofia Papagiannaki
logger = logging.getLogger(__name__)
51 79b5d61b Sofia Papagiannaki
52 79b5d61b Sofia Papagiannaki
absolute = lambda request, url: request.build_absolute_uri(url)
53 79b5d61b Sofia Papagiannaki
54 18f21257 Giorgos Korfiatis
55 bd20edc6 Giorgos Korfiatis
def _dthandler(obj):
56 bd20edc6 Giorgos Korfiatis
    if isinstance(obj, datetime.datetime):
57 bd20edc6 Giorgos Korfiatis
        return isoformat(obj)
58 bd20edc6 Giorgos Korfiatis
    else:
59 bd20edc6 Giorgos Korfiatis
        raise TypeError
60 bd20edc6 Giorgos Korfiatis
61 bd20edc6 Giorgos Korfiatis
62 18f21257 Giorgos Korfiatis
def json_response(content, status_code=None):
63 18f21257 Giorgos Korfiatis
    response = HttpResponse()
64 18f21257 Giorgos Korfiatis
    if status_code is not None:
65 18f21257 Giorgos Korfiatis
        response.status_code = status_code
66 18f21257 Giorgos Korfiatis
67 bd20edc6 Giorgos Korfiatis
    response.content = json.dumps(content, default=_dthandler)
68 18f21257 Giorgos Korfiatis
    response['Content-Type'] = 'application/json; charset=UTF-8'
69 18f21257 Giorgos Korfiatis
    response['Content-Length'] = len(response.content)
70 18f21257 Giorgos Korfiatis
    return response
71 ad730cc5 Giorgos Korfiatis
72 ad730cc5 Giorgos Korfiatis
73 7ac2131c Sofia Papagiannaki
def xml_response(content, template, status_code=None):
74 7ac2131c Sofia Papagiannaki
    response = HttpResponse()
75 7ac2131c Sofia Papagiannaki
    if status_code is not None:
76 7ac2131c Sofia Papagiannaki
        response.status_code = status_code
77 7ac2131c Sofia Papagiannaki
78 7ac2131c Sofia Papagiannaki
    response.content = render_to_string(template, content)
79 7ac2131c Sofia Papagiannaki
    response['Content-Type'] = 'application/xml; charset=UTF-8'
80 7ac2131c Sofia Papagiannaki
    response['Content-Length'] = len(response.content)
81 7ac2131c Sofia Papagiannaki
    return response
82 7ac2131c Sofia Papagiannaki
83 7ac2131c Sofia Papagiannaki
84 ad730cc5 Giorgos Korfiatis
def is_integer(x):
85 ad730cc5 Giorgos Korfiatis
    return isinstance(x, (int, long))
86 ad730cc5 Giorgos Korfiatis
87 ad730cc5 Giorgos Korfiatis
88 ad730cc5 Giorgos Korfiatis
def are_integer(lst):
89 ad730cc5 Giorgos Korfiatis
    return all(map(is_integer, lst))
90 79b5d61b Sofia Papagiannaki
91 79b5d61b Sofia Papagiannaki
92 bd93595d Sofia Papagiannaki
def validate_user(user):
93 bd93595d Sofia Papagiannaki
    # Check if the user is active.
94 bd93595d Sofia Papagiannaki
    if not user.is_active:
95 bd93595d Sofia Papagiannaki
        raise faults.Unauthorized('User inactive')
96 bd93595d Sofia Papagiannaki
97 bd93595d Sofia Papagiannaki
    # Check if the token has expired.
98 bd93595d Sofia Papagiannaki
    if user.token_expired():
99 bd93595d Sofia Papagiannaki
        raise faults.Unauthorized('Authentication expired')
100 bd93595d Sofia Papagiannaki
101 bd93595d Sofia Papagiannaki
    # Check if the user has accepted the terms.
102 bd93595d Sofia Papagiannaki
    if not user.signed_terms:
103 bd93595d Sofia Papagiannaki
        raise faults.Unauthorized('Pending approval terms')
104 bd93595d Sofia Papagiannaki
105 bd93595d Sofia Papagiannaki
106 79b5d61b Sofia Papagiannaki
def user_from_token(func):
107 79b5d61b Sofia Papagiannaki
    @wraps(func)
108 79b5d61b Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
109 79b5d61b Sofia Papagiannaki
        try:
110 79b5d61b Sofia Papagiannaki
            token = request.x_auth_token
111 79b5d61b Sofia Papagiannaki
        except AttributeError:
112 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized("No authentication token")
113 79b5d61b Sofia Papagiannaki
114 79b5d61b Sofia Papagiannaki
        if not token:
115 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized("Invalid X-Auth-Token")
116 79b5d61b Sofia Papagiannaki
117 79b5d61b Sofia Papagiannaki
        try:
118 67920ea0 Giorgos Korfiatis
            user = AstakosUser.objects.get(auth_token=token)
119 79b5d61b Sofia Papagiannaki
        except AstakosUser.DoesNotExist:
120 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized('Invalid X-Auth-Token')
121 79b5d61b Sofia Papagiannaki
122 bd93595d Sofia Papagiannaki
        validate_user(user)
123 67920ea0 Giorgos Korfiatis
124 67920ea0 Giorgos Korfiatis
        request.user = user
125 276f454e Sofia Papagiannaki
        return func(request, *args, **kwargs)
126 79b5d61b Sofia Papagiannaki
    return wrapper
127 79b5d61b Sofia Papagiannaki
128 79b5d61b Sofia Papagiannaki
129 bea584e1 Giorgos Korfiatis
def component_from_token(func):
130 bea584e1 Giorgos Korfiatis
    """Decorator for authenticating component by its token.
131 79b5d61b Sofia Papagiannaki

132 bea584e1 Giorgos Korfiatis
    Check that a component with the corresponding token exists. Also,
133 bea584e1 Giorgos Korfiatis
    if component's token has an expiration token, check that it has not
134 79b5d61b Sofia Papagiannaki
    expired.
135 79b5d61b Sofia Papagiannaki

136 79b5d61b Sofia Papagiannaki
    """
137 79b5d61b Sofia Papagiannaki
    @wraps(func)
138 79b5d61b Sofia Papagiannaki
    def wrapper(request, *args, **kwargs):
139 79b5d61b Sofia Papagiannaki
        try:
140 79b5d61b Sofia Papagiannaki
            token = request.x_auth_token
141 79b5d61b Sofia Papagiannaki
        except AttributeError:
142 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized("No authentication token")
143 79b5d61b Sofia Papagiannaki
144 79b5d61b Sofia Papagiannaki
        if not token:
145 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized("Invalid X-Auth-Token")
146 79b5d61b Sofia Papagiannaki
        try:
147 bea584e1 Giorgos Korfiatis
            component = Component.objects.get(auth_token=token)
148 bea584e1 Giorgos Korfiatis
        except Component.DoesNotExist:
149 79b5d61b Sofia Papagiannaki
            raise faults.Unauthorized("Invalid X-Auth-Token")
150 79b5d61b Sofia Papagiannaki
151 79b5d61b Sofia Papagiannaki
        # Check if the token has expired
152 bea584e1 Giorgos Korfiatis
        expiration_date = component.auth_token_expires
153 79b5d61b Sofia Papagiannaki
        if expiration_date:
154 79b5d61b Sofia Papagiannaki
            expires_at = mktime(expiration_date.timetuple())
155 79b5d61b Sofia Papagiannaki
            if time() > expires_at:
156 79b5d61b Sofia Papagiannaki
                raise faults.Unauthorized("Authentication expired")
157 79b5d61b Sofia Papagiannaki
158 bea584e1 Giorgos Korfiatis
        request.component_instance = component
159 79b5d61b Sofia Papagiannaki
        return func(request, *args, **kwargs)
160 79b5d61b Sofia Papagiannaki
    return wrapper
161 79b5d61b Sofia Papagiannaki
162 79b5d61b Sofia Papagiannaki
163 7f313da1 Sofia Papagiannaki
def get_uuid_displayname_catalogs(request, user_call=True):
164 79b5d61b Sofia Papagiannaki
    # Normal Response Codes: 200
165 79b5d61b Sofia Papagiannaki
    # Error Response Codes: BadRequest (400)
166 79b5d61b Sofia Papagiannaki
167 79b5d61b Sofia Papagiannaki
    try:
168 79b5d61b Sofia Papagiannaki
        input_data = json.loads(request.raw_post_data)
169 79b5d61b Sofia Papagiannaki
    except:
170 79b5d61b Sofia Papagiannaki
        raise faults.BadRequest('Request body should be json formatted.')
171 79b5d61b Sofia Papagiannaki
    else:
172 79b5d61b Sofia Papagiannaki
        uuids = input_data.get('uuids', [])
173 79b5d61b Sofia Papagiannaki
        if uuids is None and user_call:
174 79b5d61b Sofia Papagiannaki
            uuids = []
175 79b5d61b Sofia Papagiannaki
        displaynames = input_data.get('displaynames', [])
176 79b5d61b Sofia Papagiannaki
        if displaynames is None and user_call:
177 79b5d61b Sofia Papagiannaki
            displaynames = []
178 79b5d61b Sofia Papagiannaki
        user_obj = AstakosUser.objects
179 79b5d61b Sofia Papagiannaki
        d = {'uuid_catalog': user_obj.uuid_catalog(uuids),
180 79b5d61b Sofia Papagiannaki
             'displayname_catalog': user_obj.displayname_catalog(displaynames)}
181 79b5d61b Sofia Papagiannaki
182 79b5d61b Sofia Papagiannaki
        response = HttpResponse()
183 79b5d61b Sofia Papagiannaki
        response.content = json.dumps(d)
184 79b5d61b Sofia Papagiannaki
        response['Content-Type'] = 'application/json; charset=UTF-8'
185 79b5d61b Sofia Papagiannaki
        response['Content-Length'] = len(response.content)
186 79b5d61b Sofia Papagiannaki
        return response
187 79b5d61b Sofia Papagiannaki
188 79b5d61b Sofia Papagiannaki
189 276f454e Sofia Papagiannaki
def send_feedback(request, email_template_name='im/feedback_mail.txt'):
190 79b5d61b Sofia Papagiannaki
    form = FeedbackForm(request.POST)
191 79b5d61b Sofia Papagiannaki
    if not form.is_valid():
192 79b5d61b Sofia Papagiannaki
        logger.error("Invalid feedback request: %r", form.errors)
193 79b5d61b Sofia Papagiannaki
        raise faults.BadRequest('Invalid data')
194 79b5d61b Sofia Papagiannaki
195 79b5d61b Sofia Papagiannaki
    msg = form.cleaned_data['feedback_msg']
196 79b5d61b Sofia Papagiannaki
    data = form.cleaned_data['feedback_data']
197 79b5d61b Sofia Papagiannaki
    try:
198 276f454e Sofia Papagiannaki
        send_feedback_func(msg, data, request.user, email_template_name)
199 79b5d61b Sofia Papagiannaki
    except:
200 79b5d61b Sofia Papagiannaki
        return HttpResponse(status=502)
201 79b5d61b Sofia Papagiannaki
    return HttpResponse(status=200)
202 7ac2131c Sofia Papagiannaki
203 7ac2131c Sofia Papagiannaki
204 7ac2131c Sofia Papagiannaki
def rename_meta_key(d, old, new):
205 7ac2131c Sofia Papagiannaki
    if old not in d:
206 7ac2131c Sofia Papagiannaki
        return
207 7ac2131c Sofia Papagiannaki
    d[new] = d[old]
208 7ac2131c Sofia Papagiannaki
    del(d[old])
209 d29f0371 Sofia Papagiannaki
210 d29f0371 Sofia Papagiannaki
211 d29f0371 Sofia Papagiannaki
def get_int_parameter(p):
212 d29f0371 Sofia Papagiannaki
    if p is not None:
213 d29f0371 Sofia Papagiannaki
        try:
214 d29f0371 Sofia Papagiannaki
            p = int(p)
215 d29f0371 Sofia Papagiannaki
        except ValueError:
216 d29f0371 Sofia Papagiannaki
            return None
217 d29f0371 Sofia Papagiannaki
        if p < 0:
218 d29f0371 Sofia Papagiannaki
            return None
219 d29f0371 Sofia Papagiannaki
    return p
220 d29f0371 Sofia Papagiannaki
221 d29f0371 Sofia Papagiannaki
222 d29f0371 Sofia Papagiannaki
def get_content_length(request):
223 d29f0371 Sofia Papagiannaki
    content_length = get_int_parameter(request.META.get('CONTENT_LENGTH'))
224 d29f0371 Sofia Papagiannaki
    if content_length is None:
225 d29f0371 Sofia Papagiannaki
        raise faults.LengthRequired('Missing or invalid Content-Length header')
226 d29f0371 Sofia Papagiannaki
    return content_length