Revision fcc1e93f snf-astakos-app/astakos/im/models.py
b/snf-astakos-app/astakos/im/models.py | ||
---|---|---|
165 | 165 |
def __str__(self): |
166 | 166 |
return '%s%s%s' % (self.service, RESOURCE_SEPARATOR, self.name) |
167 | 167 |
|
168 |
|
|
169 |
class GroupKind(models.Model): |
|
170 |
name = models.CharField(_('Name'), max_length=255, unique=True, db_index=True) |
|
171 |
|
|
172 |
def __str__(self): |
|
173 |
return self.name |
|
174 |
|
|
175 |
|
|
176 |
class AstakosGroup(Group): |
|
177 |
kind = models.ForeignKey(GroupKind) |
|
178 |
homepage = models.URLField( |
|
179 |
_('Homepage Url'), max_length=255, null=True, blank=True) |
|
180 |
desc = models.TextField(_('Description'), null=True) |
|
181 |
policy = models.ManyToManyField( |
|
182 |
Resource, |
|
183 |
null=True, |
|
184 |
blank=True, |
|
185 |
through='AstakosGroupQuota' |
|
186 |
) |
|
187 |
creation_date = models.DateTimeField( |
|
188 |
_('Creation date'), |
|
189 |
default=datetime.now() |
|
190 |
) |
|
191 |
issue_date = models.DateTimeField( |
|
192 |
_('Start date'), |
|
193 |
null=True |
|
194 |
) |
|
195 |
expiration_date = models.DateTimeField( |
|
196 |
_('Expiration date'), |
|
197 |
null=True |
|
198 |
) |
|
199 |
moderation_enabled = models.BooleanField( |
|
200 |
_('Moderated membership?'), |
|
201 |
default=True |
|
202 |
) |
|
203 |
approval_date = models.DateTimeField( |
|
204 |
_('Activation date'), |
|
205 |
null=True, |
|
206 |
blank=True |
|
207 |
) |
|
208 |
estimated_participants = models.PositiveIntegerField( |
|
209 |
_('Estimated #members'), |
|
210 |
null=True, |
|
211 |
blank=True, |
|
212 |
) |
|
213 |
max_participants = models.PositiveIntegerField( |
|
214 |
_('Maximum numder of participants'), |
|
215 |
null=True, |
|
216 |
blank=True |
|
217 |
) |
|
218 |
|
|
219 |
@property |
|
220 |
def is_disabled(self): |
|
221 |
if not self.approval_date: |
|
222 |
return True |
|
223 |
return False |
|
224 |
|
|
225 |
@property |
|
226 |
def is_enabled(self): |
|
227 |
if self.is_disabled: |
|
228 |
return False |
|
229 |
if not self.issue_date: |
|
230 |
return False |
|
231 |
if not self.expiration_date: |
|
232 |
return True |
|
233 |
now = datetime.now() |
|
234 |
if self.issue_date > now: |
|
235 |
return False |
|
236 |
if now >= self.expiration_date: |
|
237 |
return False |
|
238 |
return True |
|
239 |
|
|
240 |
def enable(self): |
|
241 |
if self.is_enabled: |
|
242 |
return |
|
243 |
self.approval_date = datetime.now() |
|
244 |
self.save() |
|
245 |
quota_disturbed.send(sender=self, users=self.approved_members) |
|
246 |
#propagate_groupmembers_quota.apply_async( |
|
247 |
# args=[self], eta=self.issue_date) |
|
248 |
#propagate_groupmembers_quota.apply_async( |
|
249 |
# args=[self], eta=self.expiration_date) |
|
250 |
|
|
251 |
def disable(self): |
|
252 |
if self.is_disabled: |
|
253 |
return |
|
254 |
self.approval_date = None |
|
255 |
self.save() |
|
256 |
quota_disturbed.send(sender=self, users=self.approved_members) |
|
257 |
|
|
258 |
def approve_member(self, person): |
|
259 |
m, created = self.membership_set.get_or_create(person=person) |
|
260 |
m.approve() |
|
261 |
|
|
262 |
@property |
|
263 |
def members(self): |
|
264 |
q = self.membership_set.select_related().all() |
|
265 |
return [m.person for m in q] |
|
266 |
|
|
267 |
@property |
|
268 |
def approved_members(self): |
|
269 |
q = self.membership_set.select_related().all() |
|
270 |
return [m.person for m in q if m.is_approved] |
|
271 |
|
|
272 |
@property |
|
273 |
def quota(self): |
|
274 |
d = defaultdict(int) |
|
275 |
for q in self.astakosgroupquota_set.select_related().all(): |
|
276 |
d[q.resource] += q.uplimit or inf |
|
277 |
return d |
|
278 |
|
|
279 |
def add_policy(self, service, resource, uplimit, update=True): |
|
280 |
"""Raises ObjectDoesNotExist, IntegrityError""" |
|
281 |
resource = Resource.objects.get(service__name=service, name=resource) |
|
282 |
if update: |
|
283 |
AstakosGroupQuota.objects.update_or_create( |
|
284 |
group=self, |
|
285 |
resource=resource, |
|
286 |
defaults={'uplimit': uplimit} |
|
287 |
) |
|
288 |
else: |
|
289 |
q = self.astakosgroupquota_set |
|
290 |
q.create(resource=resource, uplimit=uplimit) |
|
291 |
|
|
292 |
@property |
|
293 |
def policies(self): |
|
294 |
return self.astakosgroupquota_set.select_related().all() |
|
295 |
|
|
296 |
@policies.setter |
|
297 |
def policies(self, policies): |
|
298 |
for p in policies: |
|
299 |
service = p.get('service', None) |
|
300 |
resource = p.get('resource', None) |
|
301 |
uplimit = p.get('uplimit', 0) |
|
302 |
update = p.get('update', True) |
|
303 |
self.add_policy(service, resource, uplimit, update) |
|
304 |
|
|
305 |
@property |
|
306 |
def owners(self): |
|
307 |
return self.owner.all() |
|
308 |
|
|
309 |
@property |
|
310 |
def owner_details(self): |
|
311 |
return self.owner.select_related().all() |
|
312 |
|
|
313 |
@owners.setter |
|
314 |
def owners(self, l): |
|
315 |
self.owner = l |
|
316 |
map(self.approve_member, l) |
|
317 |
|
|
318 | 168 |
_default_quota = {} |
319 | 169 |
def get_default_quota(): |
320 | 170 |
global _default_quota |
... | ... | |
403 | 253 |
|
404 | 254 |
uuid = models.CharField(max_length=255, null=True, blank=False, unique=True) |
405 | 255 |
|
406 |
astakos_groups = models.ManyToManyField( |
|
407 |
AstakosGroup, verbose_name=_('agroups'), blank=True, |
|
408 |
help_text=_(astakos_messages.ASTAKOSUSER_GROUPS_HELP), |
|
409 |
through='Membership') |
|
410 |
|
|
411 | 256 |
__has_signed_terms = False |
412 | 257 |
disturbed_quota = models.BooleanField(_('Needs quotaholder syncing'), |
413 | 258 |
default=False, db_index=True) |
414 | 259 |
|
415 | 260 |
objects = AstakosUserManager() |
416 | 261 |
|
417 |
|
|
418 |
owner = models.ManyToManyField( |
|
419 |
AstakosGroup, related_name='owner', null=True) |
|
420 |
|
|
421 | 262 |
def __init__(self, *args, **kwargs): |
422 | 263 |
super(AstakosUser, self).__init__(*args, **kwargs) |
423 | 264 |
self.__has_signed_terms = self.has_signed_terms |
... | ... | |
522 | 363 |
def extended_groups(self): |
523 | 364 |
return self.membership_set.select_related().all() |
524 | 365 |
|
525 |
@extended_groups.setter |
|
526 |
def extended_groups(self, groups): |
|
527 |
#TODO exceptions |
|
528 |
for name in (groups or ()): |
|
529 |
group = AstakosGroup.objects.get(name=name) |
|
530 |
self.membership_set.create(group=group) |
|
531 |
|
|
532 | 366 |
def save(self, update_timestamps=True, **kwargs): |
533 | 367 |
if update_timestamps: |
534 | 368 |
if not self.id: |
... | ... | |
891 | 725 |
return super(AstakosUserAuthProvider, self).save(*args, **kwargs) |
892 | 726 |
|
893 | 727 |
|
894 |
class Membership(models.Model): |
|
895 |
person = models.ForeignKey(AstakosUser) |
|
896 |
group = models.ForeignKey(AstakosGroup) |
|
897 |
date_requested = models.DateField(default=datetime.now(), blank=True) |
|
898 |
date_joined = models.DateField(null=True, db_index=True, blank=True) |
|
899 |
|
|
900 |
class Meta: |
|
901 |
unique_together = ("person", "group") |
|
902 |
|
|
903 |
def save(self, *args, **kwargs): |
|
904 |
if not self.id: |
|
905 |
if not self.group.moderation_enabled: |
|
906 |
self.date_joined = datetime.now() |
|
907 |
super(Membership, self).save(*args, **kwargs) |
|
908 |
|
|
909 |
@property |
|
910 |
def is_approved(self): |
|
911 |
if self.date_joined: |
|
912 |
return True |
|
913 |
return False |
|
914 |
|
|
915 |
def approve(self): |
|
916 |
if self.is_approved: |
|
917 |
return |
|
918 |
if self.group.max_participants: |
|
919 |
assert len(self.group.approved_members) + 1 <= self.group.max_participants, \ |
|
920 |
'Maximum participant number has been reached.' |
|
921 |
self.date_joined = datetime.now() |
|
922 |
self.save() |
|
923 |
quota_disturbed.send(sender=self, users=(self.person,)) |
|
924 |
|
|
925 |
def disapprove(self): |
|
926 |
approved = self.is_approved() |
|
927 |
self.delete() |
|
928 |
if approved: |
|
929 |
quota_disturbed.send(sender=self, users=(self.person,)) |
|
930 |
|
|
931 | 728 |
class ExtendedManager(models.Manager): |
932 | 729 |
def _update_or_create(self, **kwargs): |
933 | 730 |
assert kwargs, \ |
... | ... | |
957 | 754 |
|
958 | 755 |
update_or_create = _update_or_create |
959 | 756 |
|
960 |
class AstakosGroupQuota(models.Model): |
|
961 |
objects = ExtendedManager() |
|
962 |
limit = models.PositiveIntegerField(_('Limit'), null=True) # obsolete field |
|
963 |
uplimit = models.BigIntegerField(_('Up limit'), null=True) |
|
964 |
resource = models.ForeignKey(Resource) |
|
965 |
group = models.ForeignKey(AstakosGroup, blank=True) |
|
966 |
|
|
967 |
class Meta: |
|
968 |
unique_together = ("resource", "group") |
|
969 | 757 |
|
970 | 758 |
class AstakosUserQuota(models.Model): |
971 | 759 |
objects = ExtendedManager() |
... | ... | |
1171 | 959 |
session_key = models.CharField(_('session key'), max_length=40) |
1172 | 960 |
user = models.ForeignKey(AstakosUser, related_name='sessions', null=True) |
1173 | 961 |
|
962 |
|
|
963 |
### PROJECTS ### |
|
964 |
################ |
|
965 |
|
|
1174 | 966 |
class MemberJoinPolicy(models.Model): |
1175 | 967 |
policy = models.CharField(_('Policy'), max_length=255, unique=True, db_index=True) |
1176 | 968 |
description = models.CharField(_('Description'), max_length=80) |
... | ... | |
1185 | 977 |
def __str__(self): |
1186 | 978 |
return self.policy |
1187 | 979 |
|
1188 |
_auto_accept_join = False |
|
1189 |
def get_auto_accept_join(): |
|
1190 |
global _auto_accept_join |
|
1191 |
if _auto_accept_join is not False: |
|
1192 |
return _auto_accept_join |
|
1193 |
try: |
|
1194 |
auto_accept = MemberJoinPolicy.objects.get(policy='auto_accept') |
|
1195 |
except: |
|
1196 |
auto_accept = None |
|
1197 |
_auto_accept_join = auto_accept |
|
1198 |
return auto_accept |
|
1199 |
|
|
1200 |
_closed_join = False |
|
1201 |
def get_closed_join(): |
|
1202 |
global _closed_join |
|
1203 |
if _closed_join is not False: |
|
1204 |
return _closed_join |
|
1205 |
try: |
|
1206 |
closed = MemberJoinPolicy.objects.get(policy='closed') |
|
1207 |
except: |
|
1208 |
closed = None |
|
1209 |
_closed_join = closed |
|
1210 |
return closed |
|
1211 |
|
|
1212 |
_auto_accept_leave = False |
|
1213 |
def get_auto_accept_leave(): |
|
1214 |
global _auto_accept_leave |
|
1215 |
if _auto_accept_leave is not False: |
|
1216 |
return _auto_accept_leave |
|
1217 |
try: |
|
1218 |
auto_accept = MemberLeavePolicy.objects.get(policy='auto_accept') |
|
1219 |
except: |
|
1220 |
auto_accept = None |
|
1221 |
_auto_accept_leave = auto_accept |
|
1222 |
return auto_accept |
|
1223 |
|
|
1224 |
_closed_leave = False |
|
1225 |
def get_closed_leave(): |
|
1226 |
global _closed_leave |
|
1227 |
if _closed_leave is not False: |
|
1228 |
return _closed_leave |
|
1229 |
try: |
|
1230 |
closed = MemberLeavePolicy.objects.get(policy='closed') |
|
1231 |
except: |
|
1232 |
closed = None |
|
1233 |
_closed_leave = closed |
|
1234 |
return closed |
|
1235 |
|
|
1236 |
|
|
1237 |
### PROJECTS ### |
|
1238 |
################ |
|
1239 |
|
|
1240 |
|
|
1241 | 980 |
def synced_model_metaclass(class_name, class_parents, class_attributes): |
1242 | 981 |
|
1243 | 982 |
new_attributes = {} |
... | ... | |
1940 | 1679 |
reason = models.IntegerField() |
1941 | 1680 |
serial = models.BigIntegerField() |
1942 | 1681 |
|
1943 |
|
|
1944 |
def filter_queryset_by_property(q, property): |
|
1945 |
""" |
|
1946 |
Incorporate list comprehension for filtering querysets by property |
|
1947 |
since Queryset.filter() operates on the database level. |
|
1948 |
""" |
|
1949 |
return (p for p in q if getattr(p, property, False)) |
|
1950 |
|
|
1951 |
def get_alive_projects(): |
|
1952 |
return filter_queryset_by_property( |
|
1953 |
Project.objects.all(), |
|
1954 |
'is_alive' |
|
1955 |
) |
|
1956 |
|
|
1957 |
def get_active_projects(): |
|
1958 |
return filter_queryset_by_property( |
|
1959 |
Project.objects.all(), |
|
1960 |
'is_active' |
|
1961 |
) |
|
1962 |
|
|
1963 |
def _create_object(model, **kwargs): |
|
1964 |
o = model.objects.create(**kwargs) |
|
1965 |
o.save() |
|
1966 |
return o |
|
1967 |
|
|
1682 |
### SIGNALS ### |
|
1683 |
################ |
|
1968 | 1684 |
|
1969 | 1685 |
def create_astakos_user(u): |
1970 | 1686 |
try: |
... | ... | |
1993 | 1709 |
create_astakos_user(instance) |
1994 | 1710 |
post_save.connect(user_post_save, sender=User) |
1995 | 1711 |
|
1996 |
|
|
1997 |
# def astakosuser_pre_save(sender, instance, **kwargs): |
|
1998 |
# instance.aquarium_report = False |
|
1999 |
# instance.new = False |
|
2000 |
# try: |
|
2001 |
# db_instance = AstakosUser.objects.get(id=instance.id) |
|
2002 |
# except AstakosUser.DoesNotExist: |
|
2003 |
# # create event |
|
2004 |
# instance.aquarium_report = True |
|
2005 |
# instance.new = True |
|
2006 |
# else: |
|
2007 |
# get = AstakosUser.__getattribute__ |
|
2008 |
# l = filter(lambda f: get(db_instance, f) != get(instance, f), |
|
2009 |
# BILLING_FIELDS) |
|
2010 |
# instance.aquarium_report = True if l else False |
|
2011 |
# pre_save.connect(astakosuser_pre_save, sender=AstakosUser) |
|
2012 |
|
|
2013 |
# def set_default_group(user): |
|
2014 |
# try: |
|
2015 |
# default = AstakosGroup.objects.get(name='default') |
|
2016 |
# Membership( |
|
2017 |
# group=default, person=user, date_joined=datetime.now()).save() |
|
2018 |
# except AstakosGroup.DoesNotExist, e: |
|
2019 |
# logger.exception(e) |
|
2020 |
|
|
1712 |
def astakosuser_pre_save(sender, instance, **kwargs): |
|
1713 |
instance.aquarium_report = False |
|
1714 |
instance.new = False |
|
1715 |
try: |
|
1716 |
db_instance = AstakosUser.objects.get(id=instance.id) |
|
1717 |
except AstakosUser.DoesNotExist: |
|
1718 |
# create event |
|
1719 |
instance.aquarium_report = True |
|
1720 |
instance.new = True |
|
1721 |
else: |
|
1722 |
get = AstakosUser.__getattribute__ |
|
1723 |
l = filter(lambda f: get(db_instance, f) != get(instance, f), |
|
1724 |
BILLING_FIELDS) |
|
1725 |
instance.aquarium_report = True if l else False |
|
1726 |
pre_save.connect(astakosuser_pre_save, sender=AstakosUser) |
|
2021 | 1727 |
|
2022 | 1728 |
def astakosuser_post_save(sender, instance, created, **kwargs): |
2023 |
# if instance.aquarium_report:
|
|
2024 |
# report_user_event(instance, create=instance.new)
|
|
1729 |
if instance.aquarium_report: |
|
1730 |
report_user_event(instance, create=instance.new) |
|
2025 | 1731 |
if not created: |
2026 | 1732 |
return |
2027 |
# set_default_group(instance) |
|
2028 | 1733 |
# TODO handle socket.error & IOError |
2029 | 1734 |
register_users((instance,)) |
2030 | 1735 |
post_save.connect(astakosuser_post_save, sender=AstakosUser) |
... | ... | |
2037 | 1742 |
post_save.connect(resource_post_save, sender=Resource) |
2038 | 1743 |
|
2039 | 1744 |
|
2040 |
# def on_quota_disturbed(sender, users, **kwargs): |
|
2041 |
# # print '>>>', locals() |
|
2042 |
# if not users: |
|
2043 |
# return |
|
2044 |
# send_quota(users) |
|
2045 |
# |
|
2046 |
# quota_disturbed = Signal(providing_args=["users"]) |
|
2047 |
# quota_disturbed.connect(on_quota_disturbed) |
|
2048 |
|
|
2049 |
|
|
2050 |
# def send_quota_disturbed(sender, instance, **kwargs): |
|
2051 |
# users = [] |
|
2052 |
# extend = users.extend |
|
2053 |
# if sender == Membership: |
|
2054 |
# if not instance.group.is_enabled: |
|
2055 |
# return |
|
2056 |
# extend([instance.person]) |
|
2057 |
# elif sender == AstakosUserQuota: |
|
2058 |
# extend([instance.user]) |
|
2059 |
# elif sender == AstakosGroupQuota: |
|
2060 |
# if not instance.group.is_enabled: |
|
2061 |
# return |
|
2062 |
# extend(instance.group.astakosuser_set.all()) |
|
2063 |
# elif sender == AstakosGroup: |
|
2064 |
# if not instance.is_enabled: |
|
2065 |
# return |
|
2066 |
# quota_disturbed.send(sender=sender, users=users) |
|
2067 |
# post_delete.connect(send_quota_disturbed, sender=AstakosGroup) |
|
2068 |
# post_delete.connect(send_quota_disturbed, sender=Membership) |
|
2069 |
# post_save.connect(send_quota_disturbed, sender=AstakosUserQuota) |
|
2070 |
# post_delete.connect(send_quota_disturbed, sender=AstakosUserQuota) |
|
2071 |
# post_save.connect(send_quota_disturbed, sender=AstakosGroupQuota) |
|
2072 |
# post_delete.connect(send_quota_disturbed, sender=AstakosGroupQuota) |
|
2073 |
|
|
2074 |
|
|
2075 | 1745 |
def renew_token(sender, instance, **kwargs): |
2076 | 1746 |
if not instance.auth_token: |
2077 | 1747 |
instance.renew_token() |
Also available in: Unified diff