1
0
mirror of https://github.com/mail-in-a-box/mailinabox.git synced 2024-12-25 07:47:05 +00:00

Add components to user interface for setting quotas

This commit is contained in:
John Supplee 2019-01-28 23:27:03 +02:00
parent 8b95fac8c5
commit ccad47937e
3 changed files with 72 additions and 4 deletions

View File

@ -9,7 +9,7 @@ import auth, utils, multiprocessing.pool
from mailconfig import get_mail_users, get_mail_users_ex, get_admins, add_mail_user, set_mail_password, remove_mail_user from mailconfig import get_mail_users, get_mail_users_ex, get_admins, add_mail_user, set_mail_password, remove_mail_user
from mailconfig import get_mail_user_privileges, add_remove_mail_user_privilege from mailconfig import get_mail_user_privileges, add_remove_mail_user_privilege
from mailconfig import get_mail_aliases, get_mail_aliases_ex, get_mail_domains, add_mail_alias, remove_mail_alias from mailconfig import get_mail_aliases, get_mail_aliases_ex, get_mail_domains, add_mail_alias, remove_mail_alias
from mailconfig import set_mail_quota
env = utils.load_environment() env = utils.load_environment()
auth_service = auth.KeyAuthService() auth_service = auth.KeyAuthService()
@ -158,6 +158,14 @@ def mail_users_add():
except ValueError as e: except ValueError as e:
return (str(e), 400) return (str(e), 400)
@app.route('/mail/users/quota', methods=['POST'])
@authorized_personnel_only
def mail_users_quota():
try:
return set_mail_quota(request.form.get('email', ''), request.form.get('quota'), env)
except ValueError as e:
return (str(e), 400)
@app.route('/mail/users/password', methods=['POST']) @app.route('/mail/users/password', methods=['POST'])
@authorized_personnel_only @authorized_personnel_only
def mail_users_password(): def mail_users_password():

View File

@ -135,7 +135,7 @@ def get_mail_users_ex(env, with_archived=False):
user = { user = {
"email": email, "email": email,
"privileges": parse_privs(privileges), "privileges": parse_privs(privileges),
"quota": 'unlimited' if quota == '0' else quota, "quota": quota,
"status": "active", "status": "active",
} }
users.append(user) users.append(user)
@ -333,6 +333,31 @@ def hash_password(pw):
# http://wiki2.dovecot.org/Authentication/PasswordSchemes # http://wiki2.dovecot.org/Authentication/PasswordSchemes
return utils.shell('check_output', ["/usr/bin/doveadm", "pw", "-s", "SHA512-CRYPT", "-p", pw]).strip() return utils.shell('check_output', ["/usr/bin/doveadm", "pw", "-s", "SHA512-CRYPT", "-p", pw]).strip()
def set_mail_quota(email, quota, env):
# validate that password is acceptable
quota = validate_quota(quota)
# update the database
conn, c = open_database(env, with_connection=True)
c.execute("UPDATE users SET quota=? WHERE email=?", (quota, email))
if c.rowcount != 1:
return ("That's not a user (%s)." % email, 400)
conn.commit()
return "OK"
def validate_quota(quota):
# validate quota
quota = quota.strip().upper()
if quota == "":
raise ValueError("No quota provided.")
if re.search(r"[\s,.]", quota):
raise ValueError("Quotas cannot contain spaces or commas.")
if not re.match(r'^\d+[GM]?$', quota):
raise ValueError("Invalid quota.")
return quota
def get_mail_password(email, env): def get_mail_password(email, env):
# Gets the hashed password for a user. Passwords are stored in Dovecot's # Gets the hashed password for a user. Passwords are stored in Dovecot's
# password format, with a prefixed scheme. # password format, with a prefixed scheme.

View File

@ -41,7 +41,7 @@
<table id="user_table" class="table" style="width: auto"> <table id="user_table" class="table" style="width: auto">
<thead> <thead>
<tr> <tr>
<th width="50%">Email Address</th> <th width="35%">Email Address</th>
<th>Quota</th> <th>Quota</th>
<th>Actions</th> <th>Actions</th>
</tr> </tr>
@ -61,6 +61,10 @@
<span class='privs'> <span class='privs'>
</span> </span>
<a href="#" onclick="users_set_quota(this); return false;" class='setquota' title="Set Quota">
set quota
</a>
|
<span class="if_active"> <span class="if_active">
<a href="#" onclick="users_set_password(this); return false;" class='setpw' title="Set Password"> <a href="#" onclick="users_set_password(this); return false;" class='setpw' title="Set Password">
set password set password
@ -155,8 +159,9 @@ function show_users() {
n2.addClass("account_" + user.status); n2.addClass("account_" + user.status);
n.attr('data-email', user.email); n.attr('data-email', user.email);
n.attr('data-quota', user.quota);
n.find('.address').text(user.email); n.find('.address').text(user.email);
n.find('.quota').text(user.quota); n.find('.quota').text((user.quota == '0') ? 'unlimited' : user.quota);
n2.find('.restore_info tt').text(user.mailbox); n2.find('.restore_info tt').text(user.mailbox);
if (user.status == 'inactive') continue; if (user.status == 'inactive') continue;
@ -233,6 +238,36 @@ function users_set_password(elem) {
}); });
} }
function users_set_quota(elem) {
var email = $(elem).parents('tr').attr('data-email');
var quota = $(elem).parents('tr').attr('data-quota');
show_modal_confirm(
"Set Quota",
$("<p>Set quota for <b>" + email + "</b>?</p>" +
"<p>" +
"<label for='users_set_quota' style='display: block; font-weight: normal'>Quota:</label>" +
"<input type='text' id='users_set_quota' value='" + quota + "'></p>" +
"<p><small>Quotas may not contain any numbers or commas. Suffixes of G (gigabytes) and M (megabytes) are allowed.</small></p>" +
"<p><small>For unlimited storage enter 0 (zero)</small></p>"),
"Set Quota",
function() {
api(
"/mail/users/quota",
"POST",
{
email: email,
quota: $('#users_set_quota').val()
},
function(r) {
show_users();
},
function(r) {
show_modal_error("Set Quota", r);
});
});
}
function users_remove(elem) { function users_remove(elem) {
var email = $(elem).parents('tr').attr('data-email'); var email = $(elem).parents('tr').attr('data-email');