diff --git a/README.md b/README.md index 4991ebb1..680ac766 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,19 @@ Todo Changes ------- +### v0.40-quota-0.13-alpha + +* Add a `default-quota` setting in `settings.yaml` + +* Add input for setting quota when entering a new user in control panel + +* Modify `tools/mail.py` to allow for setting and getting the default system quota + +* Modify `tools/mail.py` to allow for getting a user's quota setting + +* Modify the mail users list in control panel to display percentage used + + ### v0.40-quota-0.12-alpha * Update README diff --git a/management/daemon.py b/management/daemon.py index eb467681..9d5f6a36 100755 --- a/management/daemon.py +++ b/management/daemon.py @@ -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_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 set_mail_quota, get_default_quota, validate_quota +from mailconfig import get_mail_quota, set_mail_quota, get_default_quota, validate_quota env = utils.load_environment() auth_service = auth.KeyAuthService() @@ -153,11 +153,26 @@ def mail_users(): @app.route('/mail/users/add', methods=['POST']) @authorized_personnel_only def mail_users_add(): + quota = request.form.get('quota', get_default_quota(env)) try: - return add_mail_user(request.form.get('email', ''), request.form.get('password', ''), request.form.get('privileges', ''), request.form.get('quota', ''), env) + return add_mail_user(request.form.get('email', ''), request.form.get('password', ''), request.form.get('privileges', ''), quota, env) except ValueError as e: return (str(e), 400) +@app.route('/mail/users/quota', methods=['GET']) +@authorized_personnel_only +def get_mail_users_quota(): + email = request.values.get('email', '') + quota = get_mail_quota(email, env) + + if request.values.get('text'): + return quota + + return json_response({ + "email": email, + "quota": quota + }) + @app.route('/mail/users/quota', methods=['POST']) @authorized_personnel_only def mail_users_quota(): @@ -531,16 +546,19 @@ def privacy_status_set(): @app.route('/system/default-quota', methods=["GET"]) @authorized_personnel_only def default_quota_get(): - return json_response({ - "default-quota": get_default_quota(env) - }) + if request.values.get('text'): + return get_default_quota(env) + else: + return json_response({ + "default-quota": get_default_quota(env), + }) @app.route('/system/default-quota', methods=["POST"]) @authorized_personnel_only def default_quota_set(): config = utils.load_settings(env) try: - config["default-quota"] = validate_quota(request.form.get('default_quota')) + config["default-quota"] = validate_quota(request.values.get('default_quota')) utils.write_settings(config, env) except ValueError as e: diff --git a/management/mailconfig.py b/management/mailconfig.py index 92f26dfc..8e4198a6 100755 --- a/management/mailconfig.py +++ b/management/mailconfig.py @@ -147,18 +147,30 @@ def get_mail_users_ex(env, with_archived=False): (user, domain) = email.split('@') box_size = 0 box_count = 0 - box_quota = '' + box_quota = 0 + percent = '' try: dirsize_file = os.path.join(env['STORAGE_ROOT'], 'mail/mailboxes/%s/%s/maildirsize' % (domain, user)) with open(dirsize_file, 'r') as f: - box_quota = f.readline() + box_quota = int(f.readline().split('S')[0]) for line in f.readlines(): (size, count) = line.split(' ') box_size += int(size) box_count += int(count) + + try: + percent = (box_size / box_quota) * 100 + except: + percent = 'Error' + except: box_size = '?' box_count = '?' + box_quota = '?' + percent = '?' + + if quota == '0': + percent = '' user = { "email": email, @@ -166,6 +178,7 @@ def get_mail_users_ex(env, with_archived=False): "quota": quota, "box_quota": box_quota, "box_size": sizeof_fmt(box_size) if box_size != '?' else box_size, + "percent": '%3.0f%%' % percent if type(percent) != str else percent, "box_count": box_count, "status": "active", } @@ -324,6 +337,9 @@ def add_mail_user(email, pw, privs, quota, env): validation = validate_privilege(p) if validation: return validation + if quota is None: + quota = get_default_quota() + try: quota = validate_quota(quota) except ValueError as e: @@ -338,7 +354,7 @@ def add_mail_user(email, pw, privs, quota, env): # add the user to the database try: c.execute("INSERT INTO users (email, password, privileges, quota) VALUES (?, ?, ?, ?)", - (email, pw, "\n".join(privs)), quota) + (email, pw, "\n".join(privs), quota)) except sqlite3.IntegrityError: return ("User already exists.", 400) @@ -369,6 +385,15 @@ def hash_password(pw): # http://wiki2.dovecot.org/Authentication/PasswordSchemes return utils.shell('check_output', ["/usr/bin/doveadm", "pw", "-s", "SHA512-CRYPT", "-p", pw]).strip() +def get_mail_quota(email, env): + conn, c = open_database(env, with_connection=True) + c.execute("SELECT quota FROM users WHERE email=?", (email,)) + rows = c.fetchall() + if len(rows) != 1: + return ("That's not a user (%s)." % email, 400) + + return rows[0][0] + def set_mail_quota(email, quota, env): # validate that password is acceptable quota = validate_quota(quota) diff --git a/management/templates/users.html b/management/templates/users.html index 1b1e566d..1d176de8 100644 --- a/management/templates/users.html +++ b/management/templates/users.html @@ -7,6 +7,7 @@ #user_table .account_inactive .if_active { display: none; } #user_table .account_active .if_inactive { display: none; } #user_table .account_active.if_inactive { display: none; } +.row-center { text-align: center; }

