DEFAULT_USER_LEVEL, INVITATIONS_PER_LEVEL,
AUTH_TOKEN_DURATION, BILLING_FIELDS,
EMAILCHANGE_ACTIVATION_DAYS, LOGGING_LEVEL,
- GROUP_CREATION_SUBJECT
+ SITENAME, SERVICES,
+ PROJECT_CREATION_SUBJECT, PROJECT_APPROVED_SUBJECT,
+ PROJECT_TERMINATION_SUBJECT, PROJECT_SUSPENSION_SUBJECT,
+ PROJECT_MEMBERSHIP_CHANGE_SUBJECT
)
from astakos.im.endpoints.qh import (
register_users, send_quota, register_resources
class Resource(models.Model):
- name = models.CharField(_('Name'), max_length=255, unique=True, db_index=True)
+ name = models.CharField(_('Name'), max_length=255)
meta = models.ManyToManyField(ResourceMetadata)
service = models.ForeignKey(Service)
desc = models.TextField(_('Description'), null=True)
unit = models.CharField(_('Name'), null=True, max_length=255)
group = models.CharField(_('Group'), null=True, max_length=255)
+
+ class Meta:
+ unique_together = ("name", "service")
def __str__(self):
return '%s%s%s' % (self.service, RESOURCE_SEPARATOR, self.name)
self.owner = l
map(self.approve_member, l)
-
+_default_quota = {}
+def get_default_quota():
+ global _default_quota
+ if _default_quota:
+ return _default_quota
+ for s, data in SERVICES.iteritems():
+ map(
+ lambda d:_default_quota.update(
+ {'%s%s%s' % (s, RESOURCE_SEPARATOR, d.get('name')):d.get('uplimit', 0)}
+ ),
+ data.get('resources', {})
+ )
+ return _default_quota
class AstakosUserManager(UserManager):
def quota(self):
"""Returns a dict with the sum of quota limits per resource"""
d = defaultdict(int)
+ default_quota = get_default_quota()
+ d.update(default_quota)
for q in self.policies:
d[q.resource] += q.uplimit or inf
for m in self.projectmembership_set.select_related().all():
continue
grants = p.application.definition.projectresourcegrant_set.all()
for g in grants:
- d[g.resource] += g.member_limit or inf
+ d[str(g.resource)] += g.member_limit or inf
# TODO set default for remaining
return d
through='ProjectResourceGrant'
)
- def save(self):
- self.validate_name()
- super(ProjectDefinition, self).save()
-
@property
def violated_resource_grants(self):
return False
)
if q:
raise ValidationError(
- {'name': [_(astakos_messages.UNIQUE_PROJECT_NAME_CONSTRAIN_ERR)]}
+ _(astakos_messages.UNIQUE_PROJECT_NAME_CONSTRAIN_ERR)
)
@staticmethod
- def submit(definition, resource_policies, applicant, comments, precursor_application=None, commit=True):
- application = None
+ def submit(definition, resource_policies, applicant, comments,
+ precursor_application=None, commit=True):
+
+ application = ProjectApplication()
if precursor_application:
- precursor_application_id = precursor_application.id
- application = precursor_application
- application.id = None
+ application.precursor_application = precursor_application
+ application.owner = precursor_application.owner
else:
- application = ProjectApplication(owner=applicant)
+ application.owner = applicant
+
application.definition = definition
- application.definition.id = None
+ application.definition.resource_policies = resource_policies
application.applicant = applicant
application.comments = comments
application.issue_date = datetime.now()
application.state = PENDING
+
if commit:
application.save()
application.definition.resource_policies = resource_policies
precursor = ProjectApplication.objects.get(id=precursor_application_id)
except:
pass
- precursor.state = REPLACED
- precursor.save()
- application.precursor_application_id = precursor
+ application.precursor_application = precursor
application.save()
- else:
- notification = build_notification(
- settings.SERVER_EMAIL,
- [i[1] for i in settings.ADMINS],
- _(GROUP_CREATION_SUBJECT) % {'group':application.definition.name},
- _('An new project application identified by %(id)s has been submitted.') % application.__dict__
- )
- notification.send()
+
+ notification = build_notification(
+ settings.SERVER_EMAIL,
+ [i[1] for i in settings.ADMINS],
+ _(PROJECT_CREATION_SUBJECT) % application.definition.__dict__,
+ template='im/projects/project_creation_notification.txt',
+ dictionary={'object':application}
+ )
+ notification.send()
return application
-
+
def approve(self, approval_user=None):
"""
If approval_user then during owner membership acceptance
it is checked whether the request_user is eligible.
+
+ Raises:
+ ValidationError: if there is other alive project with the same name
+
"""
+ try:
+ self.definition.validate_name()
+ except ValidationError, e:
+ raise PermissionDenied(e.messages[0])
if self.state != PENDING:
- return
- create = False
+ raise PermissionDenied(_(PROJECT_ALREADY_ACTIVE))
+
try:
- self.precursor_application.project
- except:
- create = True
+ precursor = self.precursor_application
+ project = precursor.project
+ project.application = self
+ prev_approval_date = project.last_approval_date
+ project.last_approval_date = datetime.now()
+ project.save()
- if create:
+ p = precursor
+ while p:
+ p.state = REPLACED
+ p.save()
+ p = p.precursor_application
+
+ except:
kwargs = {
'application':self,
'creation_date':datetime.now(),
}
project = _create_object(Project, **kwargs)
project.accept_member(self.owner, approval_user)
- else:
- project = self.precursor_application.project
- project.application = self
- project.last_approval_date = datetime.now()
- project.save()
+ precursor = None
+
self.state = APPROVED
self.save()
notification = build_notification(
settings.SERVER_EMAIL,
[self.owner.email],
- _('Project application has been approved on %s alpha2 testing' % SITENAME),
- _('Your application request %(id)s has been apporved.')
+ _(PROJECT_APPROVED_SUBJECT) % self.definition.__dict__,
+ template='im/projects/project_approval_notification.txt',
+ dictionary={'object':self}
)
notification.send()
rejected = self.project.sync()
if rejected:
# revert to precursor
- project.application = app.precursor_application
- if project.application:
- project.last_approval_date = last_approval_date
+ if precursor:
+ project.application = precursor
+ project.last_approval_date = prev_approval_date
project.save()
+
rejected = project.sync()
if rejected:
raise Exception(_(astakos_messages.QH_SYNC_ERROR))
else:
- project.last_application_synced = app
+ project.last_application_synced = self
project.save()
@property
def is_suspended(self):
- if not self.termination_date:
+ if self.termination_date:
return False
- if not self.last_approval_date:
+ if self.last_approval_date:
if not self.definition.violated_resource_grants:
return False
# if not self.violated_members_number_limit:
m, created = ProjectMembership.objects.get_or_create(
person=user, project=self
)
- m.accept(user, delete_on_failure=created, request_user=None)
+ m.accept(delete_on_failure=created, request_user=None)
def reject_member(self, user, request_user=None):
"""
self.terminaton_date = datetime.now()
self.save()
- notification = build_notification(
- settings.SERVER_EMAIL,
- [self.application.owner.email],
- _('Project %(name)s has been terminated.') % self.definition.__dict__,
- _('Project %(name)s has been terminated.') % self.definition.__dict__
- )
- notification.send()
+ notification = build_notification(
+ settings.SERVER_EMAIL,
+ [self.application.owner.email],
+ _(PROJECT_TERMINATION_SUBJECT) % self.definition.__dict__,
+ template='im/projects/project_termination_notification.txt',
+ dictionary={'object':self.application}
+ )
+ notification.send()
def suspend(self):
self.last_approval_date = None
self.save()
+ self.sync()
notification = build_notification(
settings.SERVER_EMAIL,
[self.application.owner.email],
- _('Project %(name)s has been suspended.') % self.definition.__dict__,
- _('Project %(name)s has been suspended.') % self.definition.__dict__
+ _(PROJECT_SUSPENSION_SUBJECT) % self.definition.__dict__,
+ template='im/projects/project_suspension_notification.txt',
+ dictionary={'object':self.application}
)
notification.send()
notification = build_notification(
settings.SERVER_EMAIL,
[self.person.email],
- _('Your membership on project %(name)s has been accepted.') % self.project.definition.__dict__,
- _('Your membership on project %(name)s has been accepted.') % self.project.definition.__dict__
+ _(PROJECT_MEMBERSHIP_CHANGE_SUBJECT) % self.project.definition.__dict__,
+ template='im/projects/project_membership_change_notification.txt',
+ dictionary={'object':self.project.application, 'action':'accepted'}
).send()
self.sync()
project=self.project,
request_date=self.request_date,
rejection_date=datetime.now()
- ).save()
+ )
self.delete()
+ history_item.save()
notification = build_notification(
settings.SERVER_EMAIL,
[self.person.email],
- _('Your membership on project %(name)s has been rejected.') % self.project.definition.__dict__,
- _('Your membership on project %(name)s has been rejected.') % self.project.definition.__dict__
+ _(PROJECT_MEMBERSHIP_CHANGE_SUBJECT) % self.project.definition.__dict__,
+ template='im/projects/project_membership_change_notification.txt',
+ dictionary={'object':self.project.application, 'action':'rejected'}
).send()
def remove(self, request_user=None):
notification = build_notification(
settings.SERVER_EMAIL,
[self.person.email],
- _('Your membership on project %(name)s has been removed.') % self.project.definition.__dict__,
- _('Your membership on project %(name)s has been removed.') % self.project.definition.__dict__
+ _(PROJECT_MEMBERSHIP_CHANGE_SUBJECT) % self.project.definition.__dict__,
+ template='im/projects/project_membership_change_notification.txt',
+ dictionary={'object':self.project.application, 'action':'removed'}
).send()
self.sync()
self.project.membership_dirty = True
self.project.save()
- rejected = self.project.sync(specific_members=[self])
+ rejected = self.project.sync(specific_members=[self.person])
if not rejected:
# if syncing was successful unset membership_dirty flag
self.membership_dirty = False
- self.save()
+ self.project.save()
class ProjectMembershipHistory(models.Model):
def check_auto_accept_join_membership_policy(sender, instance, created, **kwargs):
- if created:
- join_policy = instance.project.application.definition.member_join_policy
- if join_policy == get_auto_accept_join():
- instance.accept()
+ if not created:
+ return
+ join_policy = instance.project.application.definition.member_join_policy
+ if join_policy == get_auto_accept_join():
+ instance.accept()
post_save.connect(check_auto_accept_join_membership_policy, sender=ProjectMembership)
\ No newline at end of file