mirror of
https://github.com/mail-in-a-box/mailinabox.git
synced 2024-11-22 02:17:26 +00:00
make a privileges column in the users table and mark the first user as an admin
This commit is contained in:
parent
880ec44a0c
commit
b56f82cb92
@ -1,12 +1,14 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import os, os.path, re
|
import os, os.path, re, json
|
||||||
|
|
||||||
from flask import Flask, request, render_template, abort
|
from flask import Flask, request, render_template, abort, Response
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
import auth, utils
|
import auth, utils
|
||||||
from mailconfig import get_mail_users, add_mail_user, set_mail_password, remove_mail_user, get_mail_aliases, get_mail_domains, add_mail_alias, remove_mail_alias
|
from mailconfig import get_mail_users, 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_domains, add_mail_alias, remove_mail_alias
|
||||||
|
|
||||||
env = utils.load_environment()
|
env = utils.load_environment()
|
||||||
|
|
||||||
@ -29,6 +31,10 @@ def index():
|
|||||||
|
|
||||||
@app.route('/mail/users')
|
@app.route('/mail/users')
|
||||||
def mail_users():
|
def mail_users():
|
||||||
|
if request.args.get("format", "") == "json":
|
||||||
|
users = get_mail_users(env, as_json=True)
|
||||||
|
return Response(json.dumps(users), status=200, mimetype='application/json')
|
||||||
|
else:
|
||||||
return "".join(x+"\n" for x in get_mail_users(env))
|
return "".join(x+"\n" for x in get_mail_users(env))
|
||||||
|
|
||||||
@app.route('/mail/users/add', methods=['POST'])
|
@app.route('/mail/users/add', methods=['POST'])
|
||||||
@ -43,6 +49,22 @@ def mail_users_password():
|
|||||||
def mail_users_remove():
|
def mail_users_remove():
|
||||||
return remove_mail_user(request.form.get('email', ''), env)
|
return remove_mail_user(request.form.get('email', ''), env)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route('/mail/users/privileges')
|
||||||
|
def mail_user_privs():
|
||||||
|
privs = get_mail_user_privileges(request.args.get('email', ''), env)
|
||||||
|
if isinstance(privs, tuple): return privs # error
|
||||||
|
return "\n".join(privs)
|
||||||
|
|
||||||
|
@app.route('/mail/users/privileges/add', methods=['POST'])
|
||||||
|
def mail_user_privs_add():
|
||||||
|
return add_remove_mail_user_privilege(request.form.get('email', ''), request.form.get('privilege', ''), "add", env)
|
||||||
|
|
||||||
|
@app.route('/mail/users/privileges/remove', methods=['POST'])
|
||||||
|
def mail_user_privs_remove():
|
||||||
|
return add_remove_mail_user_privilege(request.form.get('email', ''), request.form.get('privilege', ''), "remove", env)
|
||||||
|
|
||||||
|
|
||||||
@app.route('/mail/aliases')
|
@app.route('/mail/aliases')
|
||||||
def mail_aliases():
|
def mail_aliases():
|
||||||
return "".join(x+"\t"+y+"\n" for x, y in get_mail_aliases(env))
|
return "".join(x+"\t"+y+"\n" for x, y in get_mail_aliases(env))
|
||||||
|
@ -46,10 +46,16 @@ def open_database(env, with_connection=False):
|
|||||||
else:
|
else:
|
||||||
return conn, conn.cursor()
|
return conn, conn.cursor()
|
||||||
|
|
||||||
def get_mail_users(env):
|
def get_mail_users(env, as_json=False):
|
||||||
c = open_database(env)
|
c = open_database(env)
|
||||||
c.execute('SELECT email FROM users')
|
c.execute('SELECT email, privileges FROM users')
|
||||||
|
if not as_json:
|
||||||
return [row[0] for row in c.fetchall()]
|
return [row[0] for row in c.fetchall()]
|
||||||
|
else:
|
||||||
|
return [
|
||||||
|
{ "email": row[0], "privileges": parse_privs(row[1]) }
|
||||||
|
for row in c.fetchall()
|
||||||
|
]
|
||||||
|
|
||||||
def get_mail_aliases(env):
|
def get_mail_aliases(env):
|
||||||
c = open_database(env)
|
c = open_database(env)
|
||||||
@ -122,6 +128,40 @@ def remove_mail_user(email, env):
|
|||||||
# 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")
|
||||||
|
|
||||||
|
def parse_privs(value):
|
||||||
|
return [p for p in value.split("\n") if p.strip() != ""]
|
||||||
|
|
||||||
|
def get_mail_user_privileges(email, env):
|
||||||
|
c = open_database(env)
|
||||||
|
c.execute('SELECT privileges FROM users WHERE email=?', (email,))
|
||||||
|
rows = c.fetchall()
|
||||||
|
if len(rows) != 1:
|
||||||
|
return ("That's not a user (%s)." % email, 400)
|
||||||
|
return parse_privs(rows[0][0])
|
||||||
|
|
||||||
|
def add_remove_mail_user_privilege(email, priv, action, env):
|
||||||
|
if "\n" in priv or priv.strip() == "":
|
||||||
|
return ("That's not a valid privilege (%s)." % priv, 400)
|
||||||
|
|
||||||
|
privs = get_mail_user_privileges(email, env)
|
||||||
|
if isinstance(privs, tuple): return privs # error
|
||||||
|
|
||||||
|
if action == "add":
|
||||||
|
if priv not in privs:
|
||||||
|
privs.append(priv)
|
||||||
|
elif action == "remove":
|
||||||
|
privs = [p for p in privs if p != priv]
|
||||||
|
else:
|
||||||
|
return ("Invalid action.", 400)
|
||||||
|
|
||||||
|
conn, c = open_database(env, with_connection=True)
|
||||||
|
c.execute("UPDATE users SET privileges=? WHERE email=?", ("\n".join(privs), email))
|
||||||
|
if c.rowcount != 1:
|
||||||
|
return ("Something went wrong.", 400)
|
||||||
|
conn.commit()
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
|
||||||
def add_mail_alias(source, destination, env, do_kick=True):
|
def add_mail_alias(source, destination, env, do_kick=True):
|
||||||
if not validate_email(source, mode='alias'):
|
if not validate_email(source, mode='alias'):
|
||||||
return ("Invalid email address.", 400)
|
return ("Invalid email address.", 400)
|
||||||
|
@ -17,7 +17,7 @@ db_path=$STORAGE_ROOT/mail/users.sqlite
|
|||||||
# Create an empty database if it doesn't yet exist.
|
# Create an empty database if it doesn't yet exist.
|
||||||
if [ ! -f $db_path ]; then
|
if [ ! -f $db_path ]; then
|
||||||
echo Creating new user database: $db_path;
|
echo Creating new user database: $db_path;
|
||||||
echo "CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra);" | sqlite3 $db_path;
|
echo "CREATE TABLE users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT NOT NULL UNIQUE, password TEXT NOT NULL, extra, privileges TEXT NOT NULL DEFAULT '');" | sqlite3 $db_path;
|
||||||
echo "CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL);" | sqlite3 $db_path;
|
echo "CREATE TABLE aliases (id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL UNIQUE, destination TEXT NOT NULL);" | sqlite3 $db_path;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
import sys, os, os.path, glob, re, shutil
|
import sys, os, os.path, glob, re, shutil
|
||||||
|
|
||||||
sys.path.insert(0, 'management')
|
sys.path.insert(0, 'management')
|
||||||
from utils import load_environment, save_environment, safe_domain_name
|
from utils import load_environment, save_environment, shell
|
||||||
|
|
||||||
def migration_1(env):
|
def migration_1(env):
|
||||||
# Re-arrange where we store SSL certificates. There was a typo also.
|
# Re-arrange where we store SSL certificates. There was a typo also.
|
||||||
@ -51,6 +51,11 @@ def migration_3(env):
|
|||||||
# of the file will be handled by the main function.
|
# of the file will be handled by the main function.
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def migration_4(env):
|
||||||
|
# Add a new column to the mail users table where we can store administrative privileges.
|
||||||
|
db = os.path.join(env["STORAGE_ROOT"], 'mail/users.sqlite')
|
||||||
|
shell("check_call", ["sqlite3", db, "ALTER TABLE users ADD privileges TEXT NOT NULL DEFAULT ''"])
|
||||||
|
|
||||||
def get_current_migration():
|
def get_current_migration():
|
||||||
ver = 0
|
ver = 0
|
||||||
while True:
|
while True:
|
||||||
|
@ -302,17 +302,21 @@ if [ -z "`tools/mail.py user`" ]; then
|
|||||||
EMAIL_ADDR=me@$PRIMARY_HOSTNAME
|
EMAIL_ADDR=me@$PRIMARY_HOSTNAME
|
||||||
EMAIL_PW=1234
|
EMAIL_PW=1234
|
||||||
echo
|
echo
|
||||||
echo "Creating a new mail account for $EMAIL_ADDR with password $EMAIL_PW."
|
echo "Creating a new administrative mail account for $EMAIL_ADDR with password $EMAIL_PW."
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
echo
|
echo
|
||||||
echo "Okay. I'm about to set up $EMAIL_ADDR for you."
|
echo "Okay. I'm about to set up $EMAIL_ADDR for you. This account will also"
|
||||||
|
echo "have access to the box's control panel."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Create the user's mail account. This will ask for a password if none was given above.
|
# Create the user's mail account. This will ask for a password if none was given above.
|
||||||
tools/mail.py user add $EMAIL_ADDR $EMAIL_PW
|
tools/mail.py user add $EMAIL_ADDR $EMAIL_PW
|
||||||
|
|
||||||
|
# Make it an admin.
|
||||||
|
hide_output tools/mail.py user make-admin $EMAIL_ADDR
|
||||||
|
|
||||||
# Create an alias to which we'll direct all automatically-created administrative aliases.
|
# Create an alias to which we'll direct all automatically-created administrative aliases.
|
||||||
tools/mail.py alias add administrator@$PRIMARY_HOSTNAME $EMAIL_ADDR
|
tools/mail.py alias add administrator@$PRIMARY_HOSTNAME $EMAIL_ADDR
|
||||||
fi
|
fi
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
|
|
||||||
import sys, getpass, urllib.request, urllib.error
|
import sys, getpass, urllib.request, urllib.error, json
|
||||||
|
|
||||||
def mgmt(cmd, data=None):
|
def mgmt(cmd, data=None, is_json=False):
|
||||||
mgmt_uri = 'http://localhost:10222'
|
mgmt_uri = 'http://localhost:10222'
|
||||||
|
|
||||||
setup_key_auth(mgmt_uri)
|
setup_key_auth(mgmt_uri)
|
||||||
@ -18,7 +18,9 @@ def mgmt(cmd, data=None):
|
|||||||
else:
|
else:
|
||||||
print(e, file=sys.stderr)
|
print(e, file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
return response.read().decode('utf8')
|
resp = response.read().decode('utf8')
|
||||||
|
if is_json: resp = json.loads(resp)
|
||||||
|
return resp
|
||||||
|
|
||||||
def read_password():
|
def read_password():
|
||||||
first = getpass.getpass('password: ')
|
first = getpass.getpass('password: ')
|
||||||
@ -47,6 +49,8 @@ if len(sys.argv) < 2:
|
|||||||
print(" tools/mail.py user add user@domain.com [password]")
|
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 password user@domain.com [password]")
|
||||||
print(" tools/mail.py user remove user@domain.com")
|
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")
|
||||||
print(" tools/mail.py alias (lists aliases)")
|
print(" tools/mail.py alias (lists aliases)")
|
||||||
print(" tools/mail.py alias add incoming.name@domain.com sent.to@other.domain.com")
|
print(" tools/mail.py alias add incoming.name@domain.com sent.to@other.domain.com")
|
||||||
print(" tools/mail.py alias remove incoming.name@domain.com")
|
print(" tools/mail.py alias remove incoming.name@domain.com")
|
||||||
@ -55,7 +59,13 @@ if len(sys.argv) < 2:
|
|||||||
print()
|
print()
|
||||||
|
|
||||||
elif sys.argv[1] == "user" and len(sys.argv) == 2:
|
elif sys.argv[1] == "user" and len(sys.argv) == 2:
|
||||||
print(mgmt("/mail/users"))
|
# Dump a list of users, one per line. Mark admins with an asterisk.
|
||||||
|
users = mgmt("/mail/users?format=json", is_json=True)
|
||||||
|
for user in users:
|
||||||
|
print(user['email'], end='')
|
||||||
|
if "admin" in user['privileges']:
|
||||||
|
print("*", end='')
|
||||||
|
print()
|
||||||
|
|
||||||
elif sys.argv[1] == "user" and sys.argv[2] in ("add", "password"):
|
elif sys.argv[1] == "user" and sys.argv[2] in ("add", "password"):
|
||||||
if len(sys.argv) < 5:
|
if len(sys.argv) < 5:
|
||||||
@ -75,6 +85,13 @@ elif sys.argv[1] == "user" and sys.argv[2] in ("add", "password"):
|
|||||||
elif sys.argv[1] == "user" and sys.argv[2] == "remove" and len(sys.argv) == 4:
|
elif sys.argv[1] == "user" and sys.argv[2] == "remove" and len(sys.argv) == 4:
|
||||||
print(mgmt("/mail/users/remove", { "email": sys.argv[3] }))
|
print(mgmt("/mail/users/remove", { "email": sys.argv[3] }))
|
||||||
|
|
||||||
|
elif sys.argv[1] == "user" and sys.argv[2] in ("make-admin", "remove-admin") and len(sys.argv) == 4:
|
||||||
|
if sys.argv[2] == "make-admin":
|
||||||
|
action = "add"
|
||||||
|
else:
|
||||||
|
action = "remove"
|
||||||
|
print(mgmt("/mail/users/privileges/" + action, { "email": sys.argv[3], "privilege": "admin" }))
|
||||||
|
|
||||||
elif sys.argv[1] == "alias" and len(sys.argv) == 2:
|
elif sys.argv[1] == "alias" and len(sys.argv) == 2:
|
||||||
print(mgmt("/mail/aliases"))
|
print(mgmt("/mail/aliases"))
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user