Ejemplo n.º 1
0
class Menu(models.Model):
    name = models.CharField(max_length=100)
    currency = models.ForeignKey(Currency,
                                 on_delete=models.PROTECT,
                                 default=set_default_currency(),
                                 null=True,
                                 blank=True)
    price = models.DecimalField(max_digits=19, decimal_places=2)
    type = ChoiceField(choices=MenuType, default=MenuType.NotSpecified)
    image = models.ImageField(null=True, blank=True, default='image_avail.png')
    date_last_modified = models.DateTimeField(auto_now=True)
    date_added = models.DateTimeField(auto_now_add=True)
    objects = models.Manager()

    class Meta:
        verbose_name_plural = 'Menu'
        verbose_name = 'Menu'

    def __str__(self):
        return '{}{}'.format(self.name, self.price)

    def save(self, *args, **kwargs):
        if self.pk is None:
            if self.currency is None:
                currency = Currency.objects.get(code='USD')
                self.currency = currency
        super(Menu, self).save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('menu-details', args=[str(self.id)])
Ejemplo n.º 2
0
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")
Ejemplo n.º 3
0
class Group(models.Model):
    QUAD_FORMAT_PATTERN = re.compile(
        """
            ^
                (?P<area> # which functional area, or 'gds' for all
                    gds | govuk | pdu | transformation
                )
            -
                (?P<subject_type> # eg team, role, topic, repo, contact
                    [a-z0-9]+
                )
            -
                (?P<subject> # the team, role, etc
                    [a-z0-9-]+
                )
            -
                (?P<list_type>
                    announce | discuss | members
                )
            @
        """, re.IGNORECASE | re.VERBOSE)

    name = models.CharField(max_length=256)
    email = models.CharField(max_length=256)
    description = models.CharField(max_length=256)
    slug = AutoSlugField(populate_from='name', unique=True)

    # memberships
    members = models.ManyToManyField(Person, through='Membership')
    sublists = models.ManyToManyField('self',
                                      symmetrical=False,
                                      blank=True,
                                      null=True)

    # state
    state = ChoiceField(choices=GroupState, default=GroupState.unknown)
    area = models.CharField(max_length=256, blank=True, null=True)
    subject_type = models.CharField(max_length=256, blank=True, null=True)
    subject = models.CharField(max_length=256, blank=True, null=True)
    list_type = models.CharField(max_length=256, blank=True, null=True)

    def owners(self):
        return self.membership_set.filter(role='OWNER')

    def get_absolute_url(self):
        return reverse('group-detail', kwargs={'slug': self.slug})

    def __unicode__(self):
        return self.email

    def save(self, *args, **kwargs):
        quads = self.QUAD_FORMAT_PATTERN.match(self.email)
        if quads is not None:
            self.state = GroupState.format_one
            self.area = quads.group('area')
            self.subject_type = quads.group('subject_type')
            self.subject = quads.group('subject')
            self.list_type = quads.group('list_type')
        super(Group, self).save(*args, **kwargs)
Ejemplo n.º 4
0
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',)
Ejemplo n.º 5
0
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)
Ejemplo n.º 6
0
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!'
Ejemplo n.º 7
0
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
Ejemplo n.º 8
0
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)
Ejemplo n.º 9
0
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)
Ejemplo n.º 10
0
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
Ejemplo n.º 11
0
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, )
Ejemplo n.º 12
0
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')
Ejemplo n.º 13
0
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)
Ejemplo n.º 14
0
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, )
Ejemplo n.º 15
0
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
Ejemplo n.º 16
0
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')
Ejemplo n.º 17
0
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()
Ejemplo n.º 18
0
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()
Ejemplo n.º 19
0
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,
        )
Ejemplo n.º 20
0
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)