Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 51 additions & 0 deletions api/desecapi/migrations/0038_domainserial_and_more.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Generated by Django 5.0 on 2023-12-15 16:09

import django.db.models.deletion
import django_prometheus.models
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("desecapi", "0037_remove_tokendomainpolicy_perm_dyndns"),
]

operations = [
migrations.CreateModel(
name="DomainSerial",
fields=[
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created", models.DateTimeField(auto_now_add=True, db_index=True)),
("updated", models.DateTimeField(null=True)),
("node", models.CharField(max_length=255)),
("serial", models.PositiveBigIntegerField(null=True)),
(
"domain",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
to="desecapi.domain",
),
),
],
bases=(
django_prometheus.models.ExportModelOperationsMixin("DomainSerial"),
models.Model,
),
),
migrations.AddConstraint(
model_name="domainserial",
constraint=models.UniqueConstraint(
fields=("domain", "node", "updated", "serial"),
name="domain_serial_unique_policy",
nulls_distinct=False,
),
),
]
2 changes: 1 addition & 1 deletion api/desecapi/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .authenticated_actions import *
from .base import validate_domain_name, validate_lower, validate_upper
from .captcha import Captcha
from .domains import Domain
from .domains import Domain, DomainSerial
from .donation import Donation
from .mfa import BaseFactor, TOTPFactor
from .records import (
Expand Down
26 changes: 26 additions & 0 deletions api/desecapi/models/domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -297,3 +297,29 @@ def delete(self, *args, **kwargs):

def __str__(self):
return self.name


class DomainSerial(ExportModelOperationsMixin("DomainSerial"), models.Model):
created = models.DateTimeField(auto_now_add=True, db_index=True)
updated = models.DateTimeField(null=True)
domain = models.ForeignKey("Domain", on_delete=models.CASCADE)
node = models.CharField(max_length=255)
serial = models.PositiveBigIntegerField(null=True)

class Meta:
constraints = [
models.UniqueConstraint(
name="domain_serial_unique_policy",
fields=["domain", "node", "updated", "serial"],
nulls_distinct=False,
),
]

def __str__(self):
return "<DomainSerial %s domain=%s node=%s serial=%s updated=%s>" % (
self.pk,
self.domain.name,
self.node,
self.serial,
self.updated,
)
23 changes: 22 additions & 1 deletion api/desecapi/serializers/domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from rest_framework import serializers

from api import settings
from desecapi.models import Domain, RR_SET_TYPES_AUTOMATIC
from desecapi.models import Domain, DomainSerial, RR_SET_TYPES_AUTOMATIC
from desecapi.validators import ReadOnlyOnUpdateValidator

from .records import RRsetSerializer
Expand Down Expand Up @@ -170,3 +170,24 @@ def fqdn(idx):
rrset_list_serializer.save()

return domain


class DomainSerialSerializer(serializers.ModelSerializer):
class Meta:
model = DomainSerializer
fields = (
"created",
"updated",
"domain",
"node",
"serial",
)
read_only_fields = fields

def create(self, validated_data):
# TODO
self.domain.domainserial_set.bulk_create(
[DomainSerial(domain=self.domain, node=node) for node in NODES],
ignore_conflicts=True,
)
return None # TODO
30 changes: 30 additions & 0 deletions api/desecapi/views/domains.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,36 @@ def zonefile(self, request, name=None):
return Response(prefix + instance.zonefile, content_type="text/dns")


class DomainSerialViewSet(
mixins.CreateModelMixin,
mixins.ListModelMixin,
viewsets.GenericViewSet,
):
serializer_class = DomainSerialSerializer
lookup_field = "name"
lookup_value_regex = r"[^/]+"
permission_classes = [
IsAuthenticated,
permissions.MFARequiredIfEnabled,
permissions.IsOwner,
]

@property
def throttle_scope(self):
return (
"dns_api_cheap"
if self.request.method in SAFE_METHODS
else "dns_api_per_domain_expensive"
)

@property
def domain(self):
return self.get_object()

def get_queryset(self):
return self.domain.domainserial_set.all() # TODO


class SerialListView(APIView):
permission_classes = (permissions.IsVPNClient,)
throttle_classes = (
Expand Down