class BoundaryType(MyModel): owner = CurrentUserField(blank=True, related_name="boundary_type_owner", default=1) modifier = CurrentUserField(blank=True, related_name="boundary_type_modifier", default=1) ispolitical = models.BooleanField("Polical?") istheocratic = models.BooleanField("Theocratic?") isterritory = models.BooleanField("Territory?") name = models.CharField("Name", max_length=128) fcode = models.CharField("Feature Code", max_length=10) title = models.CharField("Title", max_length=128, blank=True) style_id = models.PositiveSmallIntegerField("Style ID", null=True, blank=True) class Meta: db_table = u'of_boundary_types' ordering = ['name'] permissions = (('access_boundaries', 'Access to Boundary Types'), ) def __unicode__(self): return self.name
class Adress(models.Model): class Meta: verbose_name = "Adres" verbose_name_plural = "Adresy" name = models.CharField("Nazwa odbiorcy", max_length=CHAR_FIELD_MAX_LEN) no = models.CharField("Numer domu/mieszkania", max_length=CHAR_FIELD_MAX_LEN) street = models.CharField("Ulica", max_length=CHAR_FIELD_MAX_LEN) city = models.ForeignKey( "Dictionary", verbose_name="Miasto", related_name='+', limit_choices_to={ 'type': 'city', 'active': True }, ) postalcode = models.CharField(verbose_name="Kod pocztowy", max_length=CHAR_FIELD_MAX_LEN) user_changed = CurrentUserField() historical = HistoricalRecords() def __unicode__(self): return "Stree"
class BoundariesRelated(MyModel): owner = CurrentUserField(blank=True, related_name="boundary_related_owner", default=1) modifier = CurrentUserField(blank=True, related_name="boundary_related_modifier", default=1) parent = models.ForeignKey(Boundary, db_column='parent_id', verbose_name="The Area Of", related_name='from_boundary') child = models.ForeignKey(Boundary, db_column='child_id', verbose_name="Includes", related_name='to_boundary') #parent_id = models.ForeignKey(Boundary, db_column = 'parent_id', verbose_name="Related From", related_name='from_boundary') #child_id = models.ForeignKey(Boundary, db_column = 'child_id', verbose_name="Related To", related_name='to_boundary') @property def full_name(self): related_title = u'' related_title = self.parent.__unicode__() if self.parent else u'' related_title += u'/' if related_title else u'' related_title += self.child.__unicode__() if self.child else u'' return related_title @property def number_path(self): related_title = u'' related_title = str(self.parent.number) if self.parent.number else u'' related_title += u'-' if related_title else u'' related_title += str(self.child.number) if self.child.number else u'' return related_title def __unicode__(self): return self.full_name + ' | ' + self.number_path class Meta: #app_label = u'boundaries_related' db_table = u'of_boundaries_related' ordering = ['parent', 'child']
class Uprawnienie(models.Model): class Meta: verbose_name = u"Wydane uprwanienie" verbose_name_plural = u"Rejestr wydanych uprawnień" ordering = ['id'] id = models.AutoField(u"Numer porządkowy", primary_key=True, editable=True) name = models.CharField( u"Imie", max_length=CHAR_FIELD_MAX_LEN, ) surname = models.CharField(u"Nazwisko", max_length=CHAR_FIELD_MAX_LEN) uprawnienie = models.ForeignKey('Dictionary', verbose_name=u"Rodzaj uprawnienia", limit_choices_to={ 'type': 'Uprawnienie', 'active': True }, related_name='+') rozkaz = models.CharField(u"Rozkaz", max_length=CHAR_FIELD_MAX_LEN) date = models.DateField(u"Data przyznania", blank=True, null=True) srodowisko = models.ForeignKey('Dictionary', verbose_name=u"Środowisko", limit_choices_to={ 'type': 'Srodowisko', 'active': True }, related_name='+', blank=True, null=True) druzyna = models.ForeignKey("Dictionary", verbose_name=u"Drużyna", limit_choices_to={ 'type': 'Troop', 'active': True }, related_name="+", blank=True, null=True) user_changed = CurrentUserField() historical = HistoricalRecords() def save(self, force_insert=False, force_update=False, using=None): if self.date is None: self.date = date.today() super(Uprawnienie, self).save(force_insert, force_update, using) def clean(self): if self.srodowisko is None and self.druzyna is None: raise ValidationError(u"Musisz podać albo drużyne albo środowisko")
class Corresponcence(models.Model): class Meta: verbose_name = "Korespondencja przychodząca" verbose_name_plural = "Rejestr korespondencji przychodzącej" permissions = (("can_be_correspondence_owner", u"Może być właścicielem korespondencji"), ) number = models.AutoField(primary_key=True, verbose_name="Numer") # confidential = models.CharField("Tajność", choices=(('j', 'Jawne'), ('t', 'Tajne')), max_length=1, default='j', blank=False, null=False) data = models.DateField( u"Data rejestracji", help_text= u"Nie musisz wypełniać tego pola --- domyślnie będzie to dziś.", editable=True) # type = models.CharField("Typ dokumentu", choices=(('p', u'Przychodzący'), ('w', u'Wychodzący')), max_length=1, default='p', blank=False, null=False) adress = HistoricalForeignKey('Adress', verbose_name='Nadawca') subject = models.TextField(u"Temat wiadomości", blank=False, null=False) institution_no = models.CharField(u"Numer urzędowy", blank=True, null=True, help_text=u"Numer nadany przez nadawcę", max_length=CHAR_FIELD_MAX_LEN) remarks = models.TextField(u"Uwagi", blank=True, null=False) status = models.ForeignKey("Dictionary", related_name="+", limit_choices_to={ "type": 'corr-stat', 'active': True }, verbose_name=u"Status przesyłki") responsible = models.ForeignKey("auth.User", related_name='+', verbose_name=u"Osoba odpowiedzialna", blank=True, null=True) user_changed = CurrentUserField() historical = HistoricalRecords() def save_base(self, raw=False, cls=None, origin=None, force_insert=False, force_update=False, using=None): if self.data is None: self.data = date.today() super(Corresponcence, self).save_base(raw, cls, origin, force_insert, force_update, using)
class Dictionary(models.Model): class Meta: verbose_name = u"Słownik" verbose_name_plural = u"Słowniki" name = models.CharField(max_length=CHAR_FIELD_MAX_LEN, verbose_name="Nazwa") active = models.BooleanField( verbose_name="Aktywny", help_text="Czy dany rekord może być przypisywany do innych obiektów", default=True) type = models.CharField(max_length=CHAR_FIELD_MAX_LEN, choices=DICTIONARY_CHOICES) user_changed = CurrentUserField() def __unicode__(self): return ' '.join(('+' if self.active else '-', self.name, self.type))
class ScoutBook(models.Model): class Meta: verbose_name = u"Ksiżeczka harcerska" verbose_name_plural = u"Rejestr książeczek harcerskich" ordering = ['id'] id = models.AutoField(u"Numer porządkowy", primary_key=True, editable=True) name = models.CharField( u"Imie", max_length=CHAR_FIELD_MAX_LEN, ) surname = models.CharField(u"Nazwisko", max_length=CHAR_FIELD_MAX_LEN) srodowisko = models.ForeignKey('Dictionary', verbose_name=u"Środowisko", limit_choices_to={ 'type': 'Srodowisko', 'active': True }, related_name='+', blank=True, null=True) troop = models.ForeignKey('Dictionary', verbose_name=u"Drużyna", limit_choices_to={ 'type': 'Troop', 'active': True }, related_name='+') book_no = models.CharField(u"Numer książeczki", max_length=CHAR_FIELD_MAX_LEN, unique=True) issue_date = models.DateField(u"Data wydania", blank=True, null=True) user_changed = CurrentUserField() historical = HistoricalRecords() def clean(self): if self.pk is None and self.issue_date is None: self.issue_date = datetime.today()
class AccessRequest(AbstractBaseModel): STATUS_CHOICES = [ ('o', _('open')), # opened by user ('c', _('canceled')), # by user ('v', _('approved')), ('d', _('denied')) ] user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) message = models.TextField(_("message"), max_length=2048, help_text=_('Message for the administrators.'), blank=True) comment = models.TextField(_("Comment"), max_length=2048, blank=True) status = models.CharField(_('status'), max_length=255, choices=STATUS_CHOICES, default='o') last_modified_by_user = CurrentUserField( verbose_name=_('last modified by'), related_name='accessrequest_last_modified_by', on_delete=models.SET_NULL) completed_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=_('completed by'), related_name='accessrequest_completed_by', on_delete=models.SET_NULL) application = models.ForeignKey(Application, blank=True, null=True, on_delete=models.SET_NULL, verbose_name=_('application')) # required field if the user has no organisation organisation = models.ForeignKey(Organisation, blank=True, null=True, on_delete=models.CASCADE) objects = AccessRequestManager() open = OpenAccessRequestManager() def process(self, action=None, user=None): if action in ['cancel', 'verify', 'deny']: getattr(self, action)(user) else: raise ValueError def cancel(self, user): self.status = 'c' self.completed_by_user = user self.save() def verify(self, user): self.status = 'v' self.completed_by_user = user if self.organisation: self.user.set_organisations([self.organisation]) # check if organisation uses user activation validation_period_active = False for organisation in self.user.organisations.all(): if is_validation_period_active(organisation): self.user.valid_until = now() + timedelta( days=settings.SSO_VALIDATION_PERIOD_DAYS) self.user.save() validation_period_active = True if not validation_period_active: self.user.valid_until = None self.user.save() # add default member profile self.user.role_profiles.add(user.get_default_role_profile()) self.user.role_profiles.remove(user.get_default_guest_profile()) self.save() def deny(self, user): self.status = 'd' self.completed_by_user = user self.save() @property def is_open(self): return self.status == 'o' class Meta(AbstractBaseModel.Meta): verbose_name = _('access request') verbose_name_plural = _('access request') def get_absolute_url(self): return reverse('accounts:accessrequest_detail', kwargs={'pk': self.pk})
class Boundary(MyModel): poly = models.PolygonField("Boundary", blank=True) isconfirmed = models.BooleanField("Confirmed?", ) boundary_type = models.ForeignKey(BoundaryType) owner = CurrentUserField(blank=True, related_name="nam_owner", default=1) modifier = CurrentUserField(blank=True, related_name="nam_modifier", default=1) related = models.ManyToManyField("self", symmetrical=False, null=True, blank=True, through='boundaries.BoundariesRelated', related_name='related_boundary') name = models.CharField("Name", max_length=128, blank=True) number = models.PositiveIntegerField("Number", null=True, blank=True) geo_name_id = models.PositiveIntegerField("GEO Name ID", null=True, blank=True) previousnumber = models.CharField("Previous Number", max_length=32, blank=True) code = models.CharField("Code", max_length=32, blank=True) previouscode = models.CharField("Previous Code", max_length=32, blank=True) postalcode = models.CharField("Zip Code", max_length=32, blank=True) #area_kml = models.DecimalField("Area Kilometers", max_digits=11, decimal_places=7, null=True, blank=True) #population = models.PositiveIntegerField("Population", null=True, blank=True) #population_target_language = models.PositiveIntegerField("English Population", null=True, blank=True) notes = models.TextField("Notes", blank=True) objects = models.GeoManager() #helper functions #b = Boundary.objects.all()[0] #pt = b.pt_from_long_lat(-84.1453933304581, 9.97895563839969) #b.contains(pt) def pt_from_long_lat(self, long, lat): from django.contrib.gis.geos import fromstr return fromstr("POINT(%s %s)" % (long, lat)) def contains(self, pt): return self.poly.contains(pt) # http://nemo.seaports2100.org/doku.php/tutorials/sebastian/geomysql # input - KML Polygon (well-formatted) def kml2poly(self, kml_str): # Begin MySQL Polygon output output = 'POLYGON(' # Import XML parser from xml.dom.minidom import parseString # Parse KML kml_str i = parseString(kml_str) # Get outer rings coordinates outercoords = i.getElementsByTagName( "outerBoundaryIs")[0].getElementsByTagName( "coordinates")[0].firstChild.nodeValue.strip() # Start outer ring output output += '(' # For each point in coordinates, add to output for pt in outercoords.split(' '): lon, lat, elev = pt.split(',') output += lon + " " + lat + "," # Strip last comma from output and close outer ring output = output[:-1] + ")" # Get number of inner rings irings = len(i.getElementsByTagName("innerBoundaryIs")) # For each inner ring, add to output for n in range(irings): # Get rind coordinates innercoords = i.getElementsByTagName( "innerBoundaryIs")[n].getElementsByTagName( "coordinates")[0].firstChild.nodeValue.strip() # Start output output += ",(" # For each point in coordinates, add to output for pt in outercoords.split(' '): lon, lat, elev = pt.split(',') output += lon + " " + lat + "," # Strip last comma from output and close ring output = output[:-1] + ")" # End Polygon output output += ')' # Return formatted MySQL Polygon return output #Load poly from kml string: #'<Polygon><outerBoundaryIs><LinearRing><coordinates>-84.1453933305,9.9789556384,0 -84.1436421837,9.97173599811,0 -84.1367912059,9.96863308888,0 -84.1352551122,9.97121372626,0 -84.135777384,9.97176671998,0 -84.1358081059,9.97228899183,0 -84.1338111841,9.97342570116,0 -84.1351015028,9.97708160411,0 -84.1324901436,9.98294948196,0 -84.1326437529,9.98301092571,0 -84.134087681,9.98172060702,0 -84.1369448152,9.98150555391,0 -84.1379586371,9.98110616955,0 -84.138450187,9.98273442885,0 -84.1406007182,9.98341031007,0 -84.1416759838,9.98193566014,0 -84.1453933305,9.9789556384,0</coordinates></LinearRing></outerBoundaryIs></Polygon>' def set_poly_from_kml_str(self, kml_str): self.poly = self.kml2poly(kml_str) # a start for creating links to where this boundary may reside/be contained within def geo_tag(self): center_pt = self.center_pt bscontains = Boundary.objects.exclude(boundary_type__id=5).filter( poly__contains=center_pt) for b in bscontains: print b @property def coords(self): return self.poly.coords if self.poly else None @property def boundary(self): return self.poly.boundary if self.poly else None @property def kml(self): return self.poly.kml if self.poly else None @property def center_pt(self): return self.poly.centroid if self.poly else None @property def full_name(self): ret = u'' if self.boundary_type: ret = self.boundary_type.title ret += u'-' if ret else u'' if self.name: ret += self.name return ret @property def number_path(self): related_title = u'' related_title = str(self.number) if self.number else u'' return related_title class Meta: #app_label = u'boundaries' db_table = u'of_boundaries' # db_table = u'of_boundaries_test' #unique_together = ("boundary_type", "name", "number", "code"), verbose_name_plural = "boundaries" permissions = (('access_boundaries', 'Access to Boundaries'), ) #def get_absolute_url(self): #return "/boundary/%i/" % self.id def type(self): return u'boundary' def __unicode__(self): return self.full_name + ' | ' + self.number_path + ' : ' + str(self.id)
class Place(MyModel): confirmed = models.BooleanField("Confirmed?", ) territoryno = models.CharField("Territory No", max_length=6, null=True, blank=True, db_index=True, default="4-1-2") sortno = models.PositiveIntegerField("Sort No", null=True, default=0) blockno = models.CharField("Block No", max_length=32, null=True, blank=True) pointno = models.PositiveIntegerField("Point No", null=True, blank=True) #routemarkernoafter = models.PositiveIntegerField("Route Marker No After No", null=True, blank=True) routemarkernoafter = models.PositiveIntegerField( "Route Marker No After No", default=0) markerno = models.PositiveIntegerField("Marker No", default=0, db_index=True) tonext = models.TextField("Directions to Next", null=True, blank=True) houseno = models.CharField("House No", max_length=32, null=True, blank=True) persons = models.TextField("Persons", null=True, blank=True) interestlevel = models.IntegerField("Interest Level", null=True, blank=True) actions = models.TextField("Actions", null=True, blank=True) notes = models.TextField("Notes", null=True, blank=True) description = models.CharField("Description", max_length=255, null=True, blank=True) languages = models.CharField( "Languages", max_length=255, null=True, blank=True, default= "e:English\ns:Spanish\nch:Chinese\nf:French\ni:Italian\nx:German\n?:Other" ) name = models.CharField("Name of Place", max_length=128, null=True, blank=True) phonenos = models.TextField("Telephone Numbers", null=True, blank=True) emails = models.TextField("EMail Addresses", null=True, blank=True) placetype_id = models.IntegerField("Place Type ID", null=True, blank=True) sourcetype = models.CharField("Source Type", max_length=16, null=True, blank=True) source_id = models.IntegerField("Source ID", null=True, blank=True) geocoded = models.BooleanField("GeoCoded?", default=True) multiunit = models.BooleanField("MultiUnit?", ) residential = models.BooleanField("Residential?", default=True) deleted = models.BooleanField("Deleted?", db_index=True) googlemapurl = models.CharField("Google Map URL", max_length=255, null=True, blank=True) point = models.PointField("LatLng", default='POINT(0 0)') owner = CurrentUserField(blank=True, related_name="flt_place_owner", default=1) modifier = CurrentUserField(blank=True, related_name="flt_place_modifier", default=1) provinceno = models.PositiveIntegerField("Province No", null=True, blank=True) cantonno = models.PositiveIntegerField("Canton No", null=True, blank=True) districtno = models.PositiveIntegerField("District No", null=True, blank=True) directions = models.CharField("Directions", max_length=255, null=True, blank=True) districtname = models.CharField("District Name", max_length=32, null=True, blank=True) number = models.PositiveIntegerField("Number", null=True, blank=True) geo_name_id = models.PositiveIntegerField("GEO Name ID", null=True, blank=True) religiousaffiliation = models.CharField("Religious Affiliation", max_length=32, null=True, blank=True) postalcode = models.CharField("Zip Code", max_length=32, null=True, blank=True) noteshtml = models.TextField("Notes HTML", null=True, blank=True) objects = models.GeoManager() #p1 = Place.objects.get(id=3006) #p2 = Place.objects.get(id=3007) #p1.calcDistanceSquare(p2) def calcDistanceSquare(self, place): """calc distance squared to a place""" return (self.point[0] - place.point[0])**2 + (self.point[1] - place.point[1])**2 # http://code.activestate.com/recipes/576779-calculating-distance-between-two-geographic-points/ # http://stackoverflow.com/questions/4913349/haversine-formula-in-python-bearing-and-distance-between-two-gps-points def calcDistance(self, place): import math lat1 = self.point[0] lon1 = self.point[1] lat2 = place.point[0] lon2 = place.point[1] radius = 6371 # km dlat = math.radians(lat2 - lat1) dlon = math.radians(lon2 - lon1) a = math.sin(dlat/2) * math.sin(dlat/2) + math.cos(math.radians(lat1)) \ * math.cos(math.radians(lat2)) * math.sin(dlon/2) * math.sin(dlon/2) c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) d = radius * c return d #p1 = Place.objects.get(id=2950) #p1.findClosestPlace('4-1-2') #print p1.findClosestPlace('4-1-2') def findClosestPlace(self, markernoGreaterThan=0): """find closest place excluding self. Must be geocoded.""" from django.db.models import Q minDistance = 999999999999 # better way? places = Place.objects.filter( Q(markerno=0) | Q(markerno__gt=markernoGreaterThan), territoryno=self.territoryno).filter(geocoded=True).exclude( deleted=True) if not places: return None if self.id: places = places.exclude(id=self.id) # are there any if len(places) == 1: return places[0] closestPlace = None for place in places: distance = self.calcDistanceSquare(place) if distance < minDistance: minDistance = distance closestPlace = place return closestPlace # p1 = Place.objects.get(id=2957); p2 = p1.adjoiningPlace('before'); print p1.calcDirection(p2) # http://hoegners.de/Maxi/geo/geo.py # http://www.platoscave.net/blog/2009/oct/5/calculate-distance-latitude-longitude-python/ # http://rosettacode.org/wiki/Box_the_compass#Python # http://www.movable-type.co.uk/scripts/latlong.html def calcDirection(self, place): from math import * direction_names = [ "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW" ] directions_num = len(direction_names) directions_step = 360. / directions_num lat1 = self.point[0] lon1 = self.point[1] lat2 = place.point[0] lon2 = place.point[1] dLon = lon2 - lon1 y = sin(dLon) * cos(lat2) x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon) index = int(round(degrees(atan2(y, x)) / directions_step)) index %= directions_num return direction_names[index] # p1 = Place.objects.get(id=2957) # p1.adjoiningPlace() # p1.adjoiningPlace('before') def adjoiningPlace(self, adjoin='after'): """return place adjoining before or after within territory""" markerno = self.markerno adjoiningMarkerno = self.markerno + 1 if adjoin == 'after' else self.markerno - 1 places = Place.objects.filter(territoryno=self.territoryno).filter( markerno=adjoiningMarkerno) return places[0] if places else None def mostInLineWith(self, closestPlace, prevPlace, nextPlace): """Return the Place that is most in line with""" if mapUtils.mostInLineWith(self.point, closestPlace.point, prevPlace.point, nextPlace.point) == 'prevPt': return prevPlace else: return nextPlace def ParseDetails(self): from django.contrib.gis.geos import Point latitude = 0.0 longitude = 0.0 if self.googlemapurl: import re # look for ll=9.999107,-84.106216 like string for lat/long # http://maps.google.com/maps?hl=en&ll=10.001479,-84.134258&spn=0.001751,0.002682&t=h&vpsrc=6&z=19 reobj = re.compile( r"[&;\?]ll=(?P<latitude>[\-0-9.]+),(?P<longitude>[\-0-9.]+)") match = reobj.search(self.googlemapurl) if match: latitude = float(match.group("latitude")) longitude = float(match.group("longitude")) from django.contrib.gis.geos import Point self.point = Point(latitude, longitude) self.point = Point(latitude, longitude) self.googlemapurl = None self.isgeocoded = True if (self.point.y and self.point.x) else False @property def full_name(self): ret = u'p' ret += str(self.id) if self.territoryno: ret += ' t' ret += self.territoryno if self.markerno: ret += ' m' ret += str(self.markerno) return ret class Meta: db_table = u'of_places' #unique_together = ("boundary_type", "name", "number", "code"), verbose_name_plural = "places" permissions = (('access_places', 'Access to Places'), ) def save(self, *args, **kw): self.ParseDetails() self.geocoded = True if (self.point.y and self.point.x) else False # gonna try ignoring new markers to later assign number if self.id: # In order to handle renumbering of markerno's, I need to see if markno has changed. # If so, handle renumbering # kw['handleMarkernos'] is set in test to quickly clone Places. Do not want to process markernos if not 'handleMarkernos' in kw or kw['handleMarkernos']: isnew = True if not self.id else False placeMarkernos = PlaceMarkernos(self, isnew=isnew) placeMarkernos.handleChange() if 'handleMarkernos' in kw: del (kw['handleMarkernos']) # was just temp super(Place, self).save(*args, **kw) def delete(self, *args, **kw): # If so, handle renumbering # kw['handleMarkernos'] is set in test to quickly clone Places. Do not want to process markernos if not 'handleMarkernos' in kw or kw['handleMarkernos']: placeMarkernos = PlaceMarkernos(self, isdeleted=True) placeMarkernos.handleChange() if 'handleMarkernos' in kw: del (kw['handleMarkernos']) # was just temp super(Place, self).delete(*args, **kw) def type(self): return u'place' def __unicode__(self): return self.full_name
class RegistrationProfile(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, verbose_name=_('user')) last_modified = models.DateTimeField(_('last modified'), auto_now=True) last_modified_by_user = CurrentUserField( verbose_name=_('last modified by'), related_name='registrationprofile_last_modified_by', on_delete=models.SET_NULL) date_registered = models.DateTimeField(_('date registered'), default=timezone.now) is_validated = models.BooleanField( _('validated'), default=False, db_index=True, help_text=_( 'Designates whether this profile was already validated by the user.' )) about_me = models.TextField(_('about_me'), blank=True, max_length=1024) known_person1_first_name = models.CharField( _("first name of a known person"), max_length=100, blank=True) known_person1_last_name = models.CharField( _("last name of a known person"), max_length=100, blank=True) known_person2_first_name = models.CharField( _("first name of a another known person"), max_length=100, blank=True) known_person2_last_name = models.CharField( _("last name of a another known person"), max_length=100, blank=True) check_back = models.BooleanField( _('check back'), default=False, help_text=_('Designates if there are open questions to check.')) is_access_denied = models.BooleanField( _('access denied'), default=False, db_index=True, help_text=_('Designates if access is denied to the user.')) comment = models.TextField(_("Comment"), max_length=2048, blank=True) objects = RegistrationManager() class Meta: verbose_name = _('registration profile') verbose_name_plural = _('registration profiles') def __str__(self): return '%s' % self.user def token_valid(self): token_expiration_date = RegistrationManager.token_expiration_date() return bool(self.date_registered > token_expiration_date) token_valid.boolean = True def activation_valid(self): activation_expiration_date = RegistrationManager.activation_expiration_date( ) return self.user.is_active or (self.date_registered > activation_expiration_date) activation_valid.boolean = True def process(self, action=None, user=None): notes = [] if action == 'activate': self.user.is_active = True self.is_access_denied = False self.check_back = False if not self.user.has_usable_password(): self.user.set_password(get_random_string(40)) self.save() self.user.save() notes.append('activated') elif action == 'deny': self.is_access_denied = True self.user.is_active = False self.save() self.user.save() notes.append('denied') elif action == 'check_back': self.check_back = True self.save() notes.append('check back required') UserNote.objects.create_note(user=self.user, created_by_user=user, notes=notes)
class User(AbstractBaseUser, PermissionsMixin): MAX_PICTURE_SIZE = settings.SSO_USER_MAX_PICTURE_SIZE PICTURE_WIDTH = settings.SSO_USER_PICTURE_WIDTH PICTURE_HEIGHT = settings.SSO_USER_PICTURE_HEIGHT GENDER_CHOICES = [('m', _('male')), ('f', _('female'))] username_validator = UnicodeUsernameValidator() username = models.CharField( _('username'), max_length=150, unique=True, help_text= _('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.' ), validators=[username_validator], error_messages={ 'unique': _("A user with that username already exists.") }) first_name = models.CharField(_('first name'), max_length=150, blank=True) last_name = models.CharField(_('last name'), max_length=150, blank=True) is_staff = models.BooleanField( _('staff status'), default=False, help_text=_( 'Designates whether the user can log into this admin site.')) is_active = models.BooleanField( _('active'), default=True, db_index=True, help_text= _('Designates whether this user should be treated as active. Unselect this instead of deleting accounts.' )) date_joined = models.DateTimeField(_('date joined'), default=timezone.now) uuid = models.UUIDField(unique=True, default=uuid.uuid4, editable=True) organisations = models.ManyToManyField( Organisation, verbose_name=_('organisations'), through=Membership, blank=(not settings.SSO_ORGANISATION_REQUIRED)) admin_regions = models.ManyToManyField(AdminRegion, verbose_name=_('admin regions'), blank=True) admin_organisation_countries = models.ManyToManyField( OrganisationCountry, verbose_name=_('admin countries'), blank=True) admin_associations = models.ManyToManyField( Association, verbose_name=_('admin associations'), blank=True) app_admin_regions = models.ManyToManyField( AdminRegion, related_name='app_admin_user', verbose_name=_('app admin regions'), blank=True) app_admin_organisation_countries = models.ManyToManyField( OrganisationCountry, related_name='app_admin_user', verbose_name=_('app admin countries'), blank=True) app_admin_associations = models.ManyToManyField( Association, related_name='app_admin_user', verbose_name=_('app admin associations'), blank=True) application_roles = models.ManyToManyField( ApplicationRole, verbose_name=_('application roles'), blank=True) role_profiles = models.ManyToManyField( RoleProfile, verbose_name=_('role profiles'), blank=True, help_text=_('Organises a group of application roles that are usually ' 'assigned together.')) last_modified_by_user = CurrentUserField( verbose_name=_('last modified by'), related_name='+', on_delete=models.SET_NULL) last_modified = models.DateTimeField(_('last modified'), auto_now=True) created_by_user = models.ForeignKey('self', verbose_name=_('created by'), related_name='+', null=True, on_delete=models.SET_NULL) is_center = models.BooleanField( _('organisation'), default=False, help_text=_( 'Designates that this user is representing a organisation and not a ' 'private person.')) is_service = models.BooleanField( _('service'), default=False, help_text=_( 'Designates that this user is representing a service account and ' 'not a person.')) is_subscriber = models.BooleanField( _('subscriber'), default=False, help_text=_( 'Designates whether this user is a newsletter subscriber.')) picture = thumbnail.ImageField(_('picture'), upload_to=generate_filename, blank=True) # , storage=MediaStorage()) gender = models.CharField(_('gender'), max_length=255, choices=GENDER_CHOICES, blank=True) dob = models.DateField(_("date of birth"), blank=True, null=True) homepage = models.URLField(_("homepage"), max_length=512, blank=True) language = models.CharField(_('language'), max_length=254, choices=settings.LANGUAGES, blank=True) timezone = models.CharField(_('timezone'), blank=True, max_length=254) valid_until = models.DateTimeField(_('valid until'), blank=True, null=True) last_ip = models.GenericIPAddressField(_('last ip address'), blank=True, null=True) is_stored_permanently = models.BooleanField( _('store permanently'), help_text=_('Do not delete, even if inactive'), default=False) objects = UserManager() USERNAME_FIELD = 'username' class Meta(AbstractBaseUser.Meta): verbose_name = _('user') verbose_name_plural = _('users') permissions = ( ("read_user", "Can read user data"), ("access_all_users", "Can access all users"), ("app_admin_access_all_users", "Can access all users as App admin"), ) def get_full_name(self): """ Returns the first_name plus the last_name, with a space in between. """ full_name = '%s %s' % (self.first_name, self.last_name) return full_name.strip() def get_short_name(self): """Returns the short name for the user.""" return self.first_name def email_user(self, subject, message, from_email=None, **kwargs): """ Sends an email to this User. """ if self.primary_email() is not None: recipient_list = [self.primary_email().email] if from_email is not None: from_email = force_str(from_email) return send_mail(subject, message, recipient_list, from_email=from_email, **kwargs) else: logger.error('User %s has no primary_email', self.username) return 0 def primary_email(self): # iterate through useremail_set.all because useremail_set is cached # if we use prefetch_related('useremail_set') for user_mail in self.useremail_set.all(): if user_mail.primary: return user_mail return None def create_primary_email(self, email, confirmed=None, delete_others=False): """ make email as the primary email and all other emails non primary if the user email does not exist, it is created the other user emails are marked as not primary or deleted """ email = UserManager.normalize_email(email) user_email = None for l_user_email in self.useremail_set.all(): if email.lower() == l_user_email.email.lower(): l_user_email.primary = True l_user_email.email = email if confirmed is not None: l_user_email.confirmed = confirmed l_user_email.save() user_email = l_user_email else: if delete_others: l_user_email.delete() else: if l_user_email.primary: l_user_email.primary = False l_user_email.save(update_fields=['primary']) if not user_email: kwargs = {'email': email, 'user': self, 'primary': True} if confirmed is not None: kwargs['confirmed'] = confirmed user_email = UserEmail.objects.create(**kwargs) return user_email def confirm_primary_email_if_no_confirmed(self): if not UserEmail.objects.filter(confirmed=True, user=self).exists(): # no confirmed email addresses for this user, then the password reset # must be send to the primary email and we can mark this email as confirmed user_email = UserEmail.objects.get(primary=True, user=self) assert (not user_email.confirmed) user_email.confirmed = True user_email.save(update_fields=['confirmed']) def ensure_single_primary_email(self): ensure_single_primary(self.useremail_set.all()) def update_last_modified(self): self.save(update_fields=['last_modified']) @memoize def get_last_modified_deep(self): """ get the max date of last_modified from user and corresponding address and phones and use _prefetched_objects_cache if available for performance in api lists """ last_modified_list = [self.last_modified] if hasattr(self, '_prefetched_objects_cache') and ( 'useraddress_set' in self._prefetched_objects_cache): last_modified_list += [ obj.last_modified for obj in self.useraddress_set.all() ] else: last_modified_list += self.useraddress_set.values_list( "last_modified", flat=True) if hasattr(self, '_prefetched_objects_cache') and ( 'userphonenumber_set' in self._prefetched_objects_cache): last_modified_list += [ obj.last_modified for obj in self.userphonenumber_set.all() ] else: last_modified_list += self.userphonenumber_set.values_list( "last_modified", flat=True) if hasattr(self, '_prefetched_objects_cache') and ( 'useremail_set' in self._prefetched_objects_cache): last_modified_list += [ obj.last_modified for obj in self.useremail_set.all() ] else: last_modified_list += self.useremail_set.values_list( "last_modified", flat=True) if hasattr(self, '_prefetched_objects_cache') and ( 'userattribute_set' in self._prefetched_objects_cache): last_modified_list += [ obj.last_modified for obj in self.userattribute_set.all() ] else: last_modified_list += self.userattribute_set.values_list( "last_modified", flat=True) last_modified = max(last_modified_list) return last_modified @classmethod def get_primary_or_none(cls, queryset): # iterate through all items, uses the prefetch_related cache for item in queryset: if item.primary: return item return None @classmethod def get_default_role_profile(cls, role_uuid=None): role_profile = RoleProfile.objects.none() if role_uuid is None: role_uuid = settings.SSO_DEFAULT_MEMBER_PROFILE_UUID if role_uuid: try: role_profile = RoleProfile.objects.get(uuid=role_uuid) except ObjectDoesNotExist: pass return role_profile @classmethod def get_default_guest_profile(cls, role_uuid=None): role_profile = None if role_uuid is None: role_uuid = settings.SSO_DEFAULT_GUEST_PROFILE_UUID if role_uuid: try: role_profile = RoleProfile.objects.get(uuid=role_uuid) except ObjectDoesNotExist: pass return role_profile @classmethod def get_default_admin_profile(cls): role_profile = RoleProfile.objects.none() if settings.SSO_DEFAULT_ADMIN_PROFILE_UUID: try: role_profile = RoleProfile.objects.get( uuid=settings.SSO_DEFAULT_ADMIN_PROFILE_UUID) except ObjectDoesNotExist: pass return role_profile @property def primary_address(self): return self.get_primary_or_none(self.useraddress_set.all()) @property def primary_phone(self): return self.get_primary_or_none(self.userphonenumber_set.all()) @memoize def get_apps(self): applicationrole_ids = self.get_applicationrole_ids() return Application.objects.distinct().filter(applicationrole__in=applicationrole_ids, is_active=True). \ order_by('order').prefetch_related('applicationrole_set', 'applicationrole_set__role') def get_global_navigation_urls(self): applicationrole_ids = self.get_applicationrole_ids() return Application.objects.distinct().filter( applicationrole__in=applicationrole_ids, is_active=True, global_navigation=True).order_by('order') def get_roles_by_app(self, app_uuid): applicationrole_ids = self.get_applicationrole_ids() return Role.objects.distinct().filter( applicationrole__in=applicationrole_ids, applicationrole__application__uuid=app_uuid) def get_group_and_role_permissions(self): """ get all permissions the user has through his groups and roles """ applicationrole_ids = self.get_applicationrole_ids() q = Q(group__role__applicationrole__in=applicationrole_ids, group__role__applicationrole__application__uuid=settings. SSO_APP_UUID) | Q(group__user=self) return Permission.objects.distinct().filter(q) @memoize def get_applicationrole_ids(self): return get_applicationrole_ids(self.id) @memoize def get_applicationroles(self): applicationrole_ids = self.get_applicationrole_ids() return ApplicationRole.objects.filter( id__in=applicationrole_ids).select_related() @memoize def get_administrable_application_roles(self): """ get a queryset for the admin """ if self.is_superuser: return ApplicationRole.objects.all().select_related() else: applicationrole_ids = self.get_applicationrole_ids() # all roles the user has, with adequate inheritable flag if self.is_global_user_admin: application_roles = ApplicationRole.objects.filter( id__in=applicationrole_ids, is_inheritable_by_global_admin=True).select_related() elif self.is_user_admin: application_roles = ApplicationRole.objects.filter( id__in=applicationrole_ids, is_inheritable_by_org_admin=True).select_related() else: application_roles = ApplicationRole.objects.none() return application_roles @memoize def get_administrable_role_profiles(self): if self.is_superuser: return RoleProfile.objects.all().prefetch_related( 'application_roles', 'application_roles__role', 'application_roles__application') else: # all role profiles the user has, with adequate inheritable flag if self.is_global_user_admin: role_profiles = self.role_profiles.filter( is_inheritable_by_global_admin=True) elif self.is_user_admin: role_profiles = self.role_profiles.filter( is_inheritable_by_org_admin=True) else: role_profiles = self.role_profiles.none() return role_profiles.prefetch_related( 'application_roles', 'application_roles__role', 'application_roles__application').distinct() @memoize def get_administrable_app_admin_application_roles(self): """ get a queryset for the admin """ if self.is_app_user_admin(): return ApplicationRole.objects.filter( application__applicationadmin__admin=self) else: return ApplicationRole.objects.none() @memoize def get_administrable_app_admin_role_profiles(self): # all role profiles the user has, with adequate inheritable flag role_profiles = self.role_profiles.none() if self.is_app_user_admin(): role_profiles = RoleProfile.objects.filter( roleprofileadmin__admin=self) return role_profiles.prefetch_related( 'application_roles', 'application_roles__role', 'application_roles__application').distinct() @memoize def get_administrable_user_organisations(self): """ return a list of organisations from all the users we have admin rights on """ if self.is_global_user_admin: return Organisation.objects.all().select_related( 'organisation_country__country', 'email', 'association') elif self.is_user_admin: return Organisation.objects.filter( Q(pk__in=self.organisations.all()) | Q(admin_region__in=self.admin_regions.all()) | Q(organisation_country__in=self.admin_organisation_countries.all()) | Q(association__in=self.admin_associations.all())) \ .select_related('organisation_country__country', 'email', 'association').distinct() else: return Organisation.objects.none() @memoize def get_administrable_user_regions(self): """ return a list of regions from all the users we have admin rights on """ if self.is_global_user_admin: return AdminRegion.objects.all() elif self.is_user_admin: return AdminRegion.objects.filter( Q(organisation__in=self.organisations.all()) | Q(pk__in=self.admin_regions.all()) | Q(organisation_country__in=self.admin_organisation_countries.all()) | Q(organisation_country__association__in=self.admin_associations.all())) \ .distinct() else: return AdminRegion.objects.none() @memoize def get_administrable_user_countries(self): """ return a list of countries from all the users we have admin rights on """ if self.is_global_user_admin: return OrganisationCountry.objects.filter( is_active=True).distinct().select_related( 'country', 'association') elif self.is_user_admin: return OrganisationCountry.objects.filter( # for adminregions without a associated country Q(organisation__admin_region__in=self.admin_regions.all()) | Q(organisation__in=self.organisations.all()) | Q(adminregion__in=self.admin_regions.all()) | Q(pk__in=self.admin_organisation_countries.all()) | Q(association__in=self.admin_associations.all())) \ .select_related('country', 'association').distinct() else: return OrganisationCountry.objects.none() @memoize def get_administrable_user_associations(self): """ return a list of associations from all the users we have admin rights on """ if self.is_global_user_admin: return Association.objects.all() else: return self.admin_associations.all() @memoize def get_administrable_app_admin_user_countries(self): """ return a list of countries from all the users we have app admin rights on """ if self.is_global_app_user_admin or self.is_superuser: return OrganisationCountry.objects.all().select_related( 'country', 'association') elif self.is_app_user_admin(): return OrganisationCountry.objects.filter( # for admin regions without a associated country Q(organisation__admin_region__in=self.app_admin_regions.all()) | Q(organisation__in=self.organisations.all()) | Q(adminregion__in=self.app_admin_regions.all()) | Q(pk__in=self.app_admin_organisation_countries.all()) | Q(association__in=self.app_admin_associations.all())). \ select_related('country', 'association').distinct() else: return OrganisationCountry.objects.none() @memoize def get_administrable_app_admin_user_organisations(self): """ return a list of organisations from all the users we have rights to manage app_roles """ if self.is_global_app_user_admin or self.is_superuser: return Organisation.objects.all().select_related( 'organisation_country__country', 'email') elif self.is_app_user_admin(): return Organisation.objects.filter( Q(pk__in=self.organisations.all()) | Q(admin_region__in=self.app_admin_regions.all()) | Q(organisation_country__in=self.app_admin_organisation_countries.all()) | Q(association__in=self.app_admin_associations.all())) \ .select_related('organisation_country__country', 'email').distinct() else: return Organisation.objects.none() @memoize def get_administrable_app_admin_user_regions(self): """ return a list of regions from all the users we have admin rights on """ if self.is_global_app_user_admin or self.is_superuser: return AdminRegion.objects.all() elif self.is_app_user_admin(): return AdminRegion.objects.filter( Q(organisation__in=self.organisations.all()) | Q(pk__in=self.app_admin_regions.all()) | Q(organisation_country__in=self.app_admin_organisation_countries.all()) | Q(organisation_country__association__in=self.app_admin_associations.all())) \ .distinct() else: return AdminRegion.objects.none() @memoize def get_administrable_organisations(self): """ return a list of all organisations the user has admin rights on """ if self.has_perms([ "organisations.change_organisation", "organisations.access_all_organisations" ]): return Organisation.objects.filter( association__is_external=False).prefetch_related( 'organisation_country__country', 'email', 'organisationpicture_set') elif self.has_perm("organisations.change_organisation"): orgs = Organisation.objects.filter( Q(association__is_external=False) & (Q(user=self) | Q(admin_region__user=self) | Q(organisation_country__user=self) | Q(association__user=self))).distinct() return Organisation.objects.filter(id__in=orgs).prefetch_related( 'organisation_country__country', 'email', 'organisationpicture_set') else: return Organisation.objects.none() @memoize def administrable_organisations_exists(self): """ return if the user has admin rights on organisations """ if self.has_perms([ "organisations.change_organisation", "organisations.access_all_organisations" ]): return Organisation.objects.all().exists() elif self.has_perm("organisations.change_organisation"): return Organisation.objects.filter( Q(association__is_external=False) & (Q(user=self) | Q(admin_region__user=self) | Q(organisation_country__user=self) | Q(association__user=self))).exists() else: return False @memoize def get_assignable_associations(self): """ return a list of Associations the user can assign to organisations """ if self.has_perms([ "organisations.change_organisation", "organisations.access_all_organisations" ]): return Association.objects.filter(is_active=True, is_external=False).distinct() elif self.has_perm("organisations.change_organisation"): return Association.objects.filter(user=self, is_active=True, is_external=False) else: return Association.objects.none() @memoize def get_assignable_organisation_countries(self): """ return a list of OrganisationCountry the user can assign to organisations """ if self.has_perms([ "organisations.change_organisation", "organisations.access_all_organisations" ]): return OrganisationCountry.objects.filter( is_active=True, association__is_active=True, association__is_external=False) \ .distinct().prefetch_related('country', 'association') elif self.has_perm("organisations.change_organisation"): return OrganisationCountry.objects.filter( Q(is_active=True, association__is_active=True, association__is_external=False) & (Q(user=self) | Q(association__user=self))).prefetch_related( 'country', 'association') else: return OrganisationCountry.objects.none() @memoize def get_assignable_organisation_regions(self): """ return a list of regions the user can assign to organisations """ if self.has_perms([ "organisations.change_organisation", "organisations.access_all_organisations" ]): return AdminRegion.active_objects.filter( is_active=True, organisation_country__is_active=True, organisation_country__association__is_active=True, organisation_country__association__is_external=False, ) elif self.has_perm("organisations.change_organisation"): return AdminRegion.active_objects.filter( Q(is_active=True, organisation_country__is_active=True, organisation_country__association__is_active=True, organisation_country__association__is_external=False) & (Q(user=self) | Q(organisation_country__user=self) | Q( organisation_country__association__user=self))).distinct() else: return AdminRegion.objects.none() @memoize def get_administrable_regions(self): """ return a list of all admin_regions the user has admin rights on """ if self.has_perms([ "organisations.change_adminregion", "organisations.access_all_organisations" ]): return AdminRegion.objects.filter( organisation_country__association__is_external=False) elif self.has_perm("organisations.change_adminregion"): return AdminRegion.objects.filter( Q(organisation_country__association__is_external=False) & (Q(user=self) | Q(organisation_country__user=self) | Q( organisation_country__association__user=self))).distinct() else: return AdminRegion.objects.none() @memoize def get_administrable_region_countries(self): """ return a list of countries from the administrable regions the user has """ if self.has_perms([ "organisations.change_adminregion", "organisations.access_all_organisations" ]): return OrganisationCountry.objects.filter(association__is_external=False) \ .distinct().prefetch_related('country', 'association') elif self.has_perm("organisations.change_adminregion"): return OrganisationCountry.objects.filter( Q(association__is_external=False) & (Q(adminregion__user=self) | Q(user=self) | Q(association__user=self))).distinct().prefetch_related( 'country', 'association') else: return OrganisationCountry.objects.none() @memoize def get_administrable_countries(self): """ return a list of countries the user has admin rights on """ if self.has_perms([ "organisations.change_organisationcountry", "organisations.access_all_organisations" ]): return OrganisationCountry.objects.filter(association__is_external=False) \ .distinct().prefetch_related('country', 'association') elif self.has_perm("organisations.change_organisationcountry"): return OrganisationCountry.objects.filter( Q(association__is_external=False) & (Q(user=self) | Q(association__user=self))).prefetch_related( 'country', 'association') else: return OrganisationCountry.objects.none() @memoize def get_administrable_associations(self): """ return a list of associations the user has admin rights on """ if self.is_superuser: return Association.objects.all() elif self.has_perm("organisations.change_association"): return Association.objects.filter(user=self) else: return Association.objects.none() @memoize def get_count_of_registrationprofiles(self): qs = RegistrationProfile.objects.get_not_expired().filter( is_access_denied=False, user__is_active=False, is_validated=True, check_back=False, user__last_login__isnull=True) return RegistrationProfile.objects.filter_administrable_registrationprofiles( self, qs).count() @memoize def get_count_of_organisationchanges(self): organisationchanges = OrganisationChange.open.all() return self.filter_administrable_organisationchanges( organisationchanges).count() @memoize def get_count_of_extend_access(self): access_requests = AccessRequest.open.all() return self.filter_administrable_access_requests( access_requests).count() def filter_administrable_access_requests(self, qs): # filter the access_request for who the authenticated user has access to if self.is_superuser: pass elif self.is_global_user_admin: qs = qs.filter(user__is_superuser=False) elif self.is_user_admin: organisations = self.get_administrable_user_organisations() q = Q(user__is_superuser=False) & Q(user__is_service=False) q &= (Q(user__organisations__in=organisations) | Q(organisation__in=organisations)) qs = qs.filter(q).distinct() else: qs = AccessRequest.objects.none() return qs def filter_administrable_organisationchanges(self, qs): # filter the organisationchanges for who the authenticated user has access to if self.is_superuser: pass elif self.is_global_user_admin: qs = qs.filter(user__is_superuser=False) elif self.is_user_admin: organisations = self.get_administrable_user_organisations() q = Q(user__is_superuser=False) & Q(organisation__in=organisations) qs = qs.filter(q).distinct() else: qs = OrganisationChange.objects.none() return qs def filter_administrable_users(self, qs): # filter the users for who the authenticated user has admin rights if self.is_superuser: pass elif self.is_global_user_admin: qs = qs.filter(is_superuser=False, is_service=False) elif self.is_user_admin: organisations = self.get_administrable_user_organisations() q = Q(is_superuser=False) & Q(is_service=False) & Q( organisations__in=organisations) qs = qs.filter(q).distinct() else: qs = User.objects.none() return qs def filter_administrable_user_emails(self, qs): # filter the users for who the authenticated user has admin rights if self.is_superuser: pass elif self.is_global_user_admin: qs = qs.filter(user__is_superuser=False, user__is_service=False) elif self.is_user_admin: organisations = self.get_administrable_user_organisations() q = Q(user__is_superuser=False) & Q(user__is_service=False) & Q( user__organisations__in=organisations) qs = qs.filter(q).distinct() else: qs = qs.none() return qs def filter_administrable_app_admin_users(self, qs): # filter the users for who the authenticated user can manage app_roles if self.is_global_app_user_admin: qs = qs.filter(is_superuser=False, is_service=False) elif self.is_app_user_admin(): organisations = self.get_administrable_app_admin_user_organisations( ) q = Q(is_superuser=False) & Q(is_service=False) & Q( organisations__in=organisations) qs = qs.filter(q).distinct() else: qs = User.objects.none() return qs def filter_administrable_apps(self, qs): # filter the apps for who the authenticated user has admin rights if self.is_superuser: pass elif self.is_global_app_admin: pass elif self.has_perms(["accounts.view_application"]): qs = qs.filter(applicationadmin__admin=self) else: qs = qs.none() return qs @property def is_guest(self): # iterate over all profiles does not makes a new DB query # when prefetch_related('role_profiles') is used # otherwise self.role_profiles.filter(uuid=settings.SSO_DEFAULT_MEMBER_PROFILE_UUID).exists() # would be better for profile in self.role_profiles.all(): if profile.uuid != settings.SSO_DEFAULT_GUEST_PROFILE_UUID: return False for _ in self.application_roles.all(): return False return True @property def is_global_user_admin(self): # can access user data: name, email, center and roles for all users return self.is_user_admin and self.has_perm( "accounts.access_all_users") @property def is_user_admin(self): # can access user data: name, email, center and roles return self.has_perms([ "accounts.read_user" ]) # is used also by the api for read_only access @property def is_global_app_user_admin(self): return self.is_app_user_admin() and self.has_perm( "accounts.app_admin_access_all_users") @memoize def is_app_user_admin(self): return self.applicationadmin_set.exists( ) or self.roleprofileadmin_set.exists() @property def is_global_app_admin(self): return self.has_perms( ["accounts.view_application", "accounts.access_all_applications"]) @memoize def is_app_admin(self): return self.applicationadmin_set.exists() and self.has_perms( ["accounts.view_application"]) @property def is_global_organisation_admin(self): return self.is_organisation_admin and self.has_perms( ["organisations.access_all_organisations"]) @property def is_organisation_admin(self): return self.has_perm("organisations.change_organisation") @memoize def has_organisation(self, uuid): return Organisation.objects.filter( Q(uuid=uuid, association__is_external=False) & (Q(user=self) | Q(admin_region__user=self) | Q(organisation_country__user=self) | Q(association__user=self))).exists() @memoize def has_region(self, uuid): return AdminRegion.objects.filter( Q(uuid=uuid, organisation_country__association__is_external=False) & (Q(user=self) | Q(organisation_country__user=self) | Q(organisation_country__association__user=self))).exists() @memoize def has_country(self, uuid): return OrganisationCountry.objects.filter( Q(uuid=uuid, association__is_external=False) & (Q(user=self) | Q(association__user=self))).exists() def has_user_access_and_perm(self, uuid, perm): """ Check if the user is an admin of the user with uuid and has the permission """ return self.has_perm(perm) and self.has_user_access(uuid) def has_user_access(self, uuid): """ Check if the user is an admin of the user with uuid """ if self.is_superuser: return True elif self.has_perm("accounts.access_all_users"): user = User.objects.get(uuid=uuid) return not user.is_superuser and not user.is_service else: return User.objects.filter( Q(uuid=uuid, is_superuser=False, is_service=False) & (Q(organisations__user=self) | Q(organisations__admin_region__user=self) | Q(organisations__organisation_country__user=self) | Q(organisations__association__user=self))).exists() def has_access_request_access(self, access_request): """ Check if the user is an admin of organisation the user with uuid or if the user is an admin of the organisation in the AccessRequest """ if access_request.organisation: return self.has_organisation_user_access( access_request.organisation.uuid) else: return self.has_user_access(access_request.user.uuid) def has_app_admin_user_access(self, uuid): """ Check if the user is an admin of the user with uuid """ if self.is_superuser: return True if self.is_global_app_user_admin: user = User.objects.get(uuid=uuid) return not user.is_superuser and not user.is_service else: return User.objects.filter( Q(uuid=uuid, is_superuser=False, is_service=False) & (Q(organisations__user=self) | Q(organisations__admin_region__app_admin_user=self) | Q(organisations__organisation_country__app_admin_user=self) | Q(organisations__association__app_admin_user=self))).exists( ) def has_organisation_user_access(self, uuid): # used in sso_xxx_theme if self.has_perm("accounts.access_all_users"): return True else: return self.has_organisation(uuid) def has_organisation_access_and_perm(self, uuid, perm): return self.has_perm(perm) and self.has_organisation_access(uuid) def has_organisation_access(self, uuid): if self.has_perm("organisations.access_all_organisations"): return Organisation.objects.filter( uuid=uuid, association__is_external=False).exists() else: return self.has_organisation(uuid) def has_region_access(self, uuid): if self.has_perm("organisations.access_all_organisations"): return AdminRegion.objects.filter( uuid=uuid, organisation_country__association__is_external=False).exists() else: return self.has_region(uuid) def has_country_access(self, uuid): if self.has_perm("organisations.access_all_organisations"): return OrganisationCountry.objects.filter( uuid=uuid, association__is_external=False).exists() else: return self.has_country(uuid) @property def is_groupemail_admin(self): if self.has_perm('emails.change_groupemail' ) or GroupEmailManager.objects.filter( manager=self).exists(): return True else: return False def has_groupemail_access(self, uuid): if self.has_perm('emails.change_groupemail' ) or GroupEmailManager.objects.filter( group_email__uuid=uuid, manager=self).exists(): return True else: return False def has_app_access(self, uuid): if self.is_global_app_admin: return True else: return ApplicationAdmin.objects.filter(application__uuid=uuid, admin=self).exists() @property def is_complete(self): if self.first_name and self.last_name: return True else: return False @property def is_verified(self): if hasattr(self, 'otp_device'): return self.otp_device is not None return False def add_default_roles(self): app_roles = [] role_profiles = [self.get_default_role_profile()] # enable brand specific modification default_roles.send_robust(sender=self.__class__, user=self, app_roles=app_roles, role_profiles=role_profiles) self.add_roles(app_roles) for role_profile in role_profiles: self.role_profiles.add(role_profile) self.update_last_modified() def add_roles(self, app_roles_dict_array): # get or create Roles for app_roles_dict_item in app_roles_dict_array: roles = [] for roles_name in app_roles_dict_item['roles']: roles += [Role.objects.get_or_create(name=roles_name)[0]] app_roles_dict_item['roles'] = roles for app_roles_dict_item in app_roles_dict_array: try: application = Application.objects.get( uuid=app_roles_dict_item['uuid']) app_roles = [] for role in app_roles_dict_item['roles']: app_roles += [ ApplicationRole.objects.get_or_create( application=application, role=role)[0] ] self.application_roles.add(*app_roles) except ObjectDoesNotExist: logger.warning("Application %s does not exist" % app_roles_dict_item['uuid']) except IntegrityError as e: # programming error? logger.exception(e) def set_organisations(self, organisations): # Ensure last_modified will be updated in all cases the user changes the organisation # Force evaluation of `organisations` in case it's a queryset whose value # could be affected by `manager.clear()`. Refs #19816. organisations = tuple(organisations) self.organisations.clear() self.organisations.through.objects.bulk_create([ self.organisations.through(**{ 'user_id': self.id, 'organisation_id': organisation.id, }) for organisation in organisations ]) ensure_single_primary( self.organisations.through.objects.filter(user_id=self.id)) def add_organisation(self, organisation, primary=False): # Ensure last_modified will be updated in all cases the user changes the organisation self.organisations.through.objects.create( **{ 'user_id': self.id, 'organisation_id': organisation.id, 'primary': primary }) ensure_single_primary( self.organisations.through.objects.filter(user_id=self.id)) def remove_organisation_related_permissions( self, organisation_related_application_roles=None, organisation_related_role_profiles=None): if organisation_related_application_roles is None: organisation_related_application_roles = ApplicationRole.objects.filter( is_organisation_related=True) if organisation_related_role_profiles is None: organisation_related_role_profiles = RoleProfile.objects.filter( is_organisation_related=True) self.application_roles.remove( *list(organisation_related_application_roles)) self.role_profiles.remove(*list(organisation_related_role_profiles))
class ENNote(MyModel): title = models.CharField("Title", max_length=1024) author = models.CharField("Author", max_length=64, null=True, blank=True) owner = CurrentUserField(blank=True, related_name="flt_evernote_owner", default=1) modifier = CurrentUserField(blank=True, related_name="flt_evernote_modifier", default=1) point = models.PointField("LatLng", default='POINT(0 0)') active = models.BooleanField("Active?", default=False) geocoded = models.BooleanField("GeoCoded?", default=False) guid = models.CharField("GUID", max_length=64, db_index=True) notebookGuid = models.CharField("Notebook GUID", max_length=64) notebookName = models.CharField("Notebook Name", max_length=64) #ll = models.PointField("LongLat", default='POINT(-84.145393330458063 9.9789556383996896)') latitude = models.FloatField("Latitude", null=True, blank=True) longitude = models.FloatField("Longitude", null=True, blank=True) altitude = models.FloatField("Altitude", null=True, blank=True) content = models.TextField("Content", null=True, blank=True) encreated = models.DateTimeField("EN Created") enupdated = models.DateTimeField("EN Updated", null=True, blank=True) endeleted = models.DateTimeField("EN Deleted", null=True, blank=True) updateSequenceNum = models.IntegerField("Style ID", null=True, blank=True) objects = models.GeoManager() def __unicode__(self): return self.title def ParseDetails(self): import re #import html2text # pip install html2text enml = self.content #contenttxt = html2text.html2text(enml.decode('us-ascii','ignore')).decode('utf-8','replace') contenttxt = enml # look for ll=9.999107,-84.106216 like string for lat/long reobj = re.compile( r"[&;]ll=(?P<latitude>[\-0-9.]+),(?P<longitude>[\-0-9.]+)") match = reobj.search(contenttxt) if match: self.latitude = float(match.group("latitude")) self.longitude = float(match.group("longitude")) # look for _LWE like string for author # set author based on initials if possible reobj = re.compile(r"(^|\s|>)_?(?P<initials>[A-Z]{3})\s") match = reobj.search(contenttxt) if match: initials = match.group("initials") from note import getpubs pubs = getpubs() if initials in pubs: self.author = pubs[initials] + (" (_%s)" % initials) if self.latitude and self.longitude: from django.contrib.gis.geos import Point self.point = Point(self.latitude, self.longitude) def UpdateFromEN(self, note, cn): import datetime import re notebookName = cn.notebookName self.enupdated = datetime.datetime.fromtimestamp( note.updated / 1000).strftime("%Y-%m-%d %H:%M:%S") self.encreated = datetime.datetime.fromtimestamp( note.created / 1000).strftime("%Y-%m-%d %H:%M:%S") self.guid = note.guid self.title = note.title self.content = note.content self.notebookGuid = note.notebookGuid self.notebookName = notebookName self.active = note.active self.updateSequenceNum = note.updateSequenceNum if note.attributes.latitude: self.latitude = note.attributes.latitude self.longitude = note.attributes.longitude if note.attributes.altitude: self.altitude = note.attributes.altitude if note.attributes.author: self.author = note.attributes.author self.ParseDetails() self.save() class Meta: #app_label = u'flt_evernote' db_table = u'of_evernote' def save(self, *args, **kw): self.geocoded = True if (self.latitude and self.longitude) else False super(ENNote, self).save(*args, **kw)
class OrganisationChange(AbstractBaseModel): """ a request from an user to change the organisation """ STATUS_CHOICES = [ ('o', _('open')), # opened by user ('c', _('canceled')), # by user ('v', _('approved')), ('d', _('denied')) ] user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) original_organisation = models.ForeignKey( Organisation, related_name='original_organisation', null=True, blank=True, on_delete=models.CASCADE) organisation = models.ForeignKey(Organisation, on_delete=models.CASCADE) message = models.TextField( _("message"), max_length=2048, help_text=_('Message for the organisation administrator.'), blank=True) comment = models.TextField(_("Comment"), max_length=2048, blank=True) status = models.CharField(_('status'), max_length=255, choices=STATUS_CHOICES, default='o') last_modified_by_user = CurrentUserField( verbose_name=_('last modified by'), related_name='organisationchange_last_modified_by', on_delete=models.SET_NULL) completed_by_user = models.ForeignKey( settings.AUTH_USER_MODEL, blank=True, null=True, verbose_name=_('completed by'), related_name='organisationchange_completed_by', on_delete=models.SET_NULL) objects = OrganisationChangeManager() open = OpenOrganisationChangeManager() def __str__(self): return f'{self.user} -> {self.organisation}' def cancel(self, user): self.status = 'c' self.completed_by_user = user self.save() def verify(self, user): self.user.set_organisations([self.organisation]) self.status = 'v' self.completed_by_user = user self.user.remove_organisation_related_permissions() # check if organisation uses user activation if is_validation_period_active(self.organisation): if self.user.valid_until is None: self.user.valid_until = now() + datetime.timedelta( days=settings.SSO_VALIDATION_PERIOD_DAYS) else: self.user.valid_until = None # save changes and update last_modified field! self.user.save() self.save() def deny(self, user): self.status = 'd' self.completed_by_user = user self.save() @property def is_open(self): return self.status == 'o' class Meta(AbstractBaseModel.Meta): verbose_name = _('organisation change') verbose_name_plural = _('organisation change') def get_absolute_url(self): return reverse('accounts:organisationchange_detail', kwargs={'pk': self.pk})