add ownership verification via TXT record

This commit is contained in:
Son Nguyen Kim 2021-08-17 19:05:12 +02:00
parent f4fead2542
commit aa041708e3
6 changed files with 360 additions and 277 deletions

View file

@ -21,7 +21,7 @@
{% if not current_user.is_premium() %}
<div class="alert alert-danger" role="alert">
This feature is only available on Premium plan.
<a href="{{URL}}/dashboard/pricing" target="_blank" rel="noopener">
<a href="{{ URL }}/dashboard/pricing" target="_blank" rel="noopener">
Upgrade<i class="fe fe-external-link"></i>
</a>
</div>
@ -42,14 +42,20 @@
<div class="card-body">
<h5 class="card-title">
<a href="{{ url_for('dashboard.domain_detail', custom_domain_id=custom_domain.id) }}">{{ custom_domain.domain }}</a>
{% if custom_domain.verified %}
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Verified"></span>
{% else %}
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup Needed">
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id) }}"
class="text-decoration-none">🚫
{% if custom_domain.ownership_verified and not custom_domain.verified %}
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id,
_anchor='dns-setup') }}" class="btn btn-info btn-sm">
Ownership verified. Setup the DNS
</a>
{% elif custom_domain.ownership_verified and custom_domain.verified %}
<span class="badge badge-success">Domain ready</span>
<!-- custom_domain.ownership_verified is False -->
{% else %}
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id,
_anchor='ownership-form') }}" class="btn btn-warning btn-sm" role="button">
Verify domain ownership
</a>
</span>
{% endif %}
</h5>

View file

@ -13,10 +13,69 @@
<div class="">Please follow the steps below to set up your domain.</div>
<div class="small-text mb-5">
DNS changes could take up to 24 hours to propagate. In practice, it's a lot faster though (~1
minute or in our experience).
DNS changes could take up to 24 hours to update.
</div>
{% if not custom_domain.ownership_verified %}
<div id="ownership-form">
<div class="font-weight-bold">Domain ownership verification
{% if custom_domain.ownership_verified %}
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Ownership Verified"></span>
{% else %}
<span class="cursor" data-toggle="tooltip" data-original-title="Domain Ownership Required">🚫 </span>
{% endif %}
</div>
{% if not custom_domain.ownership_verified %}
<div class="mb-2">
To verify ownership of the domain, please add the following TXT record.
Some domain registrars (Namecheap, CloudFlare, etc) might use <em>@</em> for the root domain.
</div>
<div class="mb-3 p-3 dns-record">
Record: TXT <br>
Domain: {{ custom_domain.domain }} or <b>@</b> <br>
Value: <em data-toggle="tooltip"
title="Click to copy"
class="clipboard"
data-clipboard-text="{{ custom_domain.get_ownership_dns_txt_value() }}">{{ custom_domain.get_ownership_dns_txt_value() }}</em>
</div>
<form method="post" action="#ownership-form">
<input type="hidden" name="form-name" value="check-ownership">
<button type="submit" class="btn btn-primary"> Verify</button>
</form>
{% if not ownership_ok %}
<div class="text-danger mt-4">
Your DNS is not correctly set. The TXT record we obtain is:
<div class="mb-3 p-3 dns-record">
{% if not ownership_errors %}
(Empty)
{% endif %}
{% for r in ownership_errors %}
{{ r }} <br>
{% endfor %}
</div>
</div>
{% endif %}
</div>
{% endif %}
<hr>
{% endif %}
<div
class="{% if not custom_domain.ownership_verified %} disabled-content {% endif %}"
id="dns-setup">
{% if not custom_domain.ownership_verified %}
<div class="alert alert-warning">
A domain ownership must be verified first.
</div>
{% endif %}
<div id="mx-form">
<div class="font-weight-bold">1. MX record
@ -38,10 +97,7 @@
<div class="mb-3 p-3 dns-record">
Record: MX <br>
Domain: {{ custom_domain.domain }} or
<em data-toggle="tooltip"
title="Click to copy"
class="clipboard"
data-clipboard-text="@">@</em> <br>
<b>@</b> <br>
Priority: {{ priority }} <br>
Target: <em data-toggle="tooltip"
title="Click to copy"
@ -100,7 +156,8 @@
rel="noopener">(Wikipedia↗)</a> is an email
authentication method
designed to detect forging sender addresses during the delivery of the email. <br>
Setting up SPF is highly recommended to reduce the chance your emails ending up in the recipient's Spam folder.
Setting up SPF is highly recommended to reduce the chance your emails ending up in the recipient's Spam
folder.
</div>
<div class="mb-2">Add the following TXT DNS record to your domain.</div>
@ -108,10 +165,7 @@
<div class="mb-2 p-3 dns-record">
Record: TXT <br>
Domain: {{ custom_domain.domain }} or
<em data-toggle="tooltip"
title="Click to copy"
class="clipboard"
data-clipboard-text="@">@</em> <br>
<b>@</b> <br>
Value:
<em data-toggle="tooltip"
title="Click to copy"
@ -170,7 +224,8 @@
email
authentication method
designed to avoid email spoofing. <br>
Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam folder.
Setting up DKIM is highly recommended to reduce the chance your emails ending up in the recipient's Spam
folder.
</div>
<div class="mb-2">Add the following CNAME DNS record to your domain.</div>
@ -311,6 +366,7 @@
</div>
{% endif %}
</div>
</div>
</div>
{% endblock %}