Add a mail user

@@ -47,9 +48,10 @@ Email Address - Messages - Size - Quota + Messages + Size + Used + Quota Actions @@ -62,9 +64,10 @@ - - - + + + + @@ -159,7 +162,7 @@ function show_users() { function(r) { $('#user_table tbody').html(""); for (var i = 0; i < r.length; i++) { - var hdr = $("

"); + var hdr = $("

"); hdr.find('h4').text(r[i].domain); $('#user_table tbody').append(hdr); @@ -180,7 +183,14 @@ function show_users() { n.attr('data-quota', user.quota); n.find('.address').text(user.email); n.find('.box-count').text(user.box_count); + if (user.box_count == '?') { + n.find('.box-count').attr('title', 'Message count is unkown') + } n.find('.box-size').text(user.box_size); + if (user.box_size == '?') { + n.find('.box-size').attr('title', 'Mailbox size is unkown') + } + n.find('.percent').text(user.percent) n.find('.quota').text((user.quota == '0') ? 'unlimited' : user.quota); n2.find('.restore_info tt').text(user.mailbox); diff --git a/tools/mail.py b/tools/mail.py index 7a7b8b8e..2807d87d 100755 --- a/tools/mail.py +++ b/tools/mail.py @@ -57,10 +57,11 @@ def setup_key_auth(mgmt_uri): if len(sys.argv) < 2: print("Usage: ") + print(" tools/mail.py system default-quota [new default]") print(" tools/mail.py user (lists users with quotas)") print(" tools/mail.py user add user@domain.com [password]") print(" tools/mail.py user password user@domain.com [password]") - print(" tools/mail.py user quota user@domain new-quota") + print(" tools/mail.py user quota user@domain [new-quota]") print(" tools/mail.py user remove user@domain.com") print(" tools/mail.py user make-admin user@domain.com") print(" tools/mail.py user remove-admin user@domain.com") @@ -121,6 +122,10 @@ elif sys.argv[1] == "user" and sys.argv[2] == "admins": if "admin" in user['privileges']: print(user['email']) +elif sys.argv[1] == "user" and sys.argv[2] == "quota" and len(sys.argv) == 4: + # Set a user's quota + print(mgmt("/mail/users/quota?text=1&email=%s" % sys.argv[3])) + elif sys.argv[1] == "user" and sys.argv[2] == "quota" and len(sys.argv) == 5: # Set a user's quota users = mgmt("/mail/users/quota", { "email": sys.argv[3], "quota": sys.argv[4] }) @@ -134,6 +139,12 @@ elif sys.argv[1] == "alias" and sys.argv[2] == "add" and len(sys.argv) == 5: elif sys.argv[1] == "alias" and sys.argv[2] == "remove" and len(sys.argv) == 4: print(mgmt("/mail/aliases/remove", { "address": sys.argv[3] })) +elif sys.argv[1] == "system" and sys.argv[2] == "default-quota" and len(sys.argv) == 3: + print(mgmt("/system/default-quota?text=1")) + +elif sys.argv[1] == "system" and sys.argv[2] == "default-quota" and len(sys.argv) == 4: + print(mgmt("/system/default-quota", { "default_quota": sys.argv[3]})) + else: print("Invalid command-line arguments.") sys.exit(1)