Skip to content

Commit

Permalink
Merge pull request #99 from BiznetGIO/fix/serial-check
Browse files Browse the repository at this point in the history
Fix: check serial limit
  • Loading branch information
anak10thn authored May 14, 2020
2 parents 876f7da + 38ee7ab commit 54698b8
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 26 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
Unreleased
==========

0.7.3 (2020-05-14)
==================

- Add: check SOA serial limit before any operation
- Fix: reset serial counter if day changed

0.7.2 (2020-05-13)
==================

Expand Down
74 changes: 56 additions & 18 deletions api/app/controllers/api/record.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,49 @@
from app.vendors.rest import response


def update_serial(zone, increment="01"):
def get_serial_resource(zone):
soa_record = record_model.get_soa_record(zone)
rdata_record = model.get_one(
table="rdata", field="record_id", value=soa_record["id"]
)
rdatas = rdata_record["rdata"].split(" ")
serial = rdatas[2] # serial MUST be in this position
serial = rdatas[2]
# `serial_counter` is the last two digit of serial value (YYYYMMDDnn)
serial_counter = serial[-2:]
serial_date = serial[:-2]

return {
"soa_record": soa_record,
"rdata_record": rdata_record,
"serial": serial,
"serial_counter": serial_counter,
"serial_date": serial_date,
}


def check_serial_limit(serial_resource):
serial_counter = serial_resource["serial_counter"]
serial_date = serial_resource["serial_date"]
today_date = helpers.soa_time_set()

if int(serial_counter) > 97 and serial_date == today_date:
# knot maximum of nn is 99
# 97 was chosen because serial
# increment can be twice at time
raise ValueError("Zone Change Limit Reached")


def update_serial(serial_resource, increment="01"):
serial = serial_resource["serial"]
soa_record = serial_resource["soa_record"]
rdata_record = serial_resource["rdata_record"]

new_serial = helpers.increment_serial(serial, increment)
new_rdata = helpers.replace_serial(rdata_record["rdata"], new_serial)

content_data = {
"where": {"record_id": soa_record["id"]},
"data": {"rdata": new_rdata, "record_id": soa_record["id"]},
}

model.update("rdata", data=content_data)


Expand Down Expand Up @@ -109,6 +137,12 @@ def post(self):
except Exception as e:
return response(422, message=f"{e}")

try:
serial_resource = get_serial_resource(zone)
check_serial_limit(serial_resource)
except Exception as e:
return response(429, message=f"{e}")

try:
data = {
"owner": owner,
Expand All @@ -126,10 +160,7 @@ def post(self):
# increment serial after adding new record
rtype = type_model.get_type_by_recordid(record_id)
if rtype != "SOA":
try:
update_serial(zone)
except Exception as e:
return response(429, message=f"{e}")
update_serial(serial_resource)

record = model.get_one(table="record", field="id", value=record_id)
data = record_model.get_other_data(record)
Expand Down Expand Up @@ -176,6 +207,12 @@ def put(self, record_id):
except Exception as e:
return response(422, message=f"{e}")

try:
serial_resource = get_serial_resource(zone)
check_serial_limit(serial_resource)
except Exception as e:
return response(429, message=f"{e}")

try:
data = {
"where": {"id": record_id},
Expand All @@ -201,10 +238,7 @@ def put(self, record_id):
# increment serial after adding new record
rtype = type_model.get_type_by_recordid(record_id)
if rtype != "SOA":
try:
update_serial(zone, "02")
except Exception as e:
return response(429, message=f"{e}")
update_serial(serial_resource, "02")

record = model.get_one(table="record", field="id", value=record_id)
data_ = record_model.get_other_data(record)
Expand All @@ -229,17 +263,21 @@ def delete(self, record_id):
except Exception:
return response(404)

zone = zone_model.get_zone_by_record(record_id)
zone_name = zone["zone"]

try:
serial_resource = get_serial_resource(zone_name)
check_serial_limit(serial_resource)
except Exception as e:
return response(429, message=f"{e}")

try:
rtype = type_model.get_type_by_recordid(record_id)
if rtype == "SOA":
return response(403, message=f"Can't Delete SOA Record")
if rtype != "SOA":
zone = zone_model.get_zone_by_record(record_id)
zone_name = zone["zone"]
try:
update_serial(zone_name)
except Exception as e:
return response(429, message=f"{e}")
update_serial(serial_resource)

command.set_zone(record_id, "zone-unset")

Expand Down
15 changes: 7 additions & 8 deletions api/app/helpers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,17 @@ def increment_serial(serial, increment="01"):
Keyword arguments:
increment -- the increment value (default "01")
"""
current_time = soa_time_set()
previous_time = serial[:-2]
today_date = soa_time_set()
record_date = serial[:-2]
# The 10-digit serial (YYYYMMDDnn) is incremented, the first
# 8 digits match the current iso-date
nn = serial[-2:]
if int(nn) > 97 and previous_time == current_time:
# knot maximum of nn is 99
# 97 was chosen because serial
# increment can be twice at time
raise ValueError("Zone Change Limit Reached")
if record_date != today_date:
# date changed, reset `nn`
nn = "01"

increment = add_str(nn, increment)
return f"{current_time}{increment}"
return f"{today_date}{increment}"


def get_datetime():
Expand Down
20 changes: 20 additions & 0 deletions api/tests/integration/test_record.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import datetime

import app.helpers.helpers
from app.controllers.api import record as record_api
from app.helpers import helpers


class TestRecord:
Expand Down Expand Up @@ -413,7 +415,17 @@ def test_edit_record_respect_zone_limit(self, client, monkeypatch, mocker):
assert edit_record_data["code"] == 429
assert edit_record_data["message"] == "Zone Change Limit Reached"

# ensure correct serial
serial_resource = record_api.get_serial_resource("company.com")
today_date = helpers.soa_time_set()

assert serial_resource["serial_counter"] == "98"
assert serial_resource["serial_date"] == today_date
assert serial_resource["serial"] == f"{today_date}98"

#
# if user waits until tomorrow
#
def fake_soa_time_set():
tomorrow_date = datetime.datetime.now() + datetime.timedelta(days=1)
return tomorrow_date.strftime("%Y%m%d")
Expand All @@ -430,3 +442,11 @@ def fake_soa_time_set():
edit_record_data = res.get_json()

assert edit_record_data["code"] == 200

# ensure correct serial
serial_resource = record_api.get_serial_resource("company.com")
today_date = helpers.soa_time_set()

assert serial_resource["serial_counter"] == "03"
assert serial_resource["serial_date"] == today_date
assert serial_resource["serial"] == f"{today_date}03"

0 comments on commit 54698b8

Please sign in to comment.