mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2025-04-21 03:02:09 +00:00
Merge 5a3af9525a
into a13fd90347
This commit is contained in:
commit
626f61c879
@ -156,7 +156,12 @@ def mail_users():
|
|||||||
@authorized_personnel_only
|
@authorized_personnel_only
|
||||||
def mail_users_add():
|
def mail_users_add():
|
||||||
try:
|
try:
|
||||||
return add_mail_user(request.form.get('email', ''), request.form.get('password', ''), request.form.get('privileges', ''), env)
|
return add_mail_user(request.form.get('email', ''),
|
||||||
|
request.form.get('password', ''),
|
||||||
|
request.form.get('privileges', ''),
|
||||||
|
env,
|
||||||
|
dns_enabled=request.form.get('dns_enabled', False),
|
||||||
|
web_enabled=request.form.get('web_enabled', False))
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
return (str(e), 400)
|
return (str(e), 400)
|
||||||
|
|
||||||
@ -208,7 +213,9 @@ def mail_aliases_add():
|
|||||||
request.form.get('forwards_to', ''),
|
request.form.get('forwards_to', ''),
|
||||||
request.form.get('permitted_senders', ''),
|
request.form.get('permitted_senders', ''),
|
||||||
env,
|
env,
|
||||||
update_if_exists=(request.form.get('update_if_exists', '') == '1')
|
update_if_exists=(request.form.get('update_if_exists', '') == '1'),
|
||||||
|
dns_enabled=request.form.get('dns_enabled', False),
|
||||||
|
web_enabled=request.form.get('web_enabled', False)
|
||||||
)
|
)
|
||||||
|
|
||||||
@app.route('/mail/aliases/remove', methods=['POST'])
|
@app.route('/mail/aliases/remove', methods=['POST'])
|
||||||
@ -336,7 +343,7 @@ def ssl_get_status():
|
|||||||
|
|
||||||
# What domains can we provision certificates for? What unexpected problems do we have?
|
# What domains can we provision certificates for? What unexpected problems do we have?
|
||||||
provision, cant_provision = get_certificates_to_provision(env, show_extended_problems=False)
|
provision, cant_provision = get_certificates_to_provision(env, show_extended_problems=False)
|
||||||
|
|
||||||
# What's the current status of TLS certificates on all of the domain?
|
# What's the current status of TLS certificates on all of the domain?
|
||||||
domains_status = get_web_domains_info(env)
|
domains_status = get_web_domains_info(env)
|
||||||
domains_status = [{ "domain": d["domain"], "status": d["ssl_certificate"][0], "text": d["ssl_certificate"][1] } for d in domains_status ]
|
domains_status = [{ "domain": d["domain"], "status": d["ssl_certificate"][0], "text": d["ssl_certificate"][1] } for d in domains_status ]
|
||||||
|
@ -15,15 +15,16 @@ from utils import shell, load_env_vars_from_file, safe_domain_name, sort_domains
|
|||||||
def get_dns_domains(env):
|
def get_dns_domains(env):
|
||||||
# Add all domain names in use by email users and mail aliases and ensure
|
# Add all domain names in use by email users and mail aliases and ensure
|
||||||
# PRIMARY_HOSTNAME is in the list.
|
# PRIMARY_HOSTNAME is in the list.
|
||||||
domains = set()
|
domains = get_mail_domains(env, filter_list='dns')
|
||||||
domains |= get_mail_domains(env)
|
|
||||||
domains.add(env['PRIMARY_HOSTNAME'])
|
domains.add(env['PRIMARY_HOSTNAME'])
|
||||||
return domains
|
return domains
|
||||||
|
|
||||||
def get_dns_zones(env):
|
def get_dns_zones(env):
|
||||||
# What domains should we create DNS zones for? Never create a zone for
|
# What domains should we create DNS zones for? Never create a zone for
|
||||||
# a domain & a subdomain of that domain.
|
# a domain & a subdomain of that domain.
|
||||||
domains = get_dns_domains(env)
|
domains_mail = get_dns_domains(env)
|
||||||
|
domains_custom = set([n for n, *_ in get_custom_dns_config(env)])
|
||||||
|
domains = domains_mail | domains_custom
|
||||||
|
|
||||||
# Exclude domains that are subdomains of other domains we know. Proceed
|
# Exclude domains that are subdomains of other domains we know. Proceed
|
||||||
# by looking at shorter domains first.
|
# by looking at shorter domains first.
|
||||||
@ -144,7 +145,7 @@ def build_zone(domain, all_domains, additional_records, www_redirect_domains, en
|
|||||||
# Define ns2.PRIMARY_HOSTNAME or whatever the user overrides.
|
# Define ns2.PRIMARY_HOSTNAME or whatever the user overrides.
|
||||||
# User may provide one or more additional nameservers
|
# User may provide one or more additional nameservers
|
||||||
secondary_ns_list = get_secondary_dns(additional_records, mode="NS") \
|
secondary_ns_list = get_secondary_dns(additional_records, mode="NS") \
|
||||||
or ["ns2." + env["PRIMARY_HOSTNAME"]]
|
or ["ns2." + env["PRIMARY_HOSTNAME"]]
|
||||||
for secondary_ns in secondary_ns_list:
|
for secondary_ns in secondary_ns_list:
|
||||||
records.append((None, "NS", secondary_ns+'.', False))
|
records.append((None, "NS", secondary_ns+'.', False))
|
||||||
|
|
||||||
@ -748,16 +749,16 @@ def write_custom_dns_config(config, env):
|
|||||||
f.write(config_yaml)
|
f.write(config_yaml)
|
||||||
|
|
||||||
def set_custom_dns_record(qname, rtype, value, action, env):
|
def set_custom_dns_record(qname, rtype, value, action, env):
|
||||||
# validate qname
|
# # validate qname
|
||||||
for zone, fn in get_dns_zones(env):
|
# for zone, fn in get_dns_zones(env):
|
||||||
# It must match a zone apex or be a subdomain of a zone
|
# # It must match a zone apex or be a subdomain of a zone
|
||||||
# that we are otherwise hosting.
|
# # that we are otherwise hosting.
|
||||||
if qname == zone or qname.endswith("."+zone):
|
# if qname == zone or qname.endswith("."+zone):
|
||||||
break
|
# break
|
||||||
else:
|
# else:
|
||||||
# No match.
|
# # No match.
|
||||||
if qname != "_secondary_nameserver":
|
# if qname != "_secondary_nameserver":
|
||||||
raise ValueError("%s is not a domain name or a subdomain of a domain name managed by this box." % qname)
|
# raise ValueError("%s is not a domain name or a subdomain of a domain name managed by this box." % qname)
|
||||||
|
|
||||||
# validate rtype
|
# validate rtype
|
||||||
rtype = rtype.upper()
|
rtype = rtype.upper()
|
||||||
|
@ -3,8 +3,35 @@
|
|||||||
import subprocess, shutil, os, sqlite3, re
|
import subprocess, shutil, os, sqlite3, re
|
||||||
import utils
|
import utils
|
||||||
from email_validator import validate_email as validate_email_, EmailNotValidError
|
from email_validator import validate_email as validate_email_, EmailNotValidError
|
||||||
|
import rtyaml
|
||||||
import idna
|
import idna
|
||||||
|
|
||||||
|
def load_domain_blacklist(env, service):
|
||||||
|
try:
|
||||||
|
return set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||||
|
except:
|
||||||
|
return set()
|
||||||
|
|
||||||
|
def add_domain_blacklist(env, domain, service):
|
||||||
|
try:
|
||||||
|
ignored = set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||||
|
ignored.add(domain)
|
||||||
|
except Exception as err:
|
||||||
|
# if non-existent or baldy formatted, consider it new
|
||||||
|
ignored = {domain}
|
||||||
|
with open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)), "w") as f:
|
||||||
|
f.write(rtyaml.dump(list(ignored)))
|
||||||
|
|
||||||
|
def remove_domain_blacklist(env, domain, service):
|
||||||
|
try:
|
||||||
|
ignored = set(rtyaml.load(open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)))))
|
||||||
|
if domain in ignored:
|
||||||
|
ignored.remove(domain)
|
||||||
|
with open(os.path.join(env['STORAGE_ROOT'], '{}/ignored.yaml'.format(service)), "w") as f:
|
||||||
|
f.write(rtyaml.dump(list(ignored)))
|
||||||
|
except Exception as err:
|
||||||
|
pass
|
||||||
|
|
||||||
def validate_email(email, mode=None):
|
def validate_email(email, mode=None):
|
||||||
# Checks that an email address is syntactically valid. Returns True/False.
|
# Checks that an email address is syntactically valid. Returns True/False.
|
||||||
# Until Postfix supports SMTPUTF8, an email address may contain ASCII
|
# Until Postfix supports SMTPUTF8, an email address may contain ASCII
|
||||||
@ -254,15 +281,20 @@ def get_domain(emailaddr, as_unicode=True):
|
|||||||
pass
|
pass
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_mail_domains(env, filter_aliases=lambda alias : True):
|
def get_mail_domains(env, filter_aliases=lambda alias : True, filter_list=None):
|
||||||
|
ignored = set()
|
||||||
|
if filter_list == 'dns':
|
||||||
|
ignored |= load_domain_blacklist(env, 'dns')
|
||||||
|
if filter_list in ('web', 'www'):
|
||||||
|
ignored |= load_domain_blacklist(env, 'www')
|
||||||
# Returns the domain names (IDNA-encoded) of all of the email addresses
|
# Returns the domain names (IDNA-encoded) of all of the email addresses
|
||||||
# configured on the system.
|
# configured on the system.
|
||||||
return set(
|
return set(
|
||||||
[get_domain(login, as_unicode=False) for login in get_mail_users(env)]
|
[get_domain(login, as_unicode=False) for login in get_mail_users(env)]
|
||||||
+ [get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ]
|
+ [get_domain(address, as_unicode=False) for address, *_ in get_mail_aliases(env) if filter_aliases(address) ]
|
||||||
)
|
) - ignored
|
||||||
|
|
||||||
def add_mail_user(email, pw, privs, env):
|
def add_mail_user(email, pw, privs, env, dns_enabled=True, web_enabled=True):
|
||||||
# validate email
|
# validate email
|
||||||
if email.strip() == "":
|
if email.strip() == "":
|
||||||
return ("No email address provided.", 400)
|
return ("No email address provided.", 400)
|
||||||
@ -304,6 +336,14 @@ def add_mail_user(email, pw, privs, env):
|
|||||||
# write databasebefore next step
|
# write databasebefore next step
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Add non dns enabled domain to the ignored domain list
|
||||||
|
if dns_enabled == 'false':
|
||||||
|
add_domain_blacklist(env, get_domain(email), 'dns')
|
||||||
|
|
||||||
|
# Add non web enabled domain to the ignored domain list
|
||||||
|
if web_enabled == 'false':
|
||||||
|
add_domain_blacklist(env, get_domain(email), 'www')
|
||||||
|
|
||||||
# Update things in case any new domains are added.
|
# Update things in case any new domains are added.
|
||||||
return kick(env, "mail user added")
|
return kick(env, "mail user added")
|
||||||
|
|
||||||
@ -348,6 +388,9 @@ def remove_mail_user(email, env):
|
|||||||
return ("That's not a user (%s)." % email, 400)
|
return ("That's not a user (%s)." % email, 400)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
remove_domain_blacklist(env, get_domain(address), 'dns')
|
||||||
|
remove_domain_blacklist(env, get_domain(address), 'www')
|
||||||
|
|
||||||
# Update things in case any domains are removed.
|
# Update things in case any domains are removed.
|
||||||
return kick(env, "mail user removed")
|
return kick(env, "mail user removed")
|
||||||
|
|
||||||
@ -396,7 +439,7 @@ def add_remove_mail_user_privilege(email, priv, action, env):
|
|||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
|
|
||||||
def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exists=False, do_kick=True):
|
def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exists=False, dns_enabled=True, web_enabled=True, do_kick=True):
|
||||||
# convert Unicode domain to IDNA
|
# convert Unicode domain to IDNA
|
||||||
address = sanitize_idn_email_address(address)
|
address = sanitize_idn_email_address(address)
|
||||||
|
|
||||||
@ -485,6 +528,14 @@ def add_mail_alias(address, forwards_to, permitted_senders, env, update_if_exist
|
|||||||
|
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
# Add non dns enabled domain to the ignored domain list
|
||||||
|
if dns_enabled == 'false':
|
||||||
|
add_domain_blacklist(env, get_domain(address), 'dns')
|
||||||
|
|
||||||
|
# Add non web enabled domain to the ignored domain list
|
||||||
|
if web_enabled == 'false':
|
||||||
|
add_domain_blacklist(env, get_domain(address), 'www')
|
||||||
|
|
||||||
if do_kick:
|
if do_kick:
|
||||||
# Update things in case any new domains are added.
|
# Update things in case any new domains are added.
|
||||||
return kick(env, return_status)
|
return kick(env, return_status)
|
||||||
@ -500,6 +551,9 @@ def remove_mail_alias(address, env, do_kick=True):
|
|||||||
return ("That's not an alias (%s)." % address, 400)
|
return ("That's not an alias (%s)." % address, 400)
|
||||||
conn.commit()
|
conn.commit()
|
||||||
|
|
||||||
|
remove_domain_blacklist(env, get_domain(address), 'dns')
|
||||||
|
remove_domain_blacklist(env, get_domain(address), 'www')
|
||||||
|
|
||||||
if do_kick:
|
if do_kick:
|
||||||
# Update things in case any domains are removed.
|
# Update things in case any domains are removed.
|
||||||
return kick(env, "alias removed")
|
return kick(env, "alias removed")
|
||||||
|
@ -26,7 +26,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="addaliasAddress" class="col-sm-1 control-label">Alias</label>
|
<label for="addaliasAddress" class="col-sm-2 control-label">Alias</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<input type="email" class="form-control" id="addaliasAddress">
|
<input type="email" class="form-control" id="addaliasAddress">
|
||||||
<div style="margin-top: 3px; padding-left: 3px; font-size: 90%" class="text-muted">
|
<div style="margin-top: 3px; padding-left: 3px; font-size: 90%" class="text-muted">
|
||||||
@ -36,7 +36,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="addaliasForwardsTo" class="col-sm-1 control-label">Forwards To</label>
|
<label for="addaliasForwardsTo" class="col-sm-2 control-label">Forwards To</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<textarea class="form-control" rows="3" id="addaliasForwardsTo"></textarea>
|
<textarea class="form-control" rows="3" id="addaliasForwardsTo"></textarea>
|
||||||
<div style="margin-top: 3px; padding-left: 3px; font-size: 90%" class="text-muted">
|
<div style="margin-top: 3px; padding-left: 3px; font-size: 90%" class="text-muted">
|
||||||
@ -45,7 +45,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="addaliasSenders" class="col-sm-1 control-label">Permitted Senders</label>
|
<label for="addaliasSenders" class="col-sm-2 control-label">Permitted Senders</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="radio">
|
<div class="radio">
|
||||||
<label>
|
<label>
|
||||||
@ -64,6 +64,20 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="addaliasDnsHandling" class="col-sm-2 control-label">Services</label>
|
||||||
|
<div class="col-sm-10">
|
||||||
|
<div id="alias_service_buttons" class="btn-group btn-group-xs">
|
||||||
|
<button id="addaliasMailHandling" data-mode="mail" class="btn btn-xs btn-success active" disabled>MAIL</button>
|
||||||
|
<button id="addaliasDnsHandling" data-mode="dns" class="btn btn-xs btn-success active">DNS</button>
|
||||||
|
<button id="addaliasWebHandling" data-mode="www" class="btn btn-xs btn-success active">WWW</button>
|
||||||
|
</div>
|
||||||
|
<div id="alias_service_info" class="text-info small" style="display: none; margin: .5em 0 0 0;">
|
||||||
|
<span class="dns hidden">When deactivated, the DNS service is not configured for the domain</span>
|
||||||
|
<span class="www hidden">When deactivated, the Web services is not configured for the domain</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="col-sm-offset-1 col-sm-11">
|
<div class="col-sm-offset-1 col-sm-11">
|
||||||
<button id="add-alias-button" type="submit" class="btn btn-primary">Add Alias</button>
|
<button id="add-alias-button" type="submit" class="btn btn-primary">Add Alias</button>
|
||||||
@ -200,7 +214,33 @@ function show_aliases() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
$('#alias_type_buttons button[data-mode="regular"]').click(); // init
|
$('#alias_type_buttons button[data-mode="regular"]').click(); // init
|
||||||
})
|
|
||||||
|
// Service buttons
|
||||||
|
$('#alias_service_buttons button').off('click').click(function() {
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
$(this).removeClass('active');
|
||||||
|
$(this).addClass('btn-default');
|
||||||
|
$(this).removeClass('btn-success');
|
||||||
|
$('#alias_service_info .www').addClass('hidden');
|
||||||
|
$('#alias_service_info .dns').addClass('hidden');
|
||||||
|
if ($(this).attr('data-mode') == "dns") {
|
||||||
|
$('#alias_service_info').slideDown();
|
||||||
|
$('#addalias-form .dns').removeClass('hidden');
|
||||||
|
} else if ($(this).attr('data-mode') == "www") {
|
||||||
|
$('#alias_service_info').slideDown();
|
||||||
|
$('#addalias-form .www').removeClass('hidden');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(this).addClass('active');
|
||||||
|
$(this).removeClass('btn-default');
|
||||||
|
$(this).addClass('btn-success');
|
||||||
|
$('#alias_service_info').slideUp();
|
||||||
|
$('#addalias-form .www').addClass('hidden');
|
||||||
|
$('#addalias-form .dns').addClass('hidden');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var is_alias_add_update = false;
|
var is_alias_add_update = false;
|
||||||
@ -209,6 +249,8 @@ function do_add_alias() {
|
|||||||
var form_address = $("#addaliasAddress").val();
|
var form_address = $("#addaliasAddress").val();
|
||||||
var form_forwardsto = $("#addaliasForwardsTo").val();
|
var form_forwardsto = $("#addaliasForwardsTo").val();
|
||||||
var form_senders = ($('#addaliasForwardsToAdvanced').prop('checked') ? $("#addaliasSenders").val() : '');
|
var form_senders = ($('#addaliasForwardsToAdvanced').prop('checked') ? $("#addaliasSenders").val() : '');
|
||||||
|
var form_dns = $('#addaliasDnsHandling').hasClass('active');
|
||||||
|
var form_web = $('#addaliasWebHandling').hasClass('active');
|
||||||
if ($('#addaliasForwardsToAdvanced').prop('checked') && !/\S/.exec($("#addaliasSenders").val())) {
|
if ($('#addaliasForwardsToAdvanced').prop('checked') && !/\S/.exec($("#addaliasSenders").val())) {
|
||||||
show_modal_error(title, "You did not enter any permitted senders.");
|
show_modal_error(title, "You did not enter any permitted senders.");
|
||||||
return false;
|
return false;
|
||||||
@ -220,7 +262,9 @@ function do_add_alias() {
|
|||||||
update_if_exists: is_alias_add_update ? '1' : '0',
|
update_if_exists: is_alias_add_update ? '1' : '0',
|
||||||
address: form_address,
|
address: form_address,
|
||||||
forwards_to: form_forwardsto,
|
forwards_to: form_forwardsto,
|
||||||
permitted_senders: form_senders
|
permitted_senders: form_senders,
|
||||||
|
dns_enabled: form_dns,
|
||||||
|
web_enabled: form_web
|
||||||
},
|
},
|
||||||
function(r) {
|
function(r) {
|
||||||
// Responses are multiple lines of pre-formatted text.
|
// Responses are multiple lines of pre-formatted text.
|
||||||
@ -242,8 +286,14 @@ function aliases_reset_form() {
|
|||||||
$('#alias-cancel').addClass('hidden');
|
$('#alias-cancel').addClass('hidden');
|
||||||
$('#add-alias-button').text('Add Alias');
|
$('#add-alias-button').text('Add Alias');
|
||||||
is_alias_add_update = false;
|
is_alias_add_update = false;
|
||||||
|
|
||||||
|
$('#addaliasDnsHandling').prop('disabled', false).addClass('btn-success');
|
||||||
|
$('#addaliasWebHandling').prop('disabled', false).addClass('btn-success');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function aliases_edit(elem) {
|
function aliases_edit(elem) {
|
||||||
var address = $(elem).parents('tr').attr('data-address');
|
var address = $(elem).parents('tr').attr('data-address');
|
||||||
var receiverdivs = $(elem).parents('tr').find('.forwardsTo div');
|
var receiverdivs = $(elem).parents('tr').find('.forwardsTo div');
|
||||||
@ -267,6 +317,8 @@ function aliases_edit(elem) {
|
|||||||
$('#addaliasForwardsToAdvanced').prop('checked', senders != "");
|
$('#addaliasForwardsToAdvanced').prop('checked', senders != "");
|
||||||
$('#addaliasForwardsToNotAdvanced').prop('checked', senders == "");
|
$('#addaliasForwardsToNotAdvanced').prop('checked', senders == "");
|
||||||
$("#addaliasSenders").val(senders);
|
$("#addaliasSenders").val(senders);
|
||||||
|
$('#addaliasDnsHandling').prop('disabled', true);
|
||||||
|
$('#addaliasWebHandling').prop('disabled', true);
|
||||||
$('#add-alias-button').text('Update');
|
$('#add-alias-button').text('Update');
|
||||||
$('body').animate({ scrollTop: 0 })
|
$('body').animate({ scrollTop: 0 })
|
||||||
is_alias_add_update = true;
|
is_alias_add_update = true;
|
||||||
|
@ -23,6 +23,13 @@
|
|||||||
<input type="text" class="form-control" id="customdnsQname" placeholder="subdomain">
|
<input type="text" class="form-control" id="customdnsQname" placeholder="subdomain">
|
||||||
</td><td style="padding: 0 1em; font-weight: bold;">.</td><td>
|
</td><td style="padding: 0 1em; font-weight: bold;">.</td><td>
|
||||||
<select id="customdnsZone" class="form-control"> </select>
|
<select id="customdnsZone" class="form-control"> </select>
|
||||||
|
<div class="input-group" id="customdnsZoneFree">
|
||||||
|
<input type="text" class="form-control" placeholder="new-domain.tld" class="hidden">
|
||||||
|
<span class="input-group-btn">
|
||||||
|
<button class="btn btn-default" type="button" onclick="reset_zone_free(); return false;">X</button>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
<div class="text-info" style="margin-top: .5em">Leave the left field blank to set a record on the chosen domain name, or enter a subdomain.</div>
|
<div class="text-info" style="margin-top: .5em">Leave the left field blank to set a record on the chosen domain name, or enter a subdomain.</div>
|
||||||
</div>
|
</div>
|
||||||
@ -166,19 +173,69 @@ function show_custom_dns() {
|
|||||||
$('#secondarydns-clear-instructions').toggle(data.hostnames.length > 0);
|
$('#secondarydns-clear-instructions').toggle(data.hostnames.length > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$('#customdnsZone').text('');
|
||||||
|
var dns_list_domains = $('<optgroup/>').attr('label', 'Domains');
|
||||||
|
var dns_list_customs = $('<optgroup/>').attr('label', 'Custom');
|
||||||
|
var dns_list_advanced = $('<optgroup/>').attr('label', 'Advanced');
|
||||||
|
|
||||||
|
$('#customdnsZone').append(dns_list_domains);
|
||||||
|
$('#customdnsZone').append(dns_list_customs);
|
||||||
|
$('#customdnsZone').append(dns_list_advanced);
|
||||||
|
|
||||||
|
dns_list_advanced.append($('<option/>').text("New domain..."));
|
||||||
|
|
||||||
|
// Append all domains offered by mail
|
||||||
api(
|
api(
|
||||||
"/dns/zones",
|
"/dns/zones",
|
||||||
"GET",
|
"GET",
|
||||||
{ },
|
{ },
|
||||||
function(data) {
|
function(zones) {
|
||||||
$('#customdnsZone').text('');
|
for (var i = 0; i < zones.length; i++) {
|
||||||
for (var i = 0; i < data.length; i++) {
|
dns_list_domains.append($('<option/>').text(zones[i]));
|
||||||
$('#customdnsZone').append($('<option/>').text(data[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Append all custom domains that are not offering mail
|
||||||
|
api(
|
||||||
|
"/dns/custom",
|
||||||
|
"GET",
|
||||||
|
{ },
|
||||||
|
function(customs) {
|
||||||
|
seen = [];
|
||||||
|
for (var i = 0; i < customs.length; i++) {
|
||||||
|
fqdn = customs[i].qname.replace(/.*\.(?=[^.]*\.[^.]*$)/, "");
|
||||||
|
console.log(fqdn, seen);
|
||||||
|
if ($.inArray(fqdn, seen) == -1) {
|
||||||
|
seen.push(fqdn);
|
||||||
|
dns_list_customs.append($('<option/>').text(fqdn));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$('#customdnsZone')[0].selectedIndex = 0;
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
show_current_custom_dns();
|
show_current_custom_dns();
|
||||||
show_customdns_rtype_hint();
|
show_customdns_rtype_hint();
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
$('#customdnsZone').on('change', function(){
|
||||||
|
var selected = $(this).find("option:selected").val();
|
||||||
|
if (selected === "New domain...") {
|
||||||
|
$('#customdnsZoneFree').removeClass('hidden');
|
||||||
|
$('#customdnsZone').addClass('hidden');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
reset_zone_free();
|
||||||
|
}
|
||||||
|
|
||||||
|
function reset_zone_free() {
|
||||||
|
$('#customdnsZoneFree').addClass('hidden');
|
||||||
|
$('#customdnsZone').removeClass('hidden');
|
||||||
|
$('#customdnsZone')[0].selectedIndex = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
function show_current_custom_dns() {
|
function show_current_custom_dns() {
|
||||||
@ -238,6 +295,14 @@ function do_set_custom_dns(qname, rtype, value, method) {
|
|||||||
qname = $('#customdnsQname').val() + '.' + $('#customdnsZone').val();
|
qname = $('#customdnsQname').val() + '.' + $('#customdnsZone').val();
|
||||||
else
|
else
|
||||||
qname = $('#customdnsZone').val();
|
qname = $('#customdnsZone').val();
|
||||||
|
|
||||||
|
if ($('#customdnsZone').val() === 'New domain...') {
|
||||||
|
if ($('#customdnsQname').val() != '')
|
||||||
|
qname = $('#customdnsQname').val() + '.' + $('#customdnsZoneFree input').val();
|
||||||
|
else
|
||||||
|
qname = $('#customdnsZoneFree input').val();
|
||||||
|
}
|
||||||
|
|
||||||
rtype = $('#customdnsType').val();
|
rtype = $('#customdnsType').val();
|
||||||
value = $('#customdnsValue').val();
|
value = $('#customdnsValue').val();
|
||||||
method = 'POST';
|
method = 'POST';
|
||||||
|
@ -28,8 +28,21 @@
|
|||||||
<option value="admin">Administrator</option>
|
<option value="admin">Administrator</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="col-sm-15">
|
||||||
|
<div id="user_service_buttons" class="btn-group btn-group">
|
||||||
|
<button id="adduserMailHandling" data-mode="mail" class="btn btn-success active" disabled>MAIL</button>
|
||||||
|
<button id="adduserDnsHandling" data-mode="dns" class="btn btn-success active">DNS</button>
|
||||||
|
<button id="adduserWebHandling" data-mode="www" class="btn btn-success active">WWW</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<button type="submit" class="btn btn-primary">Add User</button>
|
<button type="submit" class="btn btn-primary">Add User</button>
|
||||||
</form>
|
</form>
|
||||||
|
<div id="user_service_info" class="text-info small" style="display: none; margin: .5em 0 0 0;">
|
||||||
|
<span class="dns hidden">When deactivated, the DNS service is not configured for the domain</span>
|
||||||
|
<span class="www hidden">When deactivated, the Web services is not configured for the domain</span>
|
||||||
|
</div>
|
||||||
<ul style="margin-top: 1em; padding-left: 1.5em; font-size: 90%;">
|
<ul style="margin-top: 1em; padding-left: 1.5em; font-size: 90%;">
|
||||||
<li>Passwords must be at least eight characters and may not contain spaces. For best results, <a href="#" onclick="return generate_random_password()">generate a random password</a>.</li>
|
<li>Passwords must be at least eight characters and may not contain spaces. For best results, <a href="#" onclick="return generate_random_password()">generate a random password</a>.</li>
|
||||||
<li>Use <a href="#" onclick="return show_panel('aliases')">aliases</a> to create email addresses that forward to existing accounts.</li>
|
<li>Use <a href="#" onclick="return show_panel('aliases')">aliases</a> to create email addresses that forward to existing accounts.</li>
|
||||||
@ -179,19 +192,50 @@ function show_users() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Service buttons
|
||||||
|
$('#user_service_buttons button').off('click').click(function() {
|
||||||
|
if ($(this).hasClass('active')) {
|
||||||
|
$(this).removeClass('active');
|
||||||
|
$(this).addClass('btn-default');
|
||||||
|
$(this).removeClass('btn-success');
|
||||||
|
$('#user_service_info .www').addClass('hidden');
|
||||||
|
$('#user_service_info .dns').addClass('hidden');
|
||||||
|
if ($(this).attr('data-mode') == "dns") {
|
||||||
|
$('#user_service_info').slideDown();
|
||||||
|
$('#user_service_info .dns').removeClass('hidden');
|
||||||
|
} else if ($(this).attr('data-mode') == "www") {
|
||||||
|
$('#user_service_info').slideDown();
|
||||||
|
$('#user_service_info .www').removeClass('hidden');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
$(this).addClass('active');
|
||||||
|
$(this).removeClass('btn-default');
|
||||||
|
$(this).addClass('btn-success');
|
||||||
|
$('#user_service_info').slideUp();
|
||||||
|
$('#user_service_info .www').addClass('hidden');
|
||||||
|
$('#user_service_info .dns').addClass('hidden');
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function do_add_user() {
|
function do_add_user() {
|
||||||
var email = $("#adduserEmail").val();
|
var email = $("#adduserEmail").val();
|
||||||
var pw = $("#adduserPassword").val();
|
var pw = $("#adduserPassword").val();
|
||||||
var privs = $("#adduserPrivs").val();
|
var privs = $("#adduserPrivs").val();
|
||||||
|
var form_dns = $('#adduserDnsHandling').hasClass('active');
|
||||||
|
var form_web = $('#adduserWebHandling').hasClass('active');
|
||||||
api(
|
api(
|
||||||
"/mail/users/add",
|
"/mail/users/add",
|
||||||
"POST",
|
"POST",
|
||||||
{
|
{
|
||||||
email: email,
|
email: email,
|
||||||
password: pw,
|
password: pw,
|
||||||
privileges: privs
|
privileges: privs,
|
||||||
|
dns_enabled: form_dns,
|
||||||
|
web_enabled: form_web
|
||||||
},
|
},
|
||||||
function(r) {
|
function(r) {
|
||||||
// Responses are multiple lines of pre-formatted text.
|
// Responses are multiple lines of pre-formatted text.
|
||||||
|
@ -16,14 +16,14 @@ def get_web_domains(env, include_www_redirects=True, exclude_dns_elsewhere=True)
|
|||||||
# Serve web for all mail domains so that we might at least
|
# Serve web for all mail domains so that we might at least
|
||||||
# provide auto-discover of email settings, and also a static website
|
# provide auto-discover of email settings, and also a static website
|
||||||
# if the user wants to make one.
|
# if the user wants to make one.
|
||||||
domains |= get_mail_domains(env)
|
domains |= get_mail_domains(env, filter_list='www')
|
||||||
|
|
||||||
if include_www_redirects:
|
if include_www_redirects:
|
||||||
# Add 'www.' subdomains that we want to provide default redirects
|
# Add 'www.' subdomains that we want to provide default redirects
|
||||||
# to the main domain for. We'll add 'www.' to any DNS zones, i.e.
|
# to the main domain for. We'll add 'www.' to any DNS zones, i.e.
|
||||||
# the topmost of each domain we serve.
|
# the topmost of each domain we serve.
|
||||||
domains |= set('www.' + zone for zone, zonefile in get_dns_zones(env))
|
domains |= set('www.' + zone for zone, zonefile in get_dns_zones(env))
|
||||||
|
|
||||||
if exclude_dns_elsewhere:
|
if exclude_dns_elsewhere:
|
||||||
# ...Unless the domain has an A/AAAA record that maps it to a different
|
# ...Unless the domain has an A/AAAA record that maps it to a different
|
||||||
# IP address than this box. Remove those domains from our list.
|
# IP address than this box. Remove those domains from our list.
|
||||||
|
Loading…
Reference in New Issue
Block a user