Revision 18ffbee1 snf-astakos-app/astakos/im/api.py

b/snf-astakos-app/astakos/im/api.py
33 33

  
34 34
import logging
35 35

  
36
from functools import wraps
36 37
from traceback import format_exc
37 38
from time import time, mktime
38 39
from urllib import quote
......
43 44
from django.utils import simplejson as json
44 45
from django.core.urlresolvers import reverse
45 46

  
46
from astakos.im.faults import BadRequest, Unauthorized, InternalServerError
47
from astakos.im.faults import BadRequest, Unauthorized, InternalServerError, Fault
47 48
from astakos.im.models import AstakosUser
48 49
from astakos.im.settings import CLOUD_SERVICES, INVITATIONS_ENABLED
49
from astakos.im.util import has_signed_terms
50
from astakos.im.util import has_signed_terms, epoch
50 51

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

  
......
62 63
    response['Content-Length'] = len(response.content)
63 64
    return response
64 65

  
65
def authenticate(request):
66
def api_method(http_method=None, token_required=False, perms=[]):
67
    """Decorator function for views that implement an API method."""
68
    
69
    def decorator(func):
70
        @wraps(func)
71
        def wrapper(request, *args, **kwargs):
72
            try:
73
                if http_method and request.method != http_method:
74
                    raise BadRequest('Method not allowed.')
75
                x_auth_token = request.META.get('HTTP_X_AUTH_TOKEN')
76
                if token_required:
77
                    if not x_auth_token:
78
                        raise Unauthorized('Access denied')
79
                    try:
80
                        user = AstakosUser.objects.get(auth_token=x_auth_token)
81
                        if not user.has_perms(perms):
82
                            raise Unauthorized('Unauthorized request')
83
                    except AstakosUser.DoesNotExist, e:
84
                        raise Unauthorized('Invalid X-Auth-Token')
85
                    kwargs['user'] = user
86
                response = func(request, *args, **kwargs)
87
                return response
88
            except Fault, fault:
89
                return render_fault(request, fault)
90
            except BaseException, e:
91
                logger.exception('Unexpected error: %s' % e)
92
                fault = InternalServerError('Unexpected error')
93
                return render_fault(request, fault)
94
        return wrapper
95
    return decorator
96

  
97
@api_method(http_method='GET', token_required=True)
98
def authenticate_old(request, user=None):
66 99
    # Normal Response Codes: 204
67 100
    # Error Response Codes: internalServerError (500)
68 101
    #                       badRequest (400)
69 102
    #                       unauthorised (401)
70
    try:
71
        if request.method != 'GET':
72
            raise BadRequest('Method not allowed.')
73
        x_auth_token = request.META.get('HTTP_X_AUTH_TOKEN')
74
        if not x_auth_token:
75
            return render_fault(request, BadRequest('Missing X-Auth-Token'))
76

  
77
        try:
78
            user = AstakosUser.objects.get(auth_token=x_auth_token)
79
        except AstakosUser.DoesNotExist, e:
80
            return render_fault(request, Unauthorized('Invalid X-Auth-Token'))
81

  
82
        # Check if the is active.
83
        if not user.is_active:
84
            return render_fault(request, Unauthorized('User inactive'))
85

  
86
        # Check if the token has expired.
87
        if (time() - mktime(user.auth_token_expires.timetuple())) > 0:
88
            return render_fault(request, Unauthorized('Authentication expired'))
89
        
90
        if not has_signed_terms(user):
91
            return render_fault(request, Unauthorized('Pending approval terms'))
92
        
93
        response = HttpResponse()
94
        response.status=204
95
        user_info = {'username':user.username,
96
                     'uniq':user.email,
97
                     'auth_token':user.auth_token,
98
                     'auth_token_created':user.auth_token_created.isoformat(),
99
                     'auth_token_expires':user.auth_token_expires.isoformat(),
100
                     'has_credits':user.has_credits,
101
                     'has_signed_terms':has_signed_terms(user)}
102
        response.content = json.dumps(user_info)
103
        response['Content-Type'] = 'application/json; charset=UTF-8'
104
        response['Content-Length'] = len(response.content)
105
        return response
106
    except BaseException, e:
107
        logger.exception(e)
108
        fault = InternalServerError('Unexpected error')
109
        return render_fault(request, fault)
103
    if not user:
104
        raise BadRequest('No user')
105
    
106
    # Check if the is active.
107
    if not user.is_active:
108
        raise Unauthorized('User inactive')
110 109

  
111
def get_services(request):
112
    if request.method != 'GET':
113
        raise BadRequest('Method not allowed.')
110
    # Check if the token has expired.
111
    if (time() - mktime(user.auth_token_expires.timetuple())) > 0:
112
        raise Unauthorized('Authentication expired')
113
    
114
    if not has_signed_terms(user):
115
        raise Unauthorized('Pending approval terms')
116
    