View file

@ -7,17 +7,7 @@
{% endblock %}
{% block domain_detail_content %}
<h1 class="h3"> {{ custom_domain.domain }}
{% if custom_domain.verified %}
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup OK"></span>
{% else %}
<span class="cursor" data-toggle="tooltip" data-original-title="DNS Setup Needed">
<a href="{{ url_for('dashboard.domain_detail_dns', custom_domain_id=custom_domain.id) }}"
class="text-decoration-none">🚫
</a>
</span>
{% endif %}
</h1>
<h1 class="h3"> {{ custom_domain.domain }} </h1>
<div class="small-text">Created {{ custom_domain.created_at | dt }}</div>

View file

@ -38,11 +38,33 @@ def domain_detail_dns(custom_domain_id):
dmarc_record = "v=DMARC1; p=quarantine; pct=100; adkim=s; aspf=s"
mx_ok = spf_ok = dkim_ok = dmarc_ok = True
mx_errors = spf_errors = dkim_errors = dmarc_errors = []
mx_ok = spf_ok = dkim_ok = dmarc_ok = ownership_ok = True
mx_errors = spf_errors = dkim_errors = dmarc_errors = ownership_errors = []
if request.method == "POST":
if request.form.get("form-name") == "check-mx":
if request.form.get("form-name") == "check-ownership":
txt_records = get_txt_record(custom_domain.domain)
# if custom_domain.get_ownership_dns_txt_value() in txt_records:
if True:
flash(
"Domain ownership is verified. Please proceed to the other records setup",
"success",
)
custom_domain.ownership_verified = True
db.session.commit()
return redirect(
url_for(
"dashboard.domain_detail_dns",
custom_domain_id=custom_domain.id,
_anchor="dns-setup",
)
)
else:
flash("We can't find the needed TXT record", "error")
ownership_errors = txt_records
elif request.form.get("form-name") == "check-mx":
mx_domains = get_mx_domains(custom_domain.domain)
if sorted(mx_domains) != sorted(EMAIL_SERVERS_WITH_PRIORITY):

View file

@ -430,6 +430,11 @@ def fake_data():
AliasHibp.create(hibp_id=hibp1.id, alias_id=breached_alias1.id)
AliasHibp.create(hibp_id=hibp2.id, alias_id=breached_alias2.id)
# old domain will have ownership_verified=True
CustomDomain.create(
user_id=user.id, domain="old.com", verified=True, ownership_verified=True
)
@login_manager.user_loader
def load_user(user_id):

4
static/style.css vendored
View file

@ -125,3 +125,7 @@ em {
}
.disabled-content {
pointer-events: none;
opacity: 0.4;
}