class Favourites(models.Model): name = models.CharField(max_length=100) color = ChoiceField(choices=Color, default=Color.green) music = ChoiceField(choices=MusicGenre, filter=('rock', 'country', 'banjo')) sport = ChoiceField(choices=Sports, grouped=True) nullable = ChoiceField(choices=Color, default=None, null=True, blank=True) @classmethod def create(cls, **kwargs): defaults = { 'music': MusicGenre.banjo, 'sport': Sports.poker, 'color': Color.green, 'nullable': None, } defaults.update(kwargs) return cls.objects.create(**defaults)
class User(models.Model): gender = ChoiceField(choices=Gender, default=Gender.not_specified) def greet(self): if self.gender == Gender.male: return 'Boy' elif self.gender == Gender.female: return 'Hello, girl.' else: return 'Hey there, user!'
class Department(Named): icon = ChoiceField(verbose_name=_("icon"), choices=DepartmentIcon, default=None, null=True, blank=True) class Meta: verbose_name = _("department") verbose_name_plural = _("departments") ordering = ('name', )
class Pizza(models.Model): name = models.CharField(max_length=50, verbose_name=u"Nome") description = models.TextField(verbose_name=u"Descrição/Ingredientes") created = models.DateTimeField(auto_now_add=True, verbose_name=u"Data de criação") price = models.DecimalField(decimal_places=2, max_digits=5, verbose_name=u"Preço R$") category = ChoiceField(choices=Category, default=Category.normal, verbose_name=u"Categoria") def __str__(self): return self.name
class SCMStatusCheck(PermByFieldMixin, TimeStampMixin, models.Model): """Represents software configuration management scan.""" base_object = models.OneToOneField(BaseObject, on_delete=models.CASCADE) last_checked = models.DateTimeField(blank=False, null=False, verbose_name=_("Last SCM check")) check_result = ChoiceField(choices=SCMCheckResult, blank=False, null=False, verbose_name=_("SCM check result")) ok = models.BooleanField(default=False, editable=False) def save(self, *args, **kwargs): self.ok = self.check_result == SCMCheckResult.scm_ok.id super().save(*args, **kwargs)
class AnimalWeigthModel(TimeStampedModel): farm = models.ForeignKey(FarmModel, on_delete=models.CASCADE, related_name=_('animal_witgth_farm')) type_animal = ChoiceField(choices=AnimalChoice, default=AnimalChoice.bovino, verbose_name=_('Tipo do Animal')) weigth = models.DecimalField(max_digits=10, decimal_places=2, null=False, blank=False, verbose_name=_('Peso do animal')) earring_number = models.CharField(max_length=15, verbose_name=_('Número do brinco'), null=False, blank=False)
class Admin(AbstractBaseUser): """An user of the console. Only admins have access to the console.""" LEVELS = AdminLevels USERNAME_FIELD = 'email' email = models.EmailField(verbose_name=_("Email"), unique=True) level = ChoiceField(verbose_name=_("Level"), choices=LEVELS, default=LEVELS.ADMIN) objects = BaseUserManager() class Meta: ordering = ('-level', 'email') @property def is_root_admin(self): return self.level == self.LEVELS.ROOT_ADMIN
class PrebootFile(Named): ftype = ChoiceField(verbose_name=_("file type"), choices=FileType, default=FileType.other) raw_config = db.TextField(verbose_name=_("raw config"), blank=True) file = db.FileField(verbose_name=_("file"), upload_to=preboot_file_name, null=True, blank=True, default=None) class Meta: verbose_name = _("preboot file") verbose_name_plural = _("preboot files") def __unicode__(self): return "_{}: {}".format(self.get_ftype_display(), self.name) def get_filesize_display(self): template = """binary {size:.2f} MB""" return template.format(size=self.file.size / 1024 / 1024, )
class DomainTemplate(models.Model): """A predefined template containing several record templates""" copy_fields = ['record_auto_ptr', 'type'] name = models.CharField(_('Template identifier'), unique=True, max_length=255) objects = DomainTemplateManager() type = models.CharField( _("type"), max_length=6, blank=True, null=True, choices=Domain.DOMAIN_TYPE, help_text=_("Record type"), ) record_auto_ptr = ChoiceField( choices=AutoPtrOptions, default=AutoPtrOptions.ALWAYS, ) def __str__(self): return self.name def natural_key(self): return (self.name, ) def add_domain_url(self): """Return URL for 'Add domain' action""" return (reverse('admin:powerdns_domain_add') + '?template={}'.format(self.pk)) def add_domain_link(self): return '<a href="{}">Create domain</a>'.format(self.add_domain_url()) add_domain_link.allow_tags = True def extra_buttons(self): yield (self.add_domain_url(), 'Create domain')
class VehicleModel(models.Model): name = models.CharField( max_length=100, blank=False, null=False) model = ChoiceField( choices=ModelsTypesChoices, default=ModelsTypesChoices.car) engine = models.FloatField( null=False, blank=False) automaker = models.ForeignKey( AutoMaker, related_name='auto_maker', on_delete=models.PROTECT) def __str__(self): return 'AutoMaker {} - engine {} - model - {}'.format( self.automaker.name, self.engine, self.model)
class PrebootFile(Named): ftype = ChoiceField( _("file type"), choices=FileType, default=FileType.other, ) raw_config = db.TextField( _("raw config"), blank=True, help_text=_("All newline characters will be converted to Unix \\n " "newlines. You can use {{variables}} in the body. " "Available variables: filename, filetype, mac, ip, " "hostname, venture and venture_role."), ) file = db.FileField( _("file"), upload_to=preboot_file_name, null=True, blank=True, default=None, ) description = db.TextField( verbose_name=_("description"), blank=True, default="", ) class Meta: verbose_name = _("preboot file") verbose_name_plural = _("preboot files") def __unicode__(self): return "_{}: {}".format(self.get_ftype_display(), self.name) def get_filesize_display(self): template = """binary {size:.2f} MB""" return template.format(size=self.file.size / 1024 / 1024, )
class BoundPerm(TimeTrackable, EditorTrackable): profile = db.ForeignKey( Profile, verbose_name=_("profile"), null=True, blank=True, default=None, ) group = db.ForeignKey( Group, verbose_name=_("group"), null=True, blank=True, default=None, ) perm = ChoiceField(verbose_name=_("permission"), choices=Perm) venture = db.ForeignKey( Venture, verbose_name=_("venture"), null=True, blank=True, default=None, ) role = db.ForeignKey( VentureRole, verbose_name=_("venture role"), null=True, blank=True, default=None, help_text=_("if left empty, the permission applies to all roles " "within the selected venture"), ) class Meta: verbose_name = _("bound permission") verbose_name_plural = _("bound permissions")
class CILayer(TimeTrackable): # to save compatibility with SlugField from Django 1.3 and don't broke # migration in SQLite... name = models.CharField(max_length=50, db_index=True) connected_types = models.ManyToManyField( CIType, verbose_name=_('CI type'), blank=True, ) icon = ChoiceField( verbose_name=_('icon'), choices=CILayerIcon, default=None, null=True, blank=True, ) class Meta: verbose_name = _('CI layer') verbose_name_plural = _('CI layers') ordering = ('name', ) def __unicode__(self): return " %s " % self.name
class Domain(TimeTrackable, Owned, WithRequests): ''' PowerDNS domains ''' DOMAIN_TYPE = ( ('MASTER', 'MASTER'), ('NATIVE', 'NATIVE'), ('SLAVE', 'SLAVE'), ) copy_fields = ['record_auto_ptr'] name = models.CharField( _("name"), unique=True, max_length=255, validators=[validate_domain_name, SubDomainValidator()]) master = models.CharField( _("master"), max_length=128, blank=True, null=True, ) last_check = models.IntegerField(_("last check"), blank=True, null=True) type = models.CharField( _("type"), max_length=6, blank=True, null=True, choices=DOMAIN_TYPE, ) notified_serial = models.PositiveIntegerField( _("notified serial"), blank=True, null=True, ) account = models.CharField( _("account"), max_length=40, blank=True, null=True, ) remarks = models.TextField(_('Additional remarks'), blank=True) template = models.ForeignKey( 'powerdns.DomainTemplate', verbose_name=_('Template'), blank=True, null=True, ) reverse_template = models.ForeignKey( 'powerdns.DomainTemplate', verbose_name=_('Reverse template'), blank=True, null=True, related_name='reverse_template_for', help_text=_( 'A template that should be used for reverse domains when ' 'PTR templates are automatically created for A records in this ' 'template.')) record_auto_ptr = ChoiceField( choices=AutoPtrOptions, default=AutoPtrOptions.ALWAYS, help_text=_('Should A records have auto PTR by default')) class Meta: db_table = u'domains' verbose_name = _("domain") verbose_name_plural = _("domains") def __str__(self): return self.name def clean(self): self.name = self.name.lower() def save(self, *args, **kwargs): # This save can trigger creating some templated records. # So we do it atomically with transaction.atomic(): super(Domain, self).save(*args, **kwargs) def get_soa(self): """Returns the SOA record for this domain""" try: return Record.objects.get(type='SOA', domain=self) except Record.DoesNotExist: return def add_record_url(self, authorised): """Return URL for 'Add record' action""" model = 'record' if authorised else 'recordrequest' return (reverse('admin:powerdns_{}_add'.format(model)) + '?domain={}'.format(self.pk)) def add_record_link(self): authorised = get_current_user().has_perm('powerdns.change_domain', self) return '<a href="{}">{}</a>'.format( self.add_record_url(authorised), ('Add record' if authorised else 'Request record')) add_record_link.allow_tags = True def extra_buttons(self): authorised = get_current_user().has_perm('powerdns.change_domain', self) yield (self.add_record_url(authorised), 'Add record')
class Profile(BasicInfo, ActivationSupport, GravatarSupport, MonitoredActivity): class Meta: verbose_name = _("profile") verbose_name_plural = _("profiles") home_page = ChoiceField( choices=AvailableHomePage, default=AvailableHomePage.default, ) # TODO: define fields below and add AUTH_LDAP_PROFILE_ATTR_MAP mappings company = db.CharField(max_length=64, blank=True) employee_id = db.CharField(max_length=64, blank=True) profit_center = db.CharField(max_length=1024, blank=True) cost_center = db.CharField(max_length=1024, blank=True) department = db.CharField(max_length=64, blank=True) manager = db.CharField(max_length=1024, blank=True) location = db.CharField(max_length=128, blank=True) def __unicode__(self): return self.nick def has_perm(self, perm, obj=None, role=None): if not self.is_active: return False if self.is_superuser: return True if isinstance(perm, Choices.Choice): groups = self.groups.all() if obj: return BoundPerm.objects.filter( db.Q(venture=None) | db.Q(venture=obj) | db.Q(venture__parent=obj) | db.Q(venture__parent__parent=obj) | db.Q(venture__parent__parent__parent=obj), db.Q(role=None) | db.Q(role=role) | db.Q(role__parent=role) | db.Q(role__parent__parent=role) | db.Q(role__parent__parent__parent=role), db.Q(profile=self) | db.Q(group__in=groups), perm=perm.id, ).exists() else: return BoundPerm.objects.filter( db.Q(role=None) | db.Q(role=role), db.Q(profile=self) | db.Q(group__in=groups), venture=None, perm=perm.id, ).exists() return super(Profile, self).has_perm(perm, obj) def perm_ventures(self, perm): """Lists all ventures to which the user has permission.""" if not self.is_active: return [] groups = self.groups.all() if self.is_superuser or BoundPerm.objects.filter( db.Q(profile=self) | db.Q(group__in=groups), perm=perm.id, venture=None, ).exists(): return Venture.objects.all() return Venture.objects.filter( db.Q(boundperm__profile=self) | db.Q(boundperm__group__in=groups), boundperm__perm=perm.id, ) def filter_by_perm(self, query, perm): """Filters a device search query according to the permissions.""" profile = self if not profile.is_active: return query.none() if profile.is_superuser or profile.has_perm(perm): return query groups = self.groups.all() return query.filter( db.Q(venture__boundperm__profile=profile, venture__boundperm__perm=perm.id) | db.Q(venture__parent__boundperm__profile=profile, venture__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__boundperm__profile=profile, venture__parent__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__parent__boundperm__profile=profile, venture__parent__parent__parent__boundperm__perm=perm.id) | db.Q(venture__boundperm__group__in=groups, venture__boundperm__perm=perm.id) | db.Q(venture__parent__boundperm__group__in=groups, venture__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__boundperm__group__in=groups, venture__parent__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__parent__boundperm__group__in=groups, venture__parent__parent__parent__boundperm__perm=perm.id) ).distinct()
class Profile(BasicInfo, ActivationSupport, GravatarSupport, MonitoredActivity): class Meta: verbose_name = _("profile") verbose_name_plural = _("profiles") home_page = ChoiceField( choices=AvailableHomePage, default=AvailableHomePage.default, ) def __unicode__(self): return self.nick def has_perm(self, perm, obj=None, role=None): if not self.is_active: return False if self.is_superuser: return True if isinstance(perm, Choices.Choice): groups = self.groups.all() if obj: return BoundPerm.objects.filter( db.Q(venture=None) | db.Q(venture=obj) | db.Q(venture__parent=obj) | db.Q(venture__parent__parent=obj) | db.Q(venture__parent__parent__parent=obj), db.Q(role=None) | db.Q(role=role) | db.Q(role__parent=role) | db.Q(role__parent__parent=role) | db.Q(role__parent__parent__parent=role), db.Q(profile=self) | db.Q(group__in=groups), perm=perm.id, ).exists() else: return BoundPerm.objects.filter( db.Q(role=None) | db.Q(role=role), db.Q(profile=self) | db.Q(group__in=groups), venture=None, perm=perm.id, ).exists() return super(Profile, self).has_perm(perm, obj) def perm_ventures(self, perm): """Lists all ventures to which the user has permission.""" if not self.is_active: return [] groups = self.groups.all() if self.is_superuser or BoundPerm.objects.filter( db.Q(profile=self) | db.Q(group__in=groups), perm=perm.id, venture=None, ).exists(): return Venture.objects.all() return Venture.objects.filter( db.Q(boundperm__profile=self) | db.Q(boundperm__group__in=groups), boundperm__perm=perm.id, ) def filter_by_perm(self, query, perm): """Filters a device search query according to the permissions.""" profile = self if not profile.is_active: return query.none() if profile.is_superuser or profile.has_perm(perm): return query groups = self.groups.all() return query.filter( db.Q(venture__boundperm__profile=profile, venture__boundperm__perm=perm.id) | db.Q(venture__parent__boundperm__profile=profile, venture__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__boundperm__profile=profile, venture__parent__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__parent__boundperm__profile=profile, venture__parent__parent__parent__boundperm__perm=perm.id) | db.Q(venture__boundperm__group__in=groups, venture__boundperm__perm=perm.id) | db.Q(venture__parent__boundperm__group__in=groups, venture__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__boundperm__group__in=groups, venture__parent__parent__boundperm__perm=perm.id) | db.Q(venture__parent__parent__parent__boundperm__group__in=groups, venture__parent__parent__parent__boundperm__perm=perm.id) ).distinct()
class RecordTemplate(models.Model): """A predefined record template that would cause a corresponding record to be created.""" objects = RecordTemplateManager() domain_template = models.ForeignKey(DomainTemplate, verbose_name=_('Domain template')) type = models.CharField( _("type"), max_length=6, blank=True, null=True, choices=Record.RECORD_TYPE, help_text=_("Record type"), ) name = models.CharField(_('name'), max_length=255) content = models.CharField(_('content'), max_length=255) ttl = models.PositiveIntegerField( _("TTL"), blank=True, null=True, default=3600, help_text=_("TTL in seconds"), ) prio = models.PositiveIntegerField( _("priority"), blank=True, null=True, help_text=_("For MX records, this should be the priority of the" " mail exchanger specified"), ) auth = models.NullBooleanField( _("authoritative"), help_text=_("Should be set for data for which is itself" " authoritative, which includes the SOA record and our own" " NS records but not set for NS records which are used for" " delegation or any delegation related glue (A, AAAA)" " records"), default=True, ) remarks = models.TextField(_('Additional remarks'), blank=True) auto_ptr = ChoiceField( _('Auto PTR field'), choices=AutoPtrOptions, default=AutoPtrOptions.ALWAYS, ) def natural_key(self): return (self.domain_template.name, self.type, self.name, self.content) def __str__(self): if self.prio is not None: content = "%d %s" % (self.prio, self.content) else: content = self.content return "%s IN %s %s" % (self.name, self.type, content) def get_kwargs(self, domain): kwargs = {} template_kwargs = { 'domain-name': domain.name, } for argname in ['type', 'ttl', 'prio', 'auth', 'auto_ptr']: kwargs[argname] = getattr(self, argname) for argname in ['name', 'content']: kwargs[argname] = getattr(self, argname).format(**template_kwargs) kwargs['template'] = self kwargs['domain'] = domain return kwargs def create_record(self, domain): """Creates, saves and returns a record for this domain""" kwargs = self.get_kwargs(domain) record = Record.objects.create(**kwargs) return record def update_record(self, record): kwargs = self.get_kwargs(record.domain) for kwarg, value in kwargs.items(): setattr(record, kwarg, value)
class Record(TimeTrackable, Owned, WithRequests): ''' PowerDNS DNS records ''' RECORD_TYPE = [(r, r) for r in RECORD_TYPES] domain = models.ForeignKey( Domain, verbose_name=_("domain"), ) name = models.CharField( _("name"), max_length=255, blank=True, null=True, validators=[validate_domain_name], help_text=_("Actual name of a record. Must not end in a '.' and be" " fully qualified - it is not relative to the name of the" " domain!"), ) type = models.CharField( _("type"), max_length=6, blank=True, null=True, choices=RECORD_TYPE, help_text=_("Record qtype"), ) content = models.CharField( _("content"), max_length=255, blank=True, null=True, help_text=_("The 'right hand side' of a DNS record. For an A" " record, this is the IP address"), ) number = models.PositiveIntegerField(_("IP number"), null=True, blank=True, default=None, editable=False, db_index=True) ttl = models.PositiveIntegerField( _("TTL"), blank=True, null=True, default=3600, help_text=_("TTL in seconds"), ) prio = models.PositiveIntegerField( _("priority"), blank=True, null=True, help_text=_("For MX records, this should be the priority of the" " mail exchanger specified"), ) change_date = models.PositiveIntegerField( _("change date"), blank=True, null=True, help_text=_("Set automatically by the system to trigger SOA" " updates and slave notifications"), ) ordername = models.CharField( _("DNSSEC Order"), max_length=255, blank=True, null=True, ) auth = models.NullBooleanField( _("authoritative"), help_text=_("Should be set for data for which is itself" " authoritative, which includes the SOA record and our own" " NS records but not set for NS records which are used for" " delegation or any delegation related glue (A, AAAA)" " records"), default=True, ) disabled = models.BooleanField( _("Disabled"), help_text=_("This record should not be used for actual DNS queries." " Note - this field works for pdns >= 3.4.0"), default=False, ) remarks = models.TextField(blank=True) template = models.ForeignKey( 'powerdns.RecordTemplate', verbose_name=_('Template'), blank=True, null=True, ) depends_on = models.ForeignKey( 'self', null=True, blank=True, verbose_name=_('Dependent on'), help_text=_( 'This record is maintained automatically for another record. It ' 'should be automatically updated/deleted. Used for PTR records' 'that depend on A records.')) auto_ptr = ChoiceField( _('Auto PTR record'), choices=AutoPtrOptions, default=AutoPtrOptions.ALWAYS, ) class Meta: db_table = u'records' ordering = ('name', 'type') unique_together = ('name', 'type', 'content') verbose_name = _("record") verbose_name_plural = _("records") def __str__(self): if self.prio is not None: content = "%d %s" % (self.prio, self.content) else: content = self.content return "%s IN %s %s" % (self.name, self.type, content) def _generate_ordername(self): ''' Check which DNSSEC Mode the domain is in and fill the `ordername` field depending on the mode. ''' cryptokey = CryptoKey.objects.filter(domain=self.domain) if not cryptokey.count(): return None metadata = DomainMetadata.objects.filter(domain=self.domain) nsec3param = metadata.filter(kind='NSEC3PARAM') nsec3narrow = metadata.filter(kind='NSEC3NARROW') if nsec3param.count(): if nsec3narrow.count(): # When running in NSEC3 'Narrow' mode, the ordername field is # ignored and best left empty. return '' return self._generate_ordername_nsec3(nsec3param[0]) return self._generate_ordername_nsec() def _generate_ordername_nsec(self): ''' In 'NSEC' mode, it should contain the relative part of a domain name, in reverse order, with dots replaced by spaces ''' domain_words = self.domain.name.split('.') host_words = self.name.split('.') relative_word_count = len(host_words) - len(domain_words) relative_words = host_words[0:relative_word_count] ordername = ' '.join(relative_words[::-1]) return ordername def _generate_ordername_nsec3(self, nsec3param): ''' In 'NSEC3' non-narrow mode, the ordername should contain a lowercase base32hex encoded representation of the salted & iterated hash of the full record name. "pdnssec hash-zone-record zone record" can be used to calculate this hash. ''' try: algo, flags, iterations, salt = nsec3param.content.split() if algo != '1': raise ValueError("Incompatible hash algorithm.") if flags != '1': raise ValueError("Incompatible flags.") salt = salt.decode('hex') # convert the record name to the DNSSEC canonical form, e.g. # a format suitable for digesting in hashes record_name = '%s.' % self.name.lower().rstrip('.') parts = ["%s%s" % (chr(len(x)), x) for x in record_name.split('.')] record_name = ''.join(parts) except (ValueError, TypeError, AttributeError): return None # incompatible input record_name = self._sha1(record_name, salt) i = 0 while i < int(iterations): record_name = self._sha1(record_name, salt) i += 1 result = base64.b32encode(record_name) result = result.translate(b32_trans) return result.lower() def _sha1(self, value, salt): s = hashlib.sha1() s.update(value) s.update(salt) return s.digest() def clean_content_field(self): """Perform a type-dependent validation of content field""" if self.type == 'A': validate_ipv4_address(self.content) elif self.type == 'AAAA': validate_ipv6_address(self.content) elif self.type == 'SOA': validate_soa(self.content) elif self.type in DOMAIN_NAME_RECORDS: validate_domain_name(self.content) def force_case(self): """Force the name and content case to upper and lower respectively""" if self.name: self.name = self.name.lower() if self.type: self.type = self.type.upper() def validate_for_conflicts(self): """Ensure this record doesn't conflict with other records.""" def check_unique(comment, **kwargs): conflicting = Record.objects.filter(**kwargs) if self.pk is not None: conflicting = conflicting.exclude(pk=self.pk) if conflicting: raise ValidationError( comment.format(', '.join( str(record.id) for record in conflicting))) if self.type == 'CNAME': check_unique( 'Cannot create CNAME record. Following conflicting ' 'records exist: {}', name=self.name, ) else: check_unique( 'Cannot create a record. Following conflicting CNAME' 'record exists: {}', type='CNAME', name=self.name, ) def clean(self): self.clean_content_field() self.force_case() self.validate_for_conflicts() return super(Record, self).clean() def save(self, *args, **kwargs): self.change_date = int(time.time()) self.ordername = self._generate_ordername() if self.type == 'A': self.number = IP(self.content).int() super(Record, self).save(*args, **kwargs) def delete_ptr(self): Record.objects.filter(depends_on=self).delete() def create_ptr(self): """Creates a PTR record for A record creating a domain if necessary.""" if self.type != 'A': raise ValueError(_('Creating PTR only for A records')) domain_name, number = to_reverse(self.content) if self.auto_ptr == AutoPtrOptions.ALWAYS: domain, created = Domain.objects.get_or_create( name=domain_name, defaults={ 'template': (self.domain.reverse_template or get_default_reverse_domain()) }) elif self.auto_ptr == AutoPtrOptions.ONLY_IF_DOMAIN: try: domain = Domain.objects.get(name=domain_name) except Domain.DoesNotExist: return else: return self.delete_ptr() Record.objects.create( type='PTR', domain=domain, name='.'.join([number, domain_name]), content=self.name, depends_on=self, owner=self.owner, )