117
    response = HttpResponse()
118
    response.status=204
119
    user_info = {'username':user.username,
120
                 'uniq':user.email,
121
                 'auth_token':user.auth_token,
122
                 'auth_token_created':user.auth_token_created.isoformat(),
123
                 'auth_token_expires':user.auth_token_expires.isoformat(),
124
                 'has_credits':user.has_credits,
125
                 'has_signed_terms':has_signed_terms(user)}
126
    response.content = json.dumps(user_info)
127
    response['Content-Type'] = 'application/json; charset=UTF-8'
128
    response['Content-Length'] = len(response.content)
129
    return response
130

  
131
@api_method(http_method='GET', token_required=True)
132
def authenticate(request, user=None):
133
    # Normal Response Codes: 204
134
    # Error Response Codes: internalServerError (500)
135
    #                       badRequest (400)
136
    #                       unauthorised (401)
137
    if not user:
138
        raise BadRequest('No user')
139
    
140
    # Check if the is active.
141
    if not user.is_active:
142
        raise Unauthorized('User inactive')
143

  
144
    # Check if the token has expired.
145
    if (time() - mktime(user.auth_token_expires.timetuple())) > 0:
146
        raise Unauthorized('Authentication expired')
147
    
148
    if not has_signed_terms(user):
149
        raise Unauthorized('Pending approval terms')
150
    
151
    response = HttpResponse()
152
    response.status=204
153
    user_info = {'userid':user.username,
154
                 'email':[user.email],
155
                 'name':user.realname,
156
                 'auth_token':user.auth_token,
157
                 'auth_token_created':epoch(user.auth_token_created),
158
                 'auth_token_expires':epoch(user.auth_token_expires),
159
                 'has_credits':user.has_credits,
160
                 'is_active':user.is_active,
161
                 'groups':[g.name for g in user.groups.all()]}
162
    response.content = json.dumps(user_info)
163
    response['Content-Type'] = 'application/json; charset=UTF-8'
164
    response['Content-Length'] = len(response.content)
165
    return response
114 166

  
167
@api_method(http_method='GET')
168
def get_services(request):
115 169
    callback = request.GET.get('callback', None)
116 170
    data = json.dumps(CLOUD_SERVICES)
117 171
    mimetype = 'application/json'
......
122 176

  
123 177
    return HttpResponse(content=data, mimetype=mimetype)
124 178

  
179
@api_method()
125 180
def get_menu(request, with_extra_links=False, with_signout=True):
126 181
    location = request.GET.get('location', '')
127 182
    exclude = []
......
144 199
        l.append({ 'url': absolute(reverse('astakos.im.views.edit_profile')),
145 200
                  'name': "My account" })
146 201
        if with_extra_links:
147
            if request.user.password:
202
            if request.user.has_usable_password():
148 203
                l.append({ 'url': absolute(reverse('password_change')),
149 204
                          'name': "Change password" })
150 205
            if INVITATIONS_ENABLED:
......
165 220
        data = '%s(%s)' % (callback, data)
166 221

  
167 222
    return HttpResponse(content=data, mimetype=mimetype)
223

  
224
@api_method(http_method='GET', token_required=True, perms=['astakos.im.can_find_userid'])
225
def find_userid(request):
226
    # Normal Response Codes: 204
227
    # Error Response Codes: internalServerError (500)
228
    #                       badRequest (400)
229
    #                       unauthorised (401)
230
    email = request.GET.get('email')
231
    if not email:
232
        raise BadRequest('Email missing')
233
    try:
234
        user = AstakosUser.objects.get(email = email)
235
    except AstakosUser.DoesNotExist, e:
236
        raise BadRequest('Invalid email')
237
    else:
238
        response = HttpResponse()
239
        response.status=204
240
        user_info = {'userid':user.username}
241
        response.content = json.dumps(user_info)
242
        response['Content-Type'] = 'application/json; charset=UTF-8'
243
        response['Content-Length'] = len(response.content)
244
        return response
245

  
246
@api_method(http_method='GET', token_required=True, perms=['astakos.im.can_find_email'])
247
def find_email(request):
248
    # Normal Response Codes: 204
249
    # Error Response Codes: internalServerError (500)
250
    #                       badRequest (400)
251
    #                       unauthorised (401)
252
    userid = request.GET.get('userid')
253
    if not userid:
254
        raise BadRequest('Userid missing')
255
    try:
256
        user = AstakosUser.objects.get(username = userid)
257
    except AstakosUser.DoesNotExist, e:
258
        raise BadRequest('Invalid userid')
259
    else:
260
        response = HttpResponse()
261
        response.status=204
262
        user_info = {'userid':user.email}
263
        response.content = json.dumps(user_info)
264
        response['Content-Type'] = 'application/json; charset=UTF-8'
265
        response['Content-Length'] = len(response.content)
266
        return response

Also available in: Unified diff