mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-29 03:27:05 +00:00
1bf8f1991f
* For non-ASCII domain names, we will keep the Unicode encoding in our users/aliases table. This is nice for the user and also simplifies things like sorting domain names (using Unicode lexicographic order is good, using ASCII lexicogrpahic order on IDNA is confusing). * Write nsd config, nsd zone files, nginx config, and SSL CSRs with domains in IDNA-encoded ASCII. * When checking SSL certificates, treat the CN and SANs as IDNA. * Since Chrome has an interesting feature of converting Unicode to IDNA in <input type="email"> form fields, we'll also forcibly convert IDNA to Unicode in the domain part of email addresses before saving email addresses in the users/aliases tables so that the table is normalized to Unicode. * Don't allow non-ASCII characters in user account email addresses. Dovecot gets confused when querying the Sqlite database (which we observed even for non-word ASCII characters too, so it may not be related to the character encoding).
255 lines
8.4 KiB
HTML
255 lines
8.4 KiB
HTML
<h2>Users</h2>
|
|
|
|
<style>
|
|
#user_table tr.account_inactive td.address { color: #888; text-decoration: line-through; }
|
|
#user_table .aliases { font-size: 90%; }
|
|
#user_table .aliases div:before { content: "⇖ "; }
|
|
#user_table .aliases div { }
|
|
#user_table .actions { margin-top: .33em; font-size: 95%; }
|
|
#user_table .account_inactive .if_active { display: none; }
|
|
#user_table .account_active .if_inactive { display: none; }
|
|
</style>
|
|
|
|
<h3>Add a mail user</h3>
|
|
|
|
<p>Add an email address to this system. This will create a new login username/password.</p>
|
|
|
|
<form class="form-inline" role="form" onsubmit="return do_add_user(); return false;">
|
|
<div class="form-group">
|
|
<label class="sr-only" for="adduserEmail">Email address</label>
|
|
<input type="email" class="form-control" id="adduserEmail" placeholder="Email Address">
|
|
</div>
|
|
<div class="form-group">
|
|
<label class="sr-only" for="adduserPassword">Password</label>
|
|
<input type="password" class="form-control" id="adduserPassword" placeholder="Password">
|
|
</div>
|
|
<div class="form-group">
|
|
<select class="form-control" id="adduserPrivs">
|
|
<option value="">Normal User</option>
|
|
<option value="admin">Administrator</option>
|
|
</select>
|
|
</div>
|
|
<button type="submit" class="btn btn-primary">Add User</button>
|
|
</form>
|
|
<ul style="margin-top: 1em; padding-left: 1.5em; font-size: 90%;">
|
|
<li>Passwords must be at least four characters and may not contain spaces.</li>
|
|
<li>Use <a href="javascript:show_panel('aliases')">aliases</a> to create email addresses that forward to existing accounts.</li>
|
|
<li>Administrators get access to this control panel.</li>
|
|
<li>User accounts cannot contain any international (non-ASCII) characters, but <a href="javascript:show_panel('aliases')">aliases</a> can.</li>
|
|
</ul>
|
|
|
|
<h3>Existing mail users</h3>
|
|
<table id="user_table" class="table" style="width: auto">
|
|
<thead>
|
|
<tr>
|
|
<th width="50%">Email Address</th>
|
|
<th>Actions</th>
|
|
<th>Mailbox Size</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
</tbody>
|
|
</table>
|
|
|
|
<div style="display: none">
|
|
<table>
|
|
<tr id="user-template">
|
|
<td class='address'>
|
|
</td>
|
|
<td class='actions'>
|
|
<span class='privs'>
|
|
</span>
|
|
|
|
<span class="if_active">
|
|
<a href="#" onclick="users_set_password(this); return false;" class='setpw' title="Set Password">
|
|
set password
|
|
</a>
|
|
|
|
|
</span>
|
|
|
|
<span class='add-privs'>
|
|
</span>
|
|
|
|
<a href="#" onclick="users_remove(this); return false;" class='if_active' title="Archive Account">
|
|
archive account
|
|
</a>
|
|
</td>
|
|
<td class='mailboxsize'>
|
|
</td>
|
|
</tr>
|
|
<tr id="user-extra-template">
|
|
<td colspan="3" style="border-top: 0; padding-top: 0">
|
|
<div class='if_inactive restore_info' style='color: #888; font-size: 90%'>To restore account, create a new account with this email address. Or to permanently delete the mailbox, delete the directory <tt></tt> on the machine.</div>
|
|
|
|
<div class='aliases' style='display: none'> </div>
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</div>
|
|
|
|
|
|
<script>
|
|
function show_users() {
|
|
$('#user_table tbody').html("<tr><td colspan='2' class='text-muted'>Loading...</td></tr>")
|
|
api(
|
|
"/mail/users",
|
|
"GET",
|
|
{ format: 'json' },
|
|
function(r) {
|
|
$('#user_table tbody').html("");
|
|
for (var i = 0; i < r.length; i++) {
|
|
var hdr = $("<tr><td><h4/></td></tr>");
|
|
hdr.find('h4').text(r[i].domain);
|
|
$('#user_table tbody').append(hdr);
|
|
|
|
for (var k = 0; k < r[i].users.length; k++) {
|
|
var user = r[i].users[k];
|
|
|
|
var n = $("#user-template").clone();
|
|
var n2 = $("#user-extra-template").clone();
|
|
n.attr('id', '');
|
|
n2.attr('id', '');
|
|
$('#user_table tbody').append(n);
|
|
$('#user_table tbody').append(n2);
|
|
|
|
n.addClass("account_" + user.status);
|
|
n2.addClass("account_" + user.status);
|
|
|
|
n.attr('data-email', user.email);
|
|
n.find('.address').text(user.email)
|
|
n.find('.mailboxsize').text(nice_size(user.mailbox_size))
|
|
n2.find('.restore_info tt').text(user.mailbox);
|
|
|
|
if (user.status == 'inactive') continue;
|
|
|
|
var add_privs = ["admin"];
|
|
|
|
for (var j = 0; j < user.privileges.length; j++) {
|
|
var p = $("<span><b><span class='name'></span></b> (<a href='#' onclick='mod_priv(this, \"remove\"); return false;' title='Remove Privilege'>remove privilege</a>) |</span>");
|
|
p.find('span.name').text(user.privileges[j]);
|
|
n.find('.privs').append(p);
|
|
if (add_privs.indexOf(user.privileges[j]) >= 0)
|
|
add_privs.splice(add_privs.indexOf(user.privileges[j]), 1);
|
|
}
|
|
|
|
for (var j = 0; j < add_privs.length; j++) {
|
|
var p = $("<span><a href='#' onclick='mod_priv(this, \"add\"); return false;' title='Add Privilege'>make <span class='name'></span></a> | </span>");
|
|
p.find('span.name').text(add_privs[j]);
|
|
n.find('.add-privs').append(p);
|
|
}
|
|
|
|
if (user.aliases && user.aliases.length > 0) {
|
|
n2.find('.aliases').show();
|
|
for (var j = 0; j < user.aliases.length; j++) {
|
|
n2.find('.aliases').append($("<div/>").text(
|
|
user.aliases[j][0]
|
|
+ (user.aliases[j][1].length > 0 ? " ⇐ " + user.aliases[j][1].join(", ") : "")
|
|
))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function do_add_user() {
|
|
var email = $("#adduserEmail").val();
|
|
var pw = $("#adduserPassword").val();
|
|
var privs = $("#adduserPrivs").val();
|
|
api(
|
|
"/mail/users/add",
|
|
"POST",
|
|
{
|
|
email: email,
|
|
password: pw,
|
|
privileges: privs
|
|
},
|
|
function(r) {
|
|
// Responses are multiple lines of pre-formatted text.
|
|
show_modal_error("Add User", $("<pre/>").text(r));
|
|
show_users()
|
|
},
|
|
function(r) {
|
|
show_modal_error("Add User", r);
|
|
});
|
|
return false;
|
|
}
|
|
|
|
function users_set_password(elem) {
|
|
var email = $(elem).parents('tr').attr('data-email');
|
|
show_modal_confirm(
|
|
"Archive User",
|
|
$("<p>Set a new password for <b>" + email + "</b>?</p> <p><label for='users_set_password_pw' style='display: block; font-weight: normal'>New Password:</label><input type='password' id='users_set_password_pw'></p><p><small>Passwords must be at least four characters and may not contain spaces.</small></p>"),
|
|
"Set Password",
|
|
function() {
|
|
api(
|
|
"/mail/users/password",
|
|
"POST",
|
|
{
|
|
email: email,
|
|
password: $('#users_set_password_pw').val()
|
|
},
|
|
function(r) {
|
|
// Responses are multiple lines of pre-formatted text.
|
|
show_modal_error("Set Password", $("<pre/>").text(r));
|
|
},
|
|
function(r) {
|
|
show_modal_error("Set Password", r);
|
|
});
|
|
});
|
|
}
|
|
|
|
function users_remove(elem) {
|
|
var email = $(elem).parents('tr').attr('data-email');
|
|
show_modal_confirm(
|
|
"Archive User",
|
|
$("<p>Are you sure you want to archive <b>" + email + "</b>?</p> <p>The user's mailboxes will not be deleted (you can do that later), but the user will no longer be able to log into any services on this machine.</p>"),
|
|
"Archive",
|
|
function() {
|
|
api(
|
|
"/mail/users/remove",
|
|
"POST",
|
|
{
|
|
email: email
|
|
},
|
|
function(r) {
|
|
// Responses are multiple lines of pre-formatted text.
|
|
show_modal_error("Remove User", $("<pre/>").text(r));
|
|
show_users();
|
|
},
|
|
function(r) {
|
|
show_modal_error("Remove User", r);
|
|
});
|
|
});
|
|
}
|
|
|
|
function mod_priv(elem, add_remove) {
|
|
var email = $(elem).parents('tr').attr('data-email');
|
|
var priv = $(elem).parents('td').find('.name').text();
|
|
|
|
// can't remove your own admin access
|
|
if (priv == "admin" && add_remove == "remove" && api_credentials != null && email == api_credentials[0]) {
|
|
show_modal_error("Modify Privileges", "You cannot remove the admin privilege from yourself.");
|
|
return;
|
|
}
|
|
|
|
var add_remove1 = add_remove.charAt(0).toUpperCase() + add_remove.substring(1);
|
|
show_modal_confirm(
|
|
"Modify Privileges",
|
|
"Are you sure you want to " + add_remove + " the " + priv + " privilege for <b>" + email + "</b>?",
|
|
add_remove1,
|
|
function() {
|
|
api(
|
|
"/mail/users/privileges/" + add_remove,
|
|
"POST",
|
|
{
|
|
email: email,
|
|
privilege: priv
|
|
},
|
|
function(r) {
|
|
show_users();
|
|
});
|
|
});
|
|
}
|
|
</script>
|