Conversation
| @@ -1,6 +1,5 @@ | |||
| """Forms for domain management.""" | |||
|
|
|||
| import logging | |||
There was a problem hiding this comment.
didn't realize we weren't logging anything in forms - thank you for removing this!
… for cname on the form. Cleaned up the file a bit. Tiny refactor to minimize db calls.
ba337aa to
3d2162e
Compare
There was a problem hiding this comment.
Wires the existing CNAME "name must not equal hostname" check into the model's clean() so it runs on every save. Also handles the shorthand (@ expands to the domain, www expands to www.example.gov) so users can't bypass the check by typing the name in a different format. Pulls the zone's domain name lookup into a single helper (_resolve_domain_name) so it isn't queried twice per clean().
There was a problem hiding this comment.
Adds a test class covering the form-level CNAME self-loop check across the three name shapes users can submit: FQDN, bare label, and @, plus the happy path. Also enables the previously-disabled CNAME entries in the shared test fixtures so the generic form-validation tests now cover CNAME alongside A/AAAA/MX.
There was a problem hiding this comment.
Mirrors the form tests at the model layer by exercising DnsRecord.clean() directly. Confirms CNAME self-loops are rejected for every name shape and that the check is skipped when it shouldn't fire — empty content, or non-CNAME types where name == content is ok. Guards against regressions if a future code path saves a record while bypassing the form.
| vendor_dns_record=vendor_dns_record, | ||
| ) | ||
|
|
||
| except Exception as e: |
There was a problem hiding this comment.
logger.exception automatically attaches the traceback of the currently-handled exception. The old logger.error(f"...{str(e)}") only logged the exception's string form (e.g. "connection refused") — you got the what but not the where. With .exception you can see the exact line that blew up, which is what you actually need to debug a vendor-API failure.
chaswick
left a comment
There was a problem hiding this comment.
Per comments below and the behavior i observed in sb, I believe those items should be addressed before approval.
| """CNAME record whose FQDN name equals its content should fail clean().""" | ||
| from django.core.exceptions import ValidationError | ||
|
|
||
| record = DnsRecord( |
There was a problem hiding this comment.
Nice. Would it make sense to also or in addition test case sensitivity, e.g. 'name=' and 'content=' are the same but different cases? name="sub.dns-test.gov" content="Sub.dns-test.gov"
|
|
||
| HOSTNAME_ERROR = "CNAME record hostname must not match record name." | ||
|
|
||
| def test_cname_fqdn_name_matches_content_raises_content_error(self): |
There was a problem hiding this comment.
Nice. Would it make sense to also or in addition test case sensitivity, e.g. data["name"] and "CNAME", <> are the same but different cases? Like "sub.dns-test.gov" and "Sub.dns-test.gov" for example.
| errors["priority"] = [DNS_RECORD_PRIORITY_REQUIRED_ERROR_MESSAGE] | ||
|
|
||
| def _validate_exclusive_names(self, record_type, errors): | ||
| def _resolve_domain_name(self) -> str | None: |
| self.VALID_CONTENT_BY_TYPE = { | ||
| "A": "192.0.2.10", | ||
| "AAAA": "2001:db8::1234:5678", | ||
| "CNAME": "www.example.com", |
There was a problem hiding this comment.
glad we can use our unit tests for these now! thank you for getting them to work!
erinysong
left a comment
There was a problem hiding this comment.
Tested and LGTM on my end! Small observation that when name == hostname, the validation error happens on the name field on admin but on the content field on the registrar. I don't think it's significant enough to block though but happy to consider otherwise
|
Nice catch, thanks! @chaswick Fixed. Ready for rev.
|
|
It was a simple add that built on this work this PR Resolves #4856 & #4825 @erinysong @chaswick |






Ticket
Resolves #4856 #4825
Changes
DnsRecord.clean()— previously only enforced at the form levelclean()to resolve the zone domain name once instead of once per validator (eliminates duplicate DB hit)logger.error(f"...")→logger.exception(...)in vendor data methods so tracebacks are preserved@, bare label, FQDN)Name and target can't be the same.Name can't be the same as the target.Target can't be the same as the record name.Context for reviewers
This branch builds from work already done in
dg/4779-no-dup-name-dns-records, which added form-level CNAME name != hostname validation. That PR left a gap:DnsRecord.clean()never enforced the same constraint, so it could be bypassed at the model level. This PR does that. No migrations needed.Setup
Ensure the DNS hosting waffle flag is ON and the test domain is enrolled. On sandbox (e.g. DG) or local with
DNS_MOCK_EXTERNAL_APIS=False:/domain/<id>/dns/recordson a DNS-enrolled domain (e.g.daisyepp.govif on DG)www, contentwww.daisyepp.gov)Name and target can't be the same.Name can't be the same as the target.Target can't be the same as the record name.@with contentdaisyepp.gov, and bare labelsubwith contentsub.daisyepp.gov— and confirm each is rejectedCode Review Verification Steps
As the original developer, I have
Satisfied acceptance criteria and met development standards
Ensured code standards are met (Original Developer)
Validated user-facing changes (if applicable)
As a code reviewer, I have
Reviewed, tested, and left feedback about the changes
Validated user-facing changes as a developer
Note: Multiple code reviewers can share the checklists above, a second reviewer should not make a duplicate checklist. All checks should be checked before approving, even those labeled N/A.
As a designer reviewer, I have
Verified that the changes match the design intention
Validated user-facing changes as a designer
References
Screenshots