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