Revision e1a80257 snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py

b/snf-astakos-app/astakos/im/api/backends/lib/django/__init__.py
33 33

  
34 34
from django.db import IntegrityError, transaction
35 35
from django.core.exceptions import ObjectDoesNotExist
36
from django.conf import settings
36 37

  
37 38
from functools import wraps
38 39
from smtplib import SMTPException
39 40

  
40 41
from astakos.im.models import (
41
    AstakosUser, AstakosGroup, GroupKind, Resource, Service, RESOURCE_SEPARATOR
42
    AstakosUser, AstakosGroup, GroupKind, Resource, Service, RESOURCE_SEPARATOR,
43
    Project, ProjectApplication, ProjectMembership, filter_queryset_by_property
42 44
)
43 45
from astakos.im.api.backends.base import BaseBackend, SuccessResult, FailureResult
44 46
from astakos.im.api.backends.errors import (
45 47
    ItemNotExists, ItemExists, MissingIdentifier, MultipleItemsExist
46 48
)
49
# from astakos.im.api.backends.lib.notifications import EmailNotification
50

  
47 51
from astakos.im.util import reserved_email, model_to_dict
48
from astakos.im.endpoints.qh import get_quota
52
from astakos.im.endpoints.qh import get_quota, send_quota
53
from astakos.im.settings import SITENAME
54
try:
55
    from astakos.im.messages import astakos_messages
56
except:
57
    pass
49 58

  
50 59
import logging
51 60

  
......
56 65

  
57 66
def safe(func):
58 67
    """Decorator function for views that implement an API method."""
59
    @transaction.commit_manually
60 68
    @wraps(func)
61 69
    def wrapper(self, *args, **kwargs):
62 70
        logger.debug('%s %s %s' % (func, args, kwargs))
......
64 72
            data = func(self, *args, **kwargs) or ()
65 73
        except Exception, e:
66 74
            logger.exception(e)
67
            transaction.rollback()
68 75
            return FailureResult(e)
69 76
        else:
70
            transaction.commit()
71 77
            return SuccessResult(data)
72 78
    return wrapper
73 79

  
......
107 113
        q = model.objects.all()
108 114
        if filter:
109 115
            q = q.filter(id__in=filter)
110
        return map(lambda o: model_to_dict(o, exclude=[]), q)
116
        return map(lambda o: self._details(o), q)
117

  
118
    def _details(self, obj):
119
        return model_to_dict(obj, exclude=[])
111 120

  
112 121
    def _create_object(self, model, **kwargs):
113 122
        o = model.objects.create(**kwargs)
......
136 145
        permissions = kwargs.pop('permissions', ())
137 146
        groups = kwargs.pop('groups', ())
138 147
        password = kwargs.pop('password', None)
148
        provider = kwargs.pop('provider', 'local')
139 149

  
140 150
        u = self._create_object(AstakosUser, **kwargs)
141 151

  
......
145 155
        u.policies = policies
146 156
        u.extended_groups = groups
147 157

  
148
        if not u.has_auth_provider('local'):
149
            u.add_auth_provider('local')
158
        if not u.has_auth_provider(provider):
159
            u.add_auth_provider(provider)
150 160

  
151
        return self._list(AstakosUser, filter=(u.id,))
161
        return self._details(u)
152 162

  
153 163
    @safe
154 164
    def add_policies(self, user_id, update=False, policies=()):
......
180 190
            except ObjectDoesNotExist, e:
181 191
                append((service, resource, e))
182 192
        return rejected
193
    
183 194
    @safe
184 195
    def add_permissions(self, user_id, permissions=()):
185 196
        user = self._lookup_user(user_id)
......
252 263
        resources = kwargs.pop('resources', ())
253 264
        s = self._create_object(Service, **kwargs)
254 265
        s.resources = resources
255
        return self._list(Service, filter=(s.id,))
266
        return self._details(s)
256 267

  
257 268
    @safe
258 269
    def remove_services(self, ids=()):
......
308 319
        g.policies = policies
309 320
#        g.members = members
310 321
        g.owners = owners
311
        return self._list(AstakosGroup, filter=(g.id,))
322
        return self._details(g)
323
    
324
    
325
    @safe
326
    def submit_application(self, **kwargs):
327
        app = self._create_object(ProjectApplication, **kwargs)
328
        notification = build_notification(
329
            settings.SERVER_EMAIL,
330
            [settings.ADMINS],
331
            _(GROUP_CREATION_SUBJECT) % {'group':app.definition.name},
332
            _('An new project application identified by %(serial)s has been submitted.') % app.serial
333
        )
334
        notification.send()
335
    
336
    @safe
337
    def list_applications(self):
338
        return self._list(ProjectAppication)
339
    
340
    @safe
341
    def approve_application(self, serial):
342
        app = self._lookup_object(ProjectAppication, serial=serial)
343
        notify = False
344
        if not app.precursor_application:
