class Contact(models.Model): from_name = models.CharField(max_length=255) from_email = models.EmailField() message = models.TextField() spam_score = models.PositiveIntegerField() ip_address = models.GenericIPAddressField() referrer = models.URLField(blank=True)
class Uploadinfo(models.Model): """ All possible information of the client who uploaded the Content file. Usage: Uploadinfo.create(c, request).save() """ content = models.OneToOneField(Content, primary_key=True, editable=False, on_delete=models.CASCADE) sessionid = models.CharField(max_length=200, blank=True, editable=False) ip = models.GenericIPAddressField(blank=True, null=True, editable=False) useragent = models.CharField(max_length=500, blank=True, editable=False) info = models.TextField(blank=True, editable=True) @classmethod def create(cls, content, request): """ Shortcut to create and save Uploadinfo in one line, e.g. uli = Uploadinfo.create(c, request) Uploadinfo.create(c, request).save() """ uploadinfo = cls(content=content) uploadinfo.set_request_data(request) return uploadinfo def set_request_data(self, request): self.sessionid = request.session.session_key if request.session.session_key else "" self.ip = request.META.get("REMOTE_ADDR") self.useragent = request.META.get("HTTP_USER_AGENT", "")[:500]
class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) profile_image = models.ImageField(storage=fs, default='default.jpg') def image_tag(self): return mark_safe('<img src="' + MEDIA_URL + '%s" width="150" height="150" />' % self.profile_image) image_tag.short_description = 'Image' bio = models.TextField(max_length=500, blank=True) user_location = models.PointField(null=True, blank=True) search_location = models.PointField(null=True, blank=True) search_distance = models.PositiveIntegerField(null=True, blank=True, editable=True, help_text="kilometer") # Todo user_location can come from address + city google api call address = models.CharField(max_length=100, null=True) city = models.CharField(max_length=50, null=True) ip_address = models.GenericIPAddressField(null=True) ip_location = models.PointField(null=True, blank=True) def get_estate(self): estate = RealEstate.objects.filter(owner=self) return estate def __str__(self): return self.user.username
class VehicleRevision(models.Model): datetime = models.DateTimeField() vehicle = models.ForeignKey(Vehicle, models.CASCADE) from_operator = models.ForeignKey(Operator, models.CASCADE, null=True, blank=True, related_name='revision_from') to_operator = models.ForeignKey(Operator, models.CASCADE, null=True, blank=True, related_name='revision_to') changes = models.JSONField(null=True, blank=True) message = models.TextField(blank=True) username = models.CharField(max_length=255, blank=True) user = models.ForeignKey(settings.AUTH_USER_MODEL, models.SET_NULL, null=True, blank=True) ip_address = models.GenericIPAddressField(null=True, blank=True) def __str__(self): return ', '.join(f'{key}: {before} → {after}' for key, before, after in self.list_changes()) def list_changes(self): if self.from_operator_id or self.to_operator_id: yield ('operator', self.from_operator, self.to_operator) if self.changes: for key in self.changes: before, after = self.changes[key].split('\n+') before = before[1:] yield (key, before, after)
class Plate(models.Model): plate = models.CharField(max_length=20, editable=False) timestamp = models.DateTimeField(editable=False) confidence = models.FloatField(editable=False) country = models.CharField(max_length=50, editable=False) direction = models.IntegerField(editable=False) ip = models.GenericIPAddressField(editable=False) created_at = models.DateTimeField(default=timezone.now, editable=False)
class IPAddressHistoricalModel(models.Model): """ Abstract model for history models tracking the IP address. """ ip_address = models.GenericIPAddressField(_('IP address'), null=True) class Meta: abstract = True
class IPcity(models.Model): ctime = models.DateTimeField(auto_now_add=True) ip = models.GenericIPAddressField() city = models.ForeignKey(City) whois_results = models.TextField(blank=True, null=True) default_drop = models.BooleanField(default=False) def __unicode__(self): return "%s-%s" % (self.ip, self.city.name)
class LogicalInterface(models.Model): physical_interface = models.ForeignKey("PhysicalInterface", on_delete=models.CASCADE) number = models.IntegerField( help_text="number used to identify interface in MIB") name = models.CharField(default="", max_length=127, blank=True) address = models.GenericIPAddressField(null=True) active = models.BooleanField(default=True) objects = GetOrNoneManager()
class CommentPhoto(models.Model): phototimor = models.ForeignKey(PhotoTimor, verbose_name=_('PhotoTimor'), related_name="comments", on_delete=models.CASCADE) user = models.ForeignKey(User, verbose_name=_('User'), blank=True, null=True, related_name='%(class)s_comments', on_delete=models.SET_NULL) comment = models.TextField(_('Comment'), max_length=COMMENT_MAX_LENGTH) submit_at = models.DateTimeField(_("Submit at"), auto_now_add=True, db_index=True) modified_at = models.DateTimeField(_("Modified at"), auto_now=True) ip_address = models.GenericIPAddressField(_('IP address'), unpack_ipv4=True, blank=True, null=True) is_public = models.BooleanField( _('Is public'), default=True, help_text=_('Uncheck this box to make the comment effectively ' 'disappear from the site.')) is_removed = models.BooleanField( _('is removed'), default=False, db_index=True, help_text=_('Check this box if the comment is inappropriate. ' 'A "This comment has been removed" message will ' 'be displayed instead.')) class Meta: ordering = ('submit_at', ) verbose_name = _('Comment') verbose_name_plural = _('Comments') def __str__(self): return "%s: %s..." % (self.user, self.comment[:50]) def to_json(self): return { "id": self.pk, "phototimor": str(self.phototimor.pk), "user": { "pk": self.user.pk, "username": self.user.username, "fullname": self.user.get_full_name(), }, "comment": self.comment, "sutmit_at": self.submit_at, "modified_at": self.modified_at, }
class Author(models.Model): objects = AuthorManager() # Data user = models.ForeignKey(User, **OPT) ip_address = models.GenericIPAddressField(**OPT) user_agent = models.TextField(**OPT) referer = models.TextField(**OPT) created = models.DateTimeField(auto_now_add=True) def __str__(self): return "{} ({})".format(self.user, self.ip_address)
class Device(models.Model): CONNECTION_TYPES = ( ("snmp", "snmp"), ("netconf", "netconf"), ) id = models.AutoField(primary_key=True) name = models.CharField(default="", max_length=127, blank=True) ip_address = models.GenericIPAddressField() chassis_id = models.CharField(default="", max_length=31, blank=True) snmp_community = models.CharField( default="", max_length=255, blank=True, help_text="string used to authenticate SNMP queries") connection_is_active = models.BooleanField(default=False) connection_type = models.CharField(max_length=15, choices=CONNECTION_TYPES, default="snmp") in_maintenance = models.BooleanField(default=False) model = models.CharField(max_length=15, default="", blank=True) junos_version = models.CharField(max_length=15, default="", blank=True) notes = models.CharField(max_length=255, default="", blank=True) def __str__(self): return f"{self.name} (id: {self.id})" def get_loopback_address(self): loopback_interface_name = "lo0.0" try: loopback_interface = LogicalInterface.objects.get( name=loopback_interface_name, physical_interface__device=self) return loopback_interface.address except (LogicalInterface.DoesNotExist, LogicalInterface.MultipleObjectsReturned): return None def get_state(self): if self.in_maintenance: return "in_maintenance" if not self.connection_is_active: return "inactive" if settings.CHECK_ALARMS: if Alarm.objects.filter(device=self, alarm_class=Alarm.MINOR).exists(): return "with_minor_alarms" if Alarm.objects.filter(device=self, alarm_class=Alarm.MAJOR).exists(): return "with_major_alarms" return "normal"
class UserComment(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True) created = models.DateTimeField(default=timezone.now) subject = models.CharField(max_length=100) send_to = models.CharField(max_length=100) email = models.EmailField(null=True) comment = models.CharField(max_length=1000) remote_addr = models.GenericIPAddressField() remote_host = models.CharField(max_length=100) site_name = models.CharField(max_length=64) def __str__(self): return f"{self.user}: {self.subject}"
class Submission(models.Model): optional = dict(null=True, default=None, blank=True) # Meta submission_id = models.CharField(max_length=64, default=generate_id) user = models.ForeignKey(User, related_name='submitted_route', **optional) ip_address = models.GenericIPAddressField(**optional) user_agent = models.CharField(max_length=1024, **optional) transportation = models.ForeignKey(Transportation, related_name='history', **optional) # Submitted data parent = models.ForeignKey('self', **optional) data_version = models.IntegerField(default=1) raw_geojson = models.TextField() raw_source = models.TextField(**optional) # Parsed data province = models.CharField(max_length=5, choices=PROVINCES, **optional) city = models.CharField(max_length=256, **optional) company = models.CharField(max_length=256, **optional) number = models.CharField(max_length=64, **optional) origin = models.CharField(max_length=256, **optional) destination = models.CharField(max_length=256, **optional) route = models.MultiLineStringField(srid=4326, **optional) parsed_ok = models.NullBooleanField(**optional) parsed_date = models.DateTimeField(**optional) parsed_error = models.CharField(max_length=1024, **optional) source = models.CharField(max_length=100, **optional) # Internal active = models.BooleanField(default=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) def __unicode__(self): return '{} {} - {} - {}'.format(self.company, self.number, self.city, self.user) class Meta: ordering = ('-updated', ) def to_geojson(self): from . import utils return utils.to_geojson(self)
class UserSettings(models.Model): ctime = models.DateTimeField(auto_now_add=True, null=True, blank=True) mtime = models.DateTimeField(auto_now=True, null=True, blank=True) session_key = models.CharField( max_length=32, null=True, blank=True, unique=True, db_index=True) # session = models.ForeignKey(Session, null=True, blank=True) key = models.CharField(max_length=32, null=True, blank=True, db_index=True) username = models.CharField(max_length=32, null=True, blank=True) password = models.CharField(max_length=32, null=True, blank=True) level_date = models.TextField(null=True, blank=True) referral = models.CharField(max_length=32, null=True, blank=True) busfav = models.BinaryField(null=True, blank=True) busfavor_amount = models.SmallIntegerField(default=5) stars = models.SmallIntegerField(default=0, null=True, blank=True) comment = models.CharField(max_length=256, null=True, blank=True) premium = models.BooleanField(default=0) vip = models.BooleanField(default=0) noads = models.BooleanField(default=0) theme = models.SmallIntegerField(default=0, choices=THEME_CHOICES) theme_save = models.SmallIntegerField(null=True, blank=True) mode = models.SmallIntegerField(default=1, choices=MODE_CHOICES) sound = models.BooleanField(default=1) sound_plusone = models.BooleanField(default=False) gps_off = models.BooleanField(default=0) city = models.ForeignKey(City, null=True, blank=True) tcard = models.CharField(max_length=20, null=True, blank=True) ip = models.GenericIPAddressField(null=True, blank=True) ua = models.CharField(max_length=512, null=True, blank=True) vk_like_pro = models.SmallIntegerField(default=0) theme_stripes = models.BooleanField(default=1) pro_demo = models.BooleanField(default=False) pro_demo_date = models.DateTimeField(null=True, blank=True) multi_all = models.BooleanField(default=False) matrix_show = models.BooleanField(default=True) map_show = models.BooleanField(default=False) speed_show = models.BooleanField(default=False) font_big = models.BooleanField(default=False) def __unicode__(self): return "%s" % self.id def save(self, *args, **kwargs): if not self.premium and not self.pro_demo: self.busfavor_amount = 5 super(UserSettings, self).save(*args, **kwargs)
class ReportRecord(models.Model): """Report records send by users. `ReportRecord` will be queried in advanced by admins from Citizen of the Earth, Taiwan. They will filter the most recent records out every a few weeks to catch the bad guys. """ id = models.AutoField(primary_key=True) factory = models.ForeignKey("Factory", on_delete=models.PROTECT) user_ip = models.GenericIPAddressField(default="192.168.0.1", blank=True, null=True) action_type = models.CharField(max_length=10) # PUT, POST action_body = JSONField() # request body created_at = models.DateTimeField(auto_now_add=True) nickname = models.CharField(max_length=64, blank=True, null=True) contact = models.CharField(max_length=64, blank=True, null=True) others = models.CharField(max_length=1024, blank=True)
class Comentario(models.Model): """ Modelo de comentarios """ created = models.DateTimeField(auto_now_add=True) author = models.ForeignKey(User) body = models.TextField(_('Ingresa tu comentario'),max_length=500, null=False, blank=False) post = models.ForeignKey(Establecimiento) ip_address = models.GenericIPAddressField(_('IP address'), unpack_ipv4=True, blank=True, null=True) is_public = models.BooleanField(_('is public'), default=True, help_text=_('Si el comentario es visible ')) def __unicode__(self): return unicode("%s: %s" % (self.post, self.body[:60])) class Meta: verbose_name = _('Comentario') verbose_name_plural = _('Comentarios')
class Address(models.Model): """ Model representing an individual IP Address """ # protocol 'both' enables ipv6 support should we add it in the future. address = models.GenericIPAddressField(protocol='both', unpack_ipv4=False, primary_key=True) coords = models.PointField(geography=True, spatial_index=True, null=True, blank=True) def __str__(self): return self.address class Meta: ordering = ['address']
class Instance(models.Model): port_type_choice = (('Обл.', 'Областной'), ('Респ.', 'Республиканский')) service_type_choice = (('БСПД', 'БСПД'), ('Спутник', 'Спутниковый канал'), ('Наземный', 'ВОЛС/DSL/ADSL/xDSL')) is_my = models.BooleanField(default=True, verbose_name='собственный договор') is_active = models.BooleanField(default=True, verbose_name='активный') client = models.ForeignKey(Client, null=True, on_delete=models.SET_NULL, verbose_name='клиент') service_type = models.CharField(max_length=20, default='Наземный', choices=service_type_choice, verbose_name='тип канала') port_type = models.CharField(max_length=20, default='Обл.', choices=port_type_choice, verbose_name='тип порта') point = models.ForeignKey(Points, null=True, on_delete=models.SET_NULL, verbose_name='точка') speed = models.ForeignKey(Speed, null=True, on_delete=models.SET_NULL, verbose_name='скорость канала') lan = models.GenericIPAddressField(protocol='IPv4', verbose_name='ip адрес сети') lan_mask = models.SmallIntegerField(default=24, verbose_name='маска подсети') def __str__(self): return self.client.name + ' --> ' + str(self.point) class Meta: verbose_name = 'Подключение' verbose_name_plural = 'Подключения'
class InstanceRun(models.Model): url = models.URLField(_('URL'), db_index=True) callback_url = models.URLField(_('Callback URL'), blank=True) requested = models.DateTimeField(_('requested'), db_index=True) started = models.DateTimeField(_('started'), blank=True, null=True, db_index=True) finished = models.DateTimeField(_('finished'), blank=True, null=True, db_index=True) dns_results = ArrayField(models.GenericIPAddressField(), verbose_name=_('DNS results'), blank=True, default=list) class Meta: verbose_name = _('instance run') verbose_name_plural = _('instance runs') ordering = ('requested', 'started', 'finished') def __str__(self): if self.finished: return _('{url} completed on {when}').format( url=self.url, when=date_format(self.finished, 'DATETIME_FORMAT')) elif self.started: return _('{url} started on {when}').format(url=self.url, when=date_format( self.started, 'DATETIME_FORMAT')) else: return _('{url} requested on {when}').format( url=self.url, when=date_format(self.requested, 'DATETIME_FORMAT'))
class UnifiedSearchItem(models.Model): """ META """ class Meta: app_label = 'tenant_foundation' db_table = 'nwapp_unified_search_items' verbose_name = _('Unified Search Item') verbose_name_plural = _('Unified Search Items') default_permissions = () permissions = () ''' CONSTANTS ''' class TYPE_OF: MEMBER = 1 AREA_COORDINATOR = 2 ASSOCIATE = 3 STAFF = 4 ITEM = 5 WATCH = 6 DISTRICT = 7 FILE = 8 ''' CHOICES ''' TYPE_OF_CHOICES = ( (TYPE_OF.MEMBER, _('Customer')), (TYPE_OF.AREA_COORDINATOR, _('Area Coordinator')), (TYPE_OF.ASSOCIATE, _('Associate')), (TYPE_OF.STAFF, _('Staff')), (TYPE_OF.ITEM, _('Item')), (TYPE_OF.WATCH, _('Watch')), (TYPE_OF.DISTRICT, _('District')), (TYPE_OF.FILE, _('File')), ) """ OBJECT MANAGER """ objects = UnifiedSearchItemManager() """ FIELDS """ # THE FOLLOWING FIELDS ARE USED FOR SEARCHING. text = models.CharField( _("Text"), max_length=2047, help_text=_( 'The searchable content text used by the keyword searcher function.' ), blank=True, null=True, db_index=True, unique=True) tags = models.ManyToManyField( "Tag", help_text=_('The tags with this unified search item.'), blank=True, related_name="unified_search_items") # THE FOLLOWING FIELDS ARE USED TO MAP OUR SEARCHABLE ITEM TO AN OBJECT. uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) slug = models.CharField( _("Slug"), max_length=255, help_text=_('The external identifier of the object.'), unique=True, db_index=True, ) type_of = models.PositiveSmallIntegerField( _("Type of"), help_text=_('The type of item this is.'), choices=TYPE_OF_CHOICES, db_index=True, ) description = models.CharField( _("Description"), max_length=255, help_text=_('The title of the object to display.'), blank=True, null=True, ) member = models.OneToOneField( "Member", help_text=_('The member of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) area_coordinator = models.OneToOneField( "AreaCoordinator", help_text=_('The area coordinator of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) associate = models.OneToOneField( "Associate", help_text=_('The associate of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) staff = models.OneToOneField("Staff", help_text=_('The staff of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) item = models.OneToOneField( "Item", help_text=_('The work-order of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) watch = models.OneToOneField("Watch", help_text=_('The watch of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) district = models.OneToOneField( "District", help_text=_('The district of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) file = models.OneToOneField("PrivateFileUpload", help_text=_('The file of this search item.'), related_name="unified_search_item", on_delete=models.CASCADE, blank=True, null=True) # THE FOLLOWING FIELDS ARE USED FOR SYSTEM PURPOSES. created_at = models.DateTimeField( _("Created At"), help_text=_('When the object was created.'), blank=True, null=True) created_by = models.ForeignKey( SharedUser, help_text=_('The user whom created this object.'), related_name="created_unified_search_items", on_delete=models.SET_NULL, blank=True, null=True, ) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) created_from_position = models.PointField( _("Created from position"), help_text=_('The latitude and longitude coordinates for the creator.'), srid=4326, geography=True, null=True, blank=True, ) last_modified_at = models.DateTimeField( _("Last Modified At"), help_text=_('When the object was last modified.'), blank=True, null=True) last_modified_by = models.ForeignKey( SharedUser, help_text=_('The user whom modified this object last.'), related_name="last_modified_unified_search_items", on_delete=models.SET_NULL, blank=True, null=True, ) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) last_modified_from_position = models.PointField( _("Last modified from position"), help_text=_( 'The latitude and longitude coordinates for the last modified user.' ), srid=4326, geography=True, null=True, blank=True, ) """ FUNCTIONS """ def __str__(self): return str(self.description) def save(self, *args, **kwargs): ''' Override our save functionality to add the following additional functionality: ''' # DEVELOPERS NOTE: # Why are we doing this? We want to handle the situation that our # application inputs an indexted text which is too large; therefore, # we will automatically truncate it so this issue will not occur. self.text = Truncator(self.text).chars(2047) ''' Run our `save` function. ''' super(UnifiedSearchItem, self).save(*args, **kwargs) @staticmethod def get_type_of_member(member): try: role_id = member.user.role_id if role_id == SharedGroup.GROUP_MEMBERSHIP.MEMBER: return UnifiedSearchItem.TYPE_OF.MEMBER elif role_id == SharedGroup.GROUP_MEMBERSHIP.AREA_COORDINATOR: return UnifiedSearchItem.TYPE_OF.AREA_COORDINATOR elif role_id == SharedGroup.GROUP_MEMBERSHIP.ASSOCIATE: return UnifiedSearchItem.TYPE_OF.ASSOCIATE elif role_id == SharedGroup.GROUP_MEMBERSHIP.FRONTLINE_STAFF: return UnifiedSearchItem.TYPE_OF.STAFF elif role_id == SharedGroup.GROUP_MEMBERSHIP.MANAGER: return UnifiedSearchItem.TYPE_OF.STAFF print("get_type_of_member | unsupported member role") except Exception as e: print("get_type_of_member | exception:", e) return -1
class ReverseDnsScan(models.Model): domain = models.CharField(max_length=128, db_index=True) hostpart = models.CharField(max_length=128) ip = models.GenericIPAddressField(db_index=True)
class Triangulation(models.Model): ip = models.GenericIPAddressField() ##MSM_BASE_FMT="https://atlas.ripe.net/api/v1/measurement/%d/result/?format=txt" msm_result_fmt = "https://193.0.6.158/api/v1/measurement/%d/result/?format=txt" KM_PER_MS = 100 # assuming 2 way and light in fiber is 2/3 speed of light msm_key = '5531c157-ace1-46f2-b386-22a68b0539a6' msm_create_url = 'https://atlas.ripe.net/api/v1/measurement/?key=%s' % ( msm_key) def _update(self): ## update with msms that are not final yet ## @@ continue from here return def parse_msm_results(self): for m in self.trimsm_set.all(): fh = urllib2.urlopen(self.__class__.msm_result_fmt % (m.msm)) for line in fh: d = json.loads(line) if d['min'] <= 0: continue p = Probe.objects.get(id=d['prb_id']) if p.has_incorrect_geoloc == True: continue tric, is_created = self.triconstraint_set.get_or_create( lat=p.lat, lon=p.lon, rtt=d['min'], lastmile_rtt=p.lastmile_rtt, prb=p) def refine(self): self._update() constraints = self.triconstraint_set.all().order_by('rtt') af = 4 if re.search(':', self.ip): af = 6 msm_def = { "definitions": [{ "target": self.ip, "description": "triangulation for %s" % self.ip, "type": "ping", "af": af, "is_oneoff": True, "packets": 5, }], "probes": [] } if len(constraints) == 0: ## no previous knowledge on this IP ### add 5 probes from each 'area' for area in ('West', 'North-Central', 'South-Central', 'North-East', 'South-East'): msm_def['probes'].append({ 'requested': 5, 'type': 'area', 'value': area }) else: prb_set = Probe.objects.all() loc_set = Loc.objects.all().order_by('-pop') for c in constraints: max_dist = c.rtt * self.__class__.KM_PER_MS point_rep = 'POINT(%s %s)' % (c.lon, c.lat) prb_set = prb_set.filter(point__distance_lt=(point_rep, D(km=max_dist))) loc_set = loc_set.filter(point__distance_lt=(point_rep, D(km=max_dist))) print "potential locs within constraints %s" % (len(loc_set)) ## top 5 locs within set (for now ordered by population) prb_ids = [] for loc in loc_set: ## select 3 probes close to this loc prb_close_to_loc = Probe.objects.filter( point__distance_lt=('POINT(%s %s)' % (loc.lon, loc.lat), D(km=100))).order_by('-id') for p in prb_close_to_loc[0:3]: prb_ids.append(str(p.id)) print "added %s (%s)" % (p.id, loc) if len(prb_ids) > 20: break msm_def['probes'].append({ 'requested': 20, 'type': 'probes', 'value': ",".join(prb_ids) }) msm_json = json.dumps(msm_def) msm_req = JsonRequest(self.__class__.msm_create_url) try: msm_conn = urllib2.urlopen(msm_req, msm_json) except urllib2.HTTPError as e: print "HTTP error %s " % (e.read) msm_meta = json.load(msm_conn) for msm_id in msm_meta['measurements']: self.save() new_trimsm = self.trimsm_set.create(msm=msm_id) print "msm_id created: %s" % (msm_id) #msm_id = msm_meta['measurements'][0] ### here we save it to TriMsm ## self.add_msm_results( msm_id ) def find_locs(self, max=10): ### very very dumb now self._order_constraints() (lat, lon, rtt, lm_rtt, prb_id) = self.constraints[0]
class IPMeta(models.Model): ip = models.GenericIPAddressField(db_index=True) created = models.DateTimeField(auto_now_add=True) invalidated = models.DateTimeField(blank=True, null=True, db_index=True) last_updated = models.DateTimeField(auto_now=True) dnsloc = models.CharField(max_length=256, blank=True, null=True) hostname = models.CharField(max_length=256, blank=True, null=True) ##is_anycast = models.NullBooleanField( blank=True, null=True ) psl = PublicSuffixList() def save(self, **kwargs): ''' IPMeta save method, does lookups if object isn't saved yet ''' if not self.id: ## do dnsloc and hostname lookups try: host_resolve = dns.resolver.query( dns.reversename.from_address(self.ip), 'PTR') h = str(host_resolve.response.answer[0].items[0]) h = h.rstrip('.') self.hostname = h except: #it's perfectly fine for a reverse not to exist pass if self.hostname: try: loc_resolve = dns.resolver.query(self.hostname, 'LOC') self.dnsloc = str(loc_resolve[0]) except: # it's perfectly fine for a loc record not to exist pass super(self.__class__, self).save(**kwargs) def info2json(self, **kwargs): ''' convert all info about this IP into a json structure. optional arguments accepted are 'lat': latitude, to georestrict by 'lon': longitude, to georestrict by 'min_rtt': rtt, to georestrict by ''' do_rtt_constraint = False try: lat = kwargs['lat'] lon = kwargs['lon'] min_rtt = kwargs['min_rtt'] do_rtt_constraint = True except: pass DNSLOC_WEIGHT = 0.95 HOSTNAME_WEIGHT = 0.90 # 0 1 2 3 4 5 7 7 # 48 51 21.953 N 2 23 0.143 E 10.00m 1.00m 10000.00m 10.00m" def _dnsloc2ll(loc_str): out = {'str': loc_str} fields = loc_str.split() if len(fields) >= 7: lat = float(fields[0]) + float(fields[1]) / 60 + float( fields[2]) / (60 * 60) if fields[3] == 'S': lat = -lat lon = float(fields[4]) + float(fields[5]) / 60 + float( fields[6]) / (60 * 60) if fields[7] == 'W': lon = -lon out['lat'] = lat out['lon'] = lon return out info = {} name2loc = [] crowdsourced = [] info['ip'] = self.ip info['hostname'] = self.hostname info['domainname'] = None try: info['domainname'] = self.__class__.psl.get_public_suffix( self.hostname) except: pass if self.dnsloc: info['dnsloc'] = _dnsloc2ll(self.dnsloc) #gc = IPGeoConstraint.objects.filter(ipmeta = self) #if len( gc ) == 1: # info['area'] = json.loads( gc[0].area.geojson ) ## add a suggestions array that contains the ordered list of suggested lat/lon suggestions = [] name2loc = self.name2loc(**kwargs) if 'dnsloc' in info: if not do_rtt_constraint or openipmap.geoutils.can_one_travel_distance_in_rtt( lat, lon, info['dnsloc']['lat'], info['dnsloc']['lon'], min_rtt): # only add this if this is possible RTTwise suggestions.append({ 'lat': info['dnsloc']['lat'], 'lon': info['dnsloc']['lon'], 'reason': 'dnsloc', 'weight': DNSLOC_WEIGHT, }) total_pop = 0 for n in name2loc: total_pop += n['pop'] for n in name2loc: # lat/lon already there n['weight'] = HOSTNAME_WEIGHT * n['pop'] / total_pop n['reason'] = 'hostname' suggestions.append(n) info['suggestions'] = suggestions crowdsourced.extend(IPRule.get_crowdsourced(self.ip)) if self.hostname: crowdsourced.extend(HostnameRule.get_crowdsourced(self.hostname)) info['crowdsourced'] = crowdsourced return info def name2loc(self, poly_geoconstraint=None, **kwargs): ''' try to figure out loc, based on name optional arguments accepted are 'lat': latitude, to georestrict by 'lon': longitude, to georestrict by 'min_rtt': rtt, to georestrict by ''' ## TODO: add polygon confinement? nr_results = 10 ## configurable? do_rtt_constraint = False try: lat = kwargs['lat'] lon = kwargs['lon'] min_rtt = kwargs['min_rtt'] do_rtt_constraint = True except: pass # this should be configurable/tags and/or have low confidence value tag_blacklist = set([ 'rev', 'cloud', 'clients', 'demarc', 'ebr', 'pool', 'bras', 'core', 'static', 'router', 'net', 'bgp', 'pos', 'out', 'link', 'host', 'infra', 'ptr', 'isp', 'adsl', 'rdns', 'tengig', 'tengige', 'tge', 'rtr', 'shared', 'red', 'access', 'tenge', 'gin', 'dsl', 'cpe' ]) if not self.hostname: return [] name = self.hostname.rstrip('.') suf = self.__class__.psl.get_public_suffix(name) rest = '' tokens = [] if suf != name: rest = name[0:len(name) - len(suf) - 1] rest = rest.lower() ## support for additional tokenization? tokens = re.split(r'[^a-zA-Z]+', rest) ## filter by token-length (for now) , TODO make configurable? tokens = [t for t in tokens if len(t) >= 3] ## remove blacklisted tokens tokens = [t for t in tokens if not t in tag_blacklist] matches = {} def add_to_matches(g, token, is_abbrev, **kwargs): if not g.loc.id in matches: ## check if geoconstraints if do_rtt_constraint and not openipmap.geoutils.can_one_travel_distance_in_rtt( lat, lon, g.loc.lat, g.loc.lon, min_rtt): return matches[g.loc.id] = { 'loc_id': g.loc.id, 'pop': g.loc.pop, 'count': g.loc.count, 'name': str(g.loc), 'lat': g.loc.lat, 'lon': g.loc.lon, 'token': set(), 'kind': set() } if poly_geoconstraint: if poly_geoconstraint.contains(g.loc.point): matches[g.loc.id] = {'in_constraint': True} matches[g.loc.id]['token'].add(token) ## this loses the link between the token and the geoalias-kind (for now) if is_abbrev: matches[g.loc.id]['kind'].add('abbrev-' + g.kind) else: matches[g.loc.id]['kind'].add(g.kind) for t in tokens: for ga in Geoalias.objects.filter(word=t): add_to_matches(ga, t, False, **kwargs) if len(matches) == 0: #print "little on strict match, trying like" for t in tokens: ## 't' can't be anything but a-zA-Z so no SQL injection should be possible sql_like_chars = '%%'.join(list(t)) sql_like_chars += '%%' # 'a%m%s%' sql = "SELECT id FROM openipmap_geoalias WHERE word LIKE '%s'" % ( sql_like_chars) for ga in Geoalias.objects.raw(sql): add_to_matches(ga, t, True, **kwargs) ## this sorts, first by 'count' (=number of hostnames the DB already has for this location) then by 'population' of location mk = sorted( matches.keys(), reverse=True, key=lambda x: (matches[x]['count'], matches[x]['pop']))[0:nr_results] ## max 10 result = [] for m in mk: entry = matches[m] # flatten entry['token'] = list(entry['token']) entry['kind'] = list(entry['kind']) result.append(entry) return result @classmethod def gather_from_msm(self, msm_id, interval=3600): #@@ todo make these configurable: limit = 10 stop = int(time.time()) start = stop - interval msm_url = "https://atlas.ripe.net/api/v1/measurement/%d/result/?start=%d&stop=%d&limit=%d&format=txt" % ( msm_id, start, stop, limit) print msm_url url_fh = urllib2.urlopen(msm_url) ips = {} for line in url_fh: try: msm = json.loads(line) prb_id = msm['prb_id'] for msm_res in msm['result']: hop_nr = msm_res['hop'] for hop_res in msm_res['result']: if 'from' in hop_res: ip = hop_res['from'] rtt = hop_res['rtt'] if not ip in ips: ips[ip] = 1 except: print "oops on %s" % (line) timediff = datetime.now() - timedelta(days=30) for ip in ips: ## figure out if there is a recent Meta fetch done try: ipm = self.objects.filter(ip=ip).filter( created__gte=timediff).order_by('-created') if len(ipm) > 0: i = ipm[0] else: ## insert it (does autolookups) i = IPMeta() i.ip = ip i.save() print "%s %s %s" % (i.ip, i.hostname, i.dnsloc) except: pass
class SharedOrganization(TenantMixin): """ Class model to represent our tenant that all other data will be attached to. """ ''' Metadata ''' class Meta: app_label = 'shared_foundation' db_table = 'nwapp_shared_organizations' verbose_name = _('Shared Organization') verbose_name_plural = _('Shared Organizations') default_permissions = () permissions = () indexes = (BrinIndex( fields=[ 'created_at', 'last_modified_at', ], autosummarize=True, ), ) ''' Constants ''' class STREET_TYPE: UNSPECIFIED = 0 OTHER = 1 AVENUE = 2 DRIVE = 3 ROAD = 4 STREET = 5 WAY = 6 class STREET_DIRECTION: NONE = 0 EAST = 1 NORTH = 2 NORTH_EAST = 3 NORTH_WEST = 4 SOUTH = 5 SOUTH_EAST = 6 SOUTH_WEST = 7 WEST = 8 ''' Choices ''' STREET_TYPE_CHOICES = ( (STREET_TYPE.UNSPECIFIED, _('-')), (STREET_TYPE.AVENUE, _('Avenue')), (STREET_TYPE.DRIVE, _('Drive')), (STREET_TYPE.ROAD, _('Road')), (STREET_TYPE.STREET, _('Street')), (STREET_TYPE.WAY, _('Way')), ) STREET_DIRECTION_CHOICES = ( (STREET_DIRECTION.NONE, _('-')), (STREET_DIRECTION.EAST, _('East')), (STREET_DIRECTION.NORTH, _('North')), (STREET_DIRECTION.NORTH_EAST, _('North East')), (STREET_DIRECTION.NORTH_WEST, _('North West')), (STREET_DIRECTION.SOUTH, _('South')), (STREET_DIRECTION.SOUTH_EAST, _('South East')), (STREET_DIRECTION.SOUTH_WEST, _('South West')), (STREET_DIRECTION.WEST, _('West')), ) ''' Object Managers ''' objects = SharedOrganizationManager() ''' Fields ''' # # FIELDS # name = models.CharField( _("Name"), max_length=63, help_text=_('The name this organization.'), ) alternate_name = models.CharField( _("Alternate Name"), max_length=63, help_text=_('The alternate name this organization.'), ) description = models.TextField( _("Description"), help_text=_('A short description of this organization.'), ) country = models.CharField( _("Country"), max_length=127, help_text= _('The country. For example, USA. You can also provide the two-letter <a href="https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2#Officially_assigned_code_elements">ISO 3166-1 alpha-2</a> country code.' ), ) province = models.CharField( _("Province"), max_length=127, help_text=_('The province. For example, CA.'), ) city = models.CharField( _("City"), max_length=127, help_text=_('The city. For example, Mountain View.'), ) street_number = models.CharField( _("Street Number"), max_length=127, help_text=_('-'), null=True, blank=True, ) street_name = models.CharField( _("Street Name"), max_length=127, help_text=_('-'), null=True, blank=True, ) apartment_unit = models.CharField( _("Apartment Unit"), max_length=127, help_text=_('-'), null=True, blank=True, ) street_type = models.PositiveSmallIntegerField( _("Street Type"), help_text=_('Please select the street type.'), choices=STREET_TYPE_CHOICES, blank=True, default=STREET_TYPE.UNSPECIFIED, ) street_type_other = models.CharField( _("Street Type (Other)"), max_length=127, help_text=_('Please select the street type not listed in our types.'), null=True, blank=True, ) street_direction = models.PositiveSmallIntegerField( _("Street Direction"), help_text=_('Please select the street direction.'), choices=STREET_DIRECTION_CHOICES, blank=True, default=STREET_DIRECTION.NONE, ) postal_code = models.CharField( _("Postal Code"), max_length=32, help_text=_('-'), null=True, blank=True, ) timezone_name = models.CharField( _("Timezone Name"), help_text=_('The timezone that this organization belongs to.'), max_length=32, choices=TIMEZONE_CHOICES, default="UTC") police_report_url = models.URLField( _("Police Report URL"), help_text= _('The URL of the police reporting service used to submit crime reports.' ), max_length=255, null=True, blank=True, ) default_position = models.PointField( _("Default Position"), help_text= _('The centre coordinates to apply for every map rendered on the user\'s screen.' ), srid=4326, geography=True, null=True, blank=True, ) default_zoom = models.FloatField( _("Default Map Zoom"), help_text= _('The centre zoom to apply for every map rendered on the user\'s screen.' ), null=True, blank=True, ) # # Contact Information # email = models.EmailField( _("Email"), help_text=_('Email address.'), null=True, blank=True, ) phone = models.CharField( _("Phone"), help_text=_('The telephone number used by the organization.'), blank=True, null=True, max_length=31, validators=[e164_phone_regex], ) website_url = models.URLField( _("Website URL"), help_text=_('The website URL of the organization.'), max_length=255, null=True, blank=True, ) facebook_url = models.URLField( _("Facebook URL"), help_text=_('The Facebook URL of the organization.'), max_length=255, null=True, blank=True, ) twitter_url = models.URLField( _("Twitter URL"), help_text=_('The Twitter URL of the organization.'), max_length=255, null=True, blank=True, ) instagram_url = models.URLField( _("Instagram URL"), help_text=_('The Instagram URL of the organization.'), max_length=255, null=True, blank=True, ) youtube_url = models.URLField( _("YouTube URL"), help_text=_('The YouTube URL of the organization.'), max_length=255, null=True, blank=True, ) # # SYSTEM FIELDS # uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( 'SharedUser', help_text=_('The user whom created this organization.'), related_name="created_shared_organizations", on_delete=models.SET_NULL, blank=True, null=True) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) last_modified_at = models.DateTimeField(auto_now=True) last_modified_by = models.ForeignKey( 'SharedUser', help_text=_('The user whom last modified this organization.'), related_name="last_modified_shared_organizations", on_delete=models.SET_NULL, blank=True, null=True) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) ''' Methods ''' def to_tenant_dt(self, aware_dt): #TODO: UNIT TEST """ Function will convert the inputted timezone aware datetime object into the timezone specific to this tenant. """ try: return aware_dt.astimezone(pytz.timezone(self.timezone_name)) except Exception as e: return aware_dt @transaction.atomic def save(self, force_insert=False, force_update=False, *args, **kwargs): """ Override the save function so we can add extra functionality. """ # If no `id` was set then we'll set it ourselves. if self.id is None: self.id = SharedOrganization.objects.count() + 1 super(SharedOrganization, self).save(force_insert, force_update, *args, **kwargs) def __str__(self): return str(self.schema_name) def get_absolute_url(self): return "/shared-organization/" + str(self.schema_name) @cached_property def is_public(self): return self.schema_name == "public" @cached_property def country_code(self): if self.country == "Canada": return "CA" #TODO: Pay off technical debit by finding out how to handle other countries. else: return "CA" def get_pretty_street_type(self): return str( dict(SharedOrganization.STREET_TYPE_CHOICES).get(self.street_type)) def get_pretty_street_direction(self): return str( dict(SharedOrganization.STREET_DIRECTION_CHOICES).get( self.street_direction)) def activate_tenant(self): # Connection needs first to be at the public schema, as this is where # the database needs to be set before creating a new tenant. If this is # not done then django-tenants will raise a "Can't create tenant outside # the public schema." error. connection.set_schema_to_public() # Switch to Public. # Connection will set it back to our tenant. connection.set_schema(self.schema_name, True) # Switch to Tenant. @staticmethod def activate_tenant_by_schema(schema_name): try: # Connection needs first to be at the public schema, as this is where # the database needs to be set before creating a new tenant. If this is # not done then django-tenants will raise a "Can't create tenant outside # the public schema." error. connection.set_schema_to_public() # Switch to Public. # Lookup the tenant in our database. organization = SharedOrganization.objects.get( schema_name=schema_name) # Connection will set it back to our tenant. connection.set_schema(organization.schema_name, True) # Switch to Tenant. return True except SharedOrganization.DoesNotExist: return False
class Item(models.Model): ''' METADATA ''' class Meta: app_label = 'tenant_foundation' db_table = 'nwapp_items' verbose_name = _('Item') verbose_name_plural = _('Items') default_permissions = () permissions = () ''' CONSTANTS ''' class STATE: ACTIVE = 'active' INACTIVE = 'inactive' ARCHIVED = 'archived' class SHOWN_TO_WHOM: GENERAL_PUBLIC = 2 ALL_NW_STAFF = 3 MY_WATCH_AREA = 4 class WHO_NEWS_FOR: MY_CITY = 2 MY_DISTRICT = 3 MY_WATCH = 4 class FORMAT_TYPE: LINK_RESOURCE_TYPE_OF = 2 YOUTUBE_VIDEO_RESOURCE_TYPE_OF = 3 IMAGE_RESOURCE_TYPE_OF = 4 FILE_RESOURCE_TYPE_OF = 5 UNSPECIFIED_TYPE_OF = 6 ''' CHOICES ''' STATE_CHOICES = ( (STATE.ACTIVE, _('Active')), (STATE.INACTIVE, _('Inactive')), (STATE.ARCHIVED, _('Archived')), ) SHOWN_TO_WHOM_CHOICES = ( (SHOWN_TO_WHOM.GENERAL_PUBLIC, _('General Public')), (SHOWN_TO_WHOM.ALL_NW_STAFF, _('All NW Staff')), (SHOWN_TO_WHOM.MY_WATCH_AREA, _('My Watch Area')), ) WHO_NEWS_FOR_CHOICES = ( (WHO_NEWS_FOR.MY_CITY, _('My City')), (WHO_NEWS_FOR.MY_DISTRICT, _('My District')), (WHO_NEWS_FOR.MY_WATCH, _('My Watch')), ) FORMAT_TYPE_CHOICES = ( (FORMAT_TYPE.LINK_RESOURCE_TYPE_OF, _('Link')), (FORMAT_TYPE.YOUTUBE_VIDEO_RESOURCE_TYPE_OF, _('YouTube Video')), (FORMAT_TYPE.IMAGE_RESOURCE_TYPE_OF, _('Image')), (FORMAT_TYPE.FILE_RESOURCE_TYPE_OF, _('File')), (FORMAT_TYPE.UNSPECIFIED_TYPE_OF, _('Unspecified')), ) ''' OBJECT MANAGERS ''' objects = ItemManager() ''' MODEL FIELDS ''' # COMMON FIELDS state = models.CharField( _('State'), help_text=_('The state of this item.'), max_length=15, choices=STATE_CHOICES, default=STATE.ACTIVE, blank=True, db_index=True, ) type_of = models.ForeignKey( "ItemType", help_text=_('The custom type of item this is.'), related_name="type_ofs", on_delete=models.CASCADE, ) description = models.TextField( _("Description"), help_text=_('A short description of this item, if it has one.'), blank=True, null=True, default='', ) # EVENT FIELDS start_at = models.DateTimeField( _("Start at"), help_text=_( 'The date and time this item will start if it is an event.'), blank=True, null=True, ) is_all_day_event = models.BooleanField( _("Is all day event"), help_text=_('Is this event item full day?'), default=False, blank=True) finish_at = models.DateTimeField( _("Finish at"), help_text=_( 'The date and time this item will finish if it is an event.'), blank=True, null=True, ) title = models.CharField( # Event / Incident / Concern _("Title"), max_length=63, help_text=_('The title of the item, if it has one.'), null=True, blank=True, default='', ) external_url = models.URLField( _("External URL"), max_length=63, help_text=_('The URL for the item to reference an external address.'), null=True, blank=True, default='', ) shown_to_whom = models.PositiveSmallIntegerField( _("Shown to whom?"), help_text=_( 'The person / organization that is allowed to view this item.'), choices=SHOWN_TO_WHOM_CHOICES, null=True, blank=True, ) can_be_posted_on_social_media = models.BooleanField( _("Can be posted on Social Media?"), help_text=_( 'Has the poster allowed this item be posted on social media?'), blank=True, default=True, ) event_logo_image = models.ForeignKey( "PrivateImageUpload", help_text=_('The logo image of this event item.'), related_name="event_logo_items", on_delete=models.SET_NULL, blank=True, null=True, ) # INCIDENT / CONCERN has_notified_authorities = models.BooleanField( _("Has notified authorities"), help_text=_('Has notified authorities?'), default=False, blank=True, null=True, ) has_accept_authority_cooperation = models.BooleanField( _("Has accepted authority cooperation"), help_text= _('Has user agreed to the fact that NW can contact the local and federal police services?' ), default=False, blank=True, null=True, ) date = models.DateField( _("Date"), help_text=_('The date this item occured.'), blank=True, null=True, ) location = models.CharField( # Event / Incident / Concern _("Location"), max_length=127, help_text=_('The location of where this event occured.'), null=True, blank=True, default='', ) # COMMUNITY NEWS who_news_for = models.PositiveSmallIntegerField( _("Who news for?"), help_text=_('Whome shall see this news item?'), choices=WHO_NEWS_FOR_CHOICES, null=True, blank=True, ) # RESOURCE format_type = models.PositiveSmallIntegerField( _("Format Type"), help_text=_('The format type of resource.'), choices=FORMAT_TYPE_CHOICES, default=FORMAT_TYPE.UNSPECIFIED_TYPE_OF, blank=True, null=True, ) embed_code = models.CharField( # Event / Incident / Concern _("Embed Code"), max_length=1023, help_text=_('The YouTube embed code for this item.'), null=True, blank=True, default='', ) resource_image = models.ForeignKey( "PrivateImageUpload", help_text=_('The resource image of this item.'), related_name="resource_image_items", on_delete=models.SET_NULL, blank=True, null=True, ) resource_file = models.ForeignKey( "PrivateFileUpload", help_text=_('The resource file of this item.'), related_name="resource_file_items", on_delete=models.SET_NULL, blank=True, null=True, ) # STAFF ACTIONING FIELDS #TODO: Implement... # AUDITING FIELDS uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) slug = models.SlugField( _("Slug"), help_text=_('The unique identifier used externally.'), max_length=255, null=False, unique=True, db_index=True, ) created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( SharedUser, help_text=_('The user whom created this object.'), related_name="created_items", on_delete=models.SET_NULL, blank=True, null=True, ) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) created_from_position = models.PointField( _("Created from position"), help_text=_('The latitude and longitude coordinates for the creator.'), srid=4326, geography=True, null=True, blank=True, ) last_modified_at = models.DateTimeField(auto_now=True) last_modified_by = models.ForeignKey( SharedUser, help_text=_('The user whom modified this object last.'), related_name="last_modified_items", on_delete=models.SET_NULL, blank=True, null=True, ) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) last_modified_from_position = models.PointField( _("Last modified from position"), help_text=_( 'The latitude and longitude coordinates for the last modified user.' ), srid=4326, geography=True, null=True, blank=True, ) """ MODEL FUNCTIONS """ def __str__(self): from tenant_foundation.models.item_type import ItemType if self.type_of.category == ItemType.CATEGORY.EVENT: return self.title if self.type_of.category == ItemType.CATEGORY.INCIDENT: return self.title if self.type_of.category == ItemType.CATEGORY.CONCERN: return self.title if self.type_of.category == ItemType.CATEGORY.INFORMATION: return Truncator(self.description).chars(63) if self.type_of.category == ItemType.CATEGORY.COMMUNITY_NEWS or self.type_of.category == ItemType.CATEGORY.VOLUNTEER: return Truncator(self.description).chars(63) if self.type_of.category == ItemType.CATEGORY.RESOURCE: if self.format_type == Item.FORMAT_TYPE.LINK_RESOURCE_TYPE_OF: return self.title if self.format_type == Item.FORMAT_TYPE.YOUTUBE_VIDEO_RESOURCE_TYPE_OF: return self.title if self.format_type == Item.FORMAT_TYPE.FILE_RESOURCE_TYPE_OF and self.format_type == Item.FORMAT_TYPE.IMAGE_RESOURCE_TYPE_OF: return self.title return str(self.slug) @transaction.atomic def save(self, *args, **kwargs): ''' Override the `save` function to support extra functionality of our model. ''' ''' If we are creating a new row, then we will automatically increment the `id` field instead of relying on Postgres DB. ''' if self.id == None: try: latest_obj = Item.objects.latest('id') self.id = latest_obj.id + 1 except Item.DoesNotExist: self.id = 1 ''' If we are creating a new model, then we will automatically increment the `id`. ''' # The following code will generate a unique slug and if the slug # is not unique in the database, then continue to try generating # a unique slug until it is found. if self.slug == "" or self.slug == None: from tenant_foundation.models.item_type import ItemType if self.type_of.category == ItemType.CATEGORY.EVENT or self.type_of.category == ItemType.CATEGORY.INCIDENT or self.type_of.category == ItemType.CATEGORY.CONCERN or self.type_of.category == ItemType.CATEGORY.RESOURCE: slug = slugify(self.title) while Item.objects.filter(slug=slug).exists(): slug = slugify(self.title) + "-" + get_referral_code(16) self.slug = slug else: self.slug = str(self.id) ''' Finally call the parent function which handles saving so we can carry out the saving operation by Django in our ORM. ''' super(Item, self).save(*args, **kwargs) def get_who_news_for_label(self): return str(dict(Item.WHO_NEWS_FOR_CHOICES).get(self.who_news_for)) def get_state_label(self): return str(dict(Item.STATE).get(self.state))
class Comment(models.Model): ''' METADATA ''' class Meta: app_label = 'tenant_foundation' db_table = 'nwapp_comments' verbose_name = _('Comment') verbose_name_plural = _('Comments') ordering = ['-created_at'] default_permissions = () permissions = () ''' CONSTANTS ''' # class MEMBER_STATE: # ACTIVE = 'active' # INACTIVE = 'inactive' ''' CHOICES ''' # MEMBER_STATE_CHOICES = ( # (MEMBER_STATE.ACTIVE, _('Active')), # (MEMBER_STATE.INACTIVE, _('Inactive')), # ) ''' OBJECT MANAGERS ''' objects = CommentManager() ''' MODEL FIELDS ''' # CUSTOM FIELDS text = models.TextField( _("Text"), help_text=_('The text content of this comment.'), ) is_archived = models.BooleanField( _("Is Archived"), help_text=_('Indicates whether comment was archived.'), default=False, blank=True, db_index=True) # SYSTEM FIELDS uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( SharedUser, help_text=_('The user whom created this away log.'), related_name="created_comments", on_delete=models.SET_NULL, blank=True, null=True) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) created_from_position = models.PointField( _("Created from position"), help_text=_('The latitude and longitude coordinates for the creator.'), srid=4326, geography=True, null=True, blank=True, ) last_modified_at = models.DateTimeField(auto_now=True) last_modified_by = models.ForeignKey( SharedUser, help_text=_('The user whom last modified this away log.'), related_name="last_modified_comments", on_delete=models.SET_NULL, blank=True, null=True) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) last_modified_from_position = models.PointField( _("Last modified from position"), help_text=_( 'The latitude and longitude coordinates for the last modified user.' ), srid=4326, geography=True, null=True, blank=True, ) """ MODEL FUNCTIONS """ def __str__(self): return str(self.text) @transaction.atomic def save(self, *args, **kwargs): ''' Override the `save` function to support extra functionality of our model. ''' ''' If we are creating a new row, then we will automatically increment the `id` field instead of relying on Postgres DB. ''' if self.id == None: try: latest_obj = Comment.objects.latest('id') self.id = latest_obj.id + 1 except Comment.DoesNotExist: self.id = 1 ''' Finally call the parent function which handles saving so we can carry out the saving operation by Django in our ORM. ''' super(Comment, self).save(*args, **kwargs)
class DummyGenericIPAddressFieldModel(models.Model): ipv4_field = models.GenericIPAddressField(protocol="IPv4") ipv6_field = models.GenericIPAddressField(protocol="IPv6") ipv46_field = models.GenericIPAddressField(protocol="both")
class District(models.Model): ''' METADATA ''' class Meta: app_label = 'tenant_foundation' db_table = 'nwapp_districts' verbose_name = _('District') verbose_name_plural = _('Districts') # ordering = ['-created_at'] default_permissions = () permissions = () ''' CONSTANTS ''' class TYPE_OF: RESIDENTIAL = 1 BUSINESS = 2 COMMUNITY_CARES = 3 ''' CHOICES ''' TYPE_OF_CHOICES = ( (TYPE_OF.RESIDENTIAL, _('Residential')), (TYPE_OF.BUSINESS, _('Business')), (TYPE_OF.COMMUNITY_CARES, _('Community Cares')), ) TYPE_OF_CODE_CHOICES = ( (TYPE_OF.RESIDENTIAL, 'rez'), (TYPE_OF.BUSINESS, 'biz'), (TYPE_OF.COMMUNITY_CARES, 'com'), ) ''' OBJECT MANAGERS ''' objects = DistrictManager() ''' MODEL FIELDS ''' # COMMON FIELDS type_of = models.PositiveSmallIntegerField( _("Type of"), help_text=_('The type of score point this is.'), choices=TYPE_OF_CHOICES, db_index=True, ) name = models.CharField( _("Name"), max_length=127, help_text=_('The name of this district.'), unique=True, db_index=True, ) description = models.CharField( _("Description"), help_text=_('The description of this district.'), max_length=255, null=True, blank=True, ) governors = models.ManyToManyField( "Associate", help_text= _('The associates which are responsible for the operation of the district.' ), blank=True, related_name="governing") tags = models.ManyToManyField( "Tag", help_text=_('The tags associated with this district.'), blank=True, related_name="districts") boundry_position = models.PointField( _("Boundry Position"), help_text= _('The centre coordinates to apply for every map rendered on the user\'s screen.' ), srid=4326, geography=True, null=True, blank=True, ) boundry_zoom = models.FloatField( _("Boundry Map Zoom"), help_text= _('The centre zoom to apply for every map rendered on the user\'s screen.' ), null=True, blank=True, ) boundry_polygon = models.PolygonField( _("Boundry Polygon"), help_text=_('The polygon of the district\'s boundry.'), blank=True, null=True, spatial_index=True, ) # RESIDENTIAL FIELDS counselor_name = models.CharField( _("Counselor Name"), help_text=_('The name of this district\'s counselor.'), max_length=127, null=True, blank=True, ) counselor_email = models.EmailField( _("Counselor Email"), help_text=_('The email of this district\'s counselor.'), max_length=127, null=True, blank=True, ) counselor_phone = models.CharField( _("Counselor Phone"), help_text=_('The phone of this district\'s counselor.'), max_length=31, validators=[e164_phone_regex], null=True, blank=True, ) # SOCIAL MEDIA facebook_url = models.URLField( _("Facebook URL"), help_text=_('The URL to the Facebook page.'), blank=True, null=True, default='', ) # BUSINESS FIELDS website_url = models.URLField( _("Website URL"), help_text=_('The external website link of this district.'), max_length=255, null=True, blank=True, ) logo_image = models.ForeignKey( "PrivateImageUpload", help_text=_('The logo image of this district.'), related_name="districts", on_delete=models.SET_NULL, blank=True, null=True, ) # SEARCHABLE FIELDS indexed_text = models.CharField( _("Indexed Text"), max_length=1023, help_text=_( 'The searchable content text used by the keyword searcher function.' ), blank=True, null=True, db_index=True, unique=True) # SYSTEM FIELDS uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) slug = models.SlugField( _("Slug"), help_text=_('The unique identifier used externally.'), max_length=255, null=False, unique=True, db_index=True, ) is_archived = models.BooleanField( _("Is Archived"), help_text=_('Indicates whether district was archived or not'), default=False, blank=True, db_index=True) created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( SharedUser, help_text=_('The user whom created this score point.'), related_name="created_districts", on_delete=models.SET_NULL, blank=True, null=True) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) created_from_position = models.PointField( _("Created from position"), help_text=_('The latitude and longitude coordinates for the creator.'), srid=4326, geography=True, null=True, blank=True, ) last_modified_at = models.DateTimeField(auto_now=True) last_modified_by = models.ForeignKey( SharedUser, help_text=_('The user whom last modified this private image upload.'), related_name="last_modified_districts", on_delete=models.SET_NULL, blank=True, null=True) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) last_modified_from_position = models.PointField( _("Last modified from position"), help_text=_( 'The latitude and longitude coordinates for the last modified user.' ), srid=4326, geography=True, null=True, blank=True, ) """ MODEL FUNCTIONS """ def __str__(self): return str(self.slug) @transaction.atomic def save(self, *args, **kwargs): ''' Override the `save` function to support extra functionality of our model. ''' ''' If we are creating a new row, then we will automatically increment the `id` field instead of relying on Postgres DB. ''' if self.id == None: try: latest_obj = District.objects.latest('id') self.id = latest_obj.id + 1 except District.DoesNotExist: self.id = 1 # Assign our unique slug to this model as our external identifier. if self.slug == None or self.slug == "": # The following code will generate a unique slug and if the slug # is not unique in the database, then continue to try generating # a unique slug until it is found. slug = slugify(self.name) while District.objects.filter(slug=slug).exists(): slug = slugify(self.name) + "-" + get_referral_code(4) self.slug = slug # Update our searchable content. text = str(self.name) + " " + str(self.description) if self.counselor_name: text += str(self.counselor_name) if self.counselor_email: text += " " + str(self.counselor_email) if self.counselor_phone: text += " " + str(self.counselor_phone) if self.website_url: text += " " + str(self.website_url) if self.type_of: text += " " + self.get_type_of_label() if self.slug: text += " " + str(self.slug) self.indexed_text = text ''' Finally call the parent function which handles saving so we can carry out the saving operation by Django in our ORM. ''' super(District, self).save(*args, **kwargs) def get_type_of_label(self): return str(dict(District.TYPE_OF_CHOICES).get(self.type_of)) def get_type_of_code(self): return str(dict(District.TYPE_OF_CODE_CHOICES).get(self.type_of)) @staticmethod def seed(length): from faker import Faker results = [] faker = Faker('en_CA') for i in range(0, length): try: type_of = faker.random_int(min=1, max=3, step=1) name = faker.company() + " District" description = faker.paragraph(nb_sentences=3, variable_nb_sentences=True, ext_word_list=None) counselor_name = faker.name() counselor_email = faker.email() counselor_phone = faker.phone_number() website_url = faker.uri() # print( # type_of, "\n", name, "\n", description, "\n", # counselor_name, "\n", counselor_email, "\n", counselor_phone, "\n", # website_url, "\n", # ) district = District.objects.create( type_of=type_of, name=name, description=description, counselor_name=counselor_name, counselor_email=counselor_email, counselor_phone=counselor_phone, website_url=website_url, ) results.append(district) except Exception as e: print(e) pass return results
class Associate(models.Model): """ Class model represents the Neighbourhood Watch registered area coordinator for the particular tenant. """ ''' METADATA ''' class Meta: app_label = 'tenant_foundation' db_table = 'nwapp_associates' verbose_name = _('Associate') verbose_name_plural = _('Associates') default_permissions = () permissions = () ''' CONSTANTS ''' class STATE: ACTIVE = 'active' INACTIVE = 'inactive' class DEMOTION_REASON: OTHER_REASON = 1 RETIRED_REASON = 2 HEALTH_REASON = 3 NO_LONGER_WANTS_ROLE_REASON = 4 REPRIMAND_REASON = 5 class TYPE_OF: RESIDENTIAL = 1 BUSINESS = 2 COMMUNITY_CARES = 3 ''' CHOICES ''' STATE_CHOICES = ( (STATE.ACTIVE, _('Active')), (STATE.INACTIVE, _('Inactive')), ) DEMOTION_REASON_CHOICES = ( (DEMOTION_REASON.RETIRED_REASON, _('Retired')), (DEMOTION_REASON.HEALTH_REASON, _('Health')), (DEMOTION_REASON.NO_LONGER_WANTS_ROLE_REASON, _('No longer wants role')), (DEMOTION_REASON.REPRIMAND_REASON, _('Reprimand')), (DEMOTION_REASON.OTHER_REASON, _('Other (Please specify)')), ) TYPE_OF_CHOICES = ( (TYPE_OF.BUSINESS, _('Business')), (TYPE_OF.RESIDENTIAL, _('Residential')), (TYPE_OF.COMMUNITY_CARES, _('Community Cares')), ) ''' OBJECT MANAGERS ''' objects = AssociateManager() ''' MODEL FIELDS ''' # SYSTEM FIELDS user = models.OneToOneField( SharedUser, help_text=_('The user whom is an associate.'), related_name="associate", on_delete=models.CASCADE, primary_key=True, ) type_of = models.PositiveSmallIntegerField( _("Type of"), help_text=_('The type of area coordinator this is.'), choices=TYPE_OF_CHOICES, db_index=True, default=TYPE_OF.RESIDENTIAL, ) uuid = models.CharField( _("UUID"), help_text= _('The unique identifier we want to release to the public to identify this unique record.' ), default=uuid.uuid4, editable=False, max_length=63, # Do not change unique=True, db_index=True, ) # BUSINESS LOGIC SPECIFIC FIELDS has_signed_conflict_of_interest_agreement = models.BooleanField( _("Has signed conflict of interest agreement"), default=False, help_text= _('Boolean indicates whether has agreed to the conflict of interest agreement.' ), blank=True, ) conflict_of_interest_agreement = models.TextField( _("Conflict of interest agreement"), help_text= _('The actual terms of conflict of interest agreement the user agreed to when they signed.' ), blank=True, null=True, ) conflict_of_interest_agreement_signed_on = models.DateTimeField( _('Conflict of interest agreement signed on'), help_text=_('The date when the agreement was signed on.'), blank=True, null=True, ) has_signed_code_of_conduct_agreement = models.BooleanField( _("Has signed code of conduct agreement"), default=False, help_text=_( 'Boolean indicates whether has agreed to the code of conduct.'), blank=True, ) code_of_conduct_agreement = models.TextField( _("Code of conduct agreement"), help_text=_( 'The code of conduct agreement the user agreed to when they signed.' ), blank=True, null=True, ) code_of_conduct_agreement_signed_on = models.DateTimeField( _('Code of conduct agreement signed on'), help_text=_( 'The date when the code of conduct agreement was signed on.'), blank=True, null=True, ) has_signed_confidentiality_agreement = models.BooleanField( _("Has signed confidentiality agreement"), default=False, help_text= _('Boolean indicates whether has agreed to the confidentiality agreement.' ), blank=True, ) confidentiality_agreement = models.TextField( _("Confidentiality agreement agreement"), help_text= _('The actual terms of confidentiality agreement the user agreed to when they signed.' ), blank=True, null=True, ) confidentiality_agreement_signed_on = models.DateTimeField( _('Confidentiality agreement signed on'), help_text=_('The date when the agreement was signed on.'), blank=True, null=True, ) has_signed_associate_agreement = models.BooleanField( _("Has signed associate agreement"), default=False, help_text=_( 'Boolean indicates whether has agreed to the associate agreement.' ), blank=True, ) associate_agreement = models.TextField( _("Associate agreement"), help_text= _('The actual terms of associate agreement the user agreed to when they signed.' ), blank=True, null=True, ) associate_agreement_signed_on = models.DateTimeField( _('Associate agreement signed on'), help_text=_('The date when the associate agreement was signed on.'), blank=True, null=True, ) police_check_date = models.DateField( _('Police check date'), help_text=_('The date when the police check was taken on.'), blank=True, null=True, ) demotion_reason = models.PositiveSmallIntegerField( _("Demotion Reason"), help_text=_('The reason for the demotion.'), choices=DEMOTION_REASON_CHOICES, null=True, blank=True, ) demotion_reason_other = models.TextField( _("Demotion Reason (Other)"), help_text=_('The other reason for the demotion.'), blank=True, null=True, ) # MISC watch = models.ForeignKey( "Watch", help_text=_('The watch this associate belongs to.'), related_name="associates", on_delete=models.SET_NULL, blank=True, null=True, ) # AUDITING FIELDS created_at = models.DateTimeField(auto_now_add=True, db_index=True) created_by = models.ForeignKey( SharedUser, help_text=_('The user whom created this object.'), related_name="created_associates", on_delete=models.SET_NULL, blank=True, null=True, ) created_from = models.GenericIPAddressField( _("Created from"), help_text=_('The IP address of the creator.'), blank=True, null=True) created_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is creator a public IP and is routable.'), default=False, blank=True) created_from_position = models.PointField( _("Created from position"), help_text=_('The latitude and longitude coordinates for the creator.'), srid=4326, geography=True, null=True, blank=True, ) last_modified_at = models.DateTimeField(auto_now=True) last_modified_by = models.ForeignKey( SharedUser, help_text=_('The user whom modified this object last.'), related_name="last_modified_associates", on_delete=models.SET_NULL, blank=True, null=True, ) last_modified_from = models.GenericIPAddressField( _("Last modified from"), help_text=_('The IP address of the modifier.'), blank=True, null=True) last_modified_from_is_public = models.BooleanField( _("Is the IP "), help_text=_('Is modifier a public IP and is routable.'), default=False, blank=True) last_modified_from_position = models.PointField( _("Last modified from position"), help_text=_( 'The latitude and longitude coordinates for the last modified user.' ), srid=4326, geography=True, null=True, blank=True, ) # SEARCHABLE FIELDS indexed_text = models.CharField( _("Indexed Text"), max_length=1023, help_text=_( 'The searchable content text used by the keyword searcher function.' ), blank=True, null=True, db_index=True, unique=True) """ MODEL FUNCTIONS """ def __str__(self): ''' Override the `casting` function so we output the following string when an object gets casted to a string. ''' return str(self.user) @transaction.atomic def save(self, *args, **kwargs): ''' Override the `save` function to support extra functionality of our model. ''' ''' Finally call the parent function which handles saving so we can carry out the saving operation by Django in our ORM. ''' super(Associate, self).save(*args, **kwargs) def get_full_name(self): return self.user.get_full_name() def get_pretty_state(self): return str(dict(Associate.STATE_CHOICES).get(self.user.member.state)) def invalidate(self, method_name): #TODO: IMPLEMENT """ Function used to clear the cache for the cached property functions. """ try: pass # if method_name == 'fullname': # del self.fullname # else: # raise Exception("Method name not found.") except AttributeError: pass def invalidate_all(self): self.invalidate("fullname")
class DummyGenericIPAddressFieldModel(models.Model): ipv4_field = models.GenericIPAddressField(protocol='IPv4') ipv6_field = models.GenericIPAddressField(protocol='IPv6') ipv46_field = models.GenericIPAddressField(protocol='both')