345
            kwargs = {
346
                'application':app,
347
                'creation_date':datetime.now(),
348
                'last_approval_date':datetime.now(),
349
            }
350
            project = self._create_object(Project, **kwargs)
351
        else:
352
            project = app.precursor_application.project
353
            last_approval_date = project.last_approval_date
354
            if project.is_valid:
355
                project.application = app
356
                project.last_approval_date = datetime.now()
357
                project.save()
358
            else:
359
                raise Exception(_(astakos_messages.INVALID_PROJECT) % project.__dict__)
360
        
361
        r = _synchonize_project(project.serial)
362
        if not r.is_success:
363
            # revert to precursor
364
            project.appication = app.precursor_application
365
            if project.application:
366
                project.last_approval_date = last_approval_date
367
            project.save()
368
            r = synchonize_project(project.serial)
369
            if not r.is_success:
370
                raise Exception(_(astakos_messages.QH_SYNC_ERROR))
371
        else:
372
            project.last_application_synced = app
373
            project.save()
374
            sender, recipients, subject, message
375
            notification = build_notification(
376
                settings.SERVER_EMAIL,
377
                [project.owner.email],
378
                _('Project application has been approved on %s alpha2 testing' % SITENAME),
379
                _('Your application request %(serial)s has been apporved.')
380
            )
381
            notification.send()
382
    
383
    
384
    @safe
385
    def list_projects(self, filter_property=None):
386
        if filter_property:
387
            q = filter_queryset_by_property(
388
                Project.objects.all(),
389
                filter_property
390
            )
391
            return map(lambda o: self._details(o), q)
392
        return self._list(Project)
393
        
394

  
395
    
396
    @safe
397
    def add_project_member(self, serial, user_id, request_user):
398
        project = self._lookup_object(Project, serial=serial)
399
        user = self.lookup_user(user_id)
400
        if not project.owner == request_user:
401
            raise Exception(_(astakos_messages.NOT_PROJECT_OWNER))
402
        
403
        if not project.is_alive:
404
            raise Exception(_(astakos_messages.NOT_ALIVE_PROJECT) % project.__dict__)
405
        if len(project.members) + 1 > project.limit_on_members_number:
406
            raise Exception(_(astakos_messages.MEMBER_NUMBER_LIMIT_REACHED))
407
        m = self._lookup_object(ProjectMembership, person=user, project=project)
408
        if m.is_accepted:
409
            return
410
        m.is_accepted = True
411
        m.decision_date = datetime.now()
412
        m.save()
413
        notification = build_notification(
414
            settings.SERVER_EMAIL,
415
            [user.email],
416
            _('Your membership on project %(name)s has been accepted.') % project.definition.__dict__, 
417
            _('Your membership on project %(name)s has been accepted.') % project.definition.__dict__,
418
        )
419
        notification.send()
420
    
421
    @safe
422
    def remove_project_member(self, serial, user_id, request_user):
423
        project = self._lookup_object(Project, serial=serial)
424
        if not project.is_alive:
425
            raise Exception(_(astakos_messages.NOT_ALIVE_PROJECT) % project.__dict__)
426
        if not project.owner == request_user:
427
            raise Exception(_(astakos_messages.NOT_PROJECT_OWNER))
428
        user = self.lookup_user(user_id)
429
        m = self._lookup_object(ProjectMembership, person=user, project=project)
430
        if not m.is_accepted:
431
            return
432
        m.is_accepted = False
433
        m.decision_date = datetime.now()
434
        m.save()
435
        notification = build_notification(
436
            settings.SERVER_EMAIL,
437
            [user.email],
438
            _('Your membership on project %(name)s has been removed.') % project.definition.__dict__, 
439
            _('Your membership on project %(name)s has been removed.') % project.definition.__dict__,
440
        )
441
        notification.send()    
442
    
443
    @safe
444
    def suspend_project(self, serial):
445
        project = self._lookup_object(Project, serial=serial)
446
        project.suspend()
447
        notification = build_notification(
448
            settings.SERVER_EMAIL,
449
            [project.owner.email],
450
            _('Project %(name)s has been suspended on %s alpha2 testing' % SITENAME),
451
            _('Project %(name)s has been suspended on %s alpha2 testing' % SITENAME)
452
        )
453
        notification.send()
454
    
455
    @safe
456
    def terminate_project(self, serial):
457
        project = self._lookup_object(Project, serial=serial)
458
        project.termination()
459
        notification = build_notification(
460
            settings.SERVER_EMAIL,
461
            [project.owner.email],
462
            _('Project %(name)s has been terminated on %s alpha2 testing' % SITENAME),
463
            _('Project %(name)s has been terminated on %s alpha2 testing' % SITENAME)
464
        )
465
        notification.send()
466
    
467
    @safe
468
    def synchonize_project(self, serial):
469
        project = self._lookup_object(Project, serial=serial)
470
        project.sync()

Also available in: Unified diff