883: Admin create user enhancement r=mergify[bot] a=cr1st1p

## What type of PR?
Enhancement

## What does this PR do?
It allows the admin docker image to also create the admin user.
The idea is that in my kubernetes setup, I do not want to manually do anything, as such, I need a way for the admin user to also be created automatically without me getting inside the pod.
So I had to change the manage.py function that creates the user to allow different 'modes' (me, I'll be using 'ifmissing') and also start.py to call that functionality if appropriate environment variables are present.

So now, in my Deployment, I add 3 more environment variables and I get the admin user created, IF not already present.

### Related issue(s)
none?

## Prerequistes
Before we can consider review and merge, please make sure the following list is done and checked.
If an entry in not applicable, you can check it or remove it from the list.

- [x] In case of feature or enhancement: documentation updated accordingly
- [x] Unless it's docs or a minor change: place entry in the [changelog](CHANGELOG.md), under the latest un-released version.


Co-authored-by: cristi <cristi.posoiu@gmail.com>
Co-authored-by: cr1st1p <cristi.posoiu@gmail.com>
Co-authored-by: Tim Möhlmann <muhlemmer@gmail.com>
master
bors[bot] 5 years ago committed by GitHub
commit 2785bca1f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -13,6 +13,7 @@ v1.6.1 - unreleased
- Enhancement: Make Unbound drop privileges after binding to port
- Enhancement: Stop using static assets, but build them using Webpack
- Enhancement: Create an Authentication Token with IPv6 address restriction ([#829](https://github.com/Mailu/Mailu/issues/829))
- Enhancement: Automatically create admin user on container startup if given appropriate environment variables
- Enhancement: Missing wildcard option in alias flask command ([#869](https://github.com/Mailu/Mailu/issues/869))
- Bug: Fix creating new fetched accounts
- Bug: Fix poor performance if ANTIVIRUS is configured to none.

@ -42,22 +42,44 @@ def advertise():
@click.argument('localpart')
@click.argument('domain_name')
@click.argument('password')
@click.option('-m', '--mode')
@flask_cli.with_appcontext
def admin(localpart, domain_name, password):
def admin(localpart, domain_name, password, mode='create'):
""" Create an admin user
'mode' can be:
- 'create' (default) Will try to create user and will raise an exception if present
- 'ifmissing': if user exists, nothing happens, else it will be created
- 'update': user is created or, if it exists, its password gets updated
"""
domain = models.Domain.query.get(domain_name)
if not domain:
domain = models.Domain(name=domain_name)
db.session.add(domain)
user = models.User(
localpart=localpart,
domain=domain,
global_admin=True
)
user.set_password(password)
db.session.add(user)
db.session.commit()
user = None
if mode == 'ifmissing' or mode == 'update':
email = '{}@{}'.format(localpart, domain_name)
user = models.User.query.get(email)
if user and mode == 'ifmissing':
print('user %s exists, not updating' % email)
return
if not user:
user = models.User(
localpart=localpart,
domain=domain,
global_admin=True
)
user.set_password(password)
db.session.add(user)
db.session.commit()
print("created admin user")
elif mode == 'update':
user.set_password(password)
db.session.commit()
print("updated admin password")
@mailu.command()

@ -4,4 +4,13 @@ import os
os.system("flask mailu advertise")
os.system("flask db upgrade")
account = os.environ.get("INITIAL_ADMIN_ACCOUNT")
domain = os.environ.get("INITIAL_ADMIN_DOMAIN")
password = os.environ.get("INITIAL_ADMIN_PW")
if account is not None and domain is not None and password is not None:
mode = os.environ.get("INITIAL_ADMIN_MODE", default="ifmissing")
os.system("flask mailu admin %s %s '%s' --mode %s" % (account, domain, password, mode))
os.system("gunicorn -w 4 -b :80 --access-logfile - --error-logfile - --preload 'mailu:create_app()'")

@ -96,7 +96,13 @@ You may now start Mailu. Move the to the Mailu directory and run:
docker-compose up -d
Finally, you must create the initial admin user account:
Finally, you need an admin user account.
You can have the system create it automatically:
use the environment variables ``INITIAL_ACCOUNT*`` as described in :ref:`admin_account`
You should set ``INITIAL_ADMIN_MODE`` also to either ``update`` or ``ifmissing``. Leaving it with the default value could cause errors when restarting the system.
Else, if you don't go with the automatic way, you need to manually create the admin account now:
.. code-block:: bash

@ -92,6 +92,31 @@ Both ``SITENAME`` and ``WEBSITE`` are customization options for the panel menu
in the admin interface, while ``SITENAME`` is a customization option for
every Web interface.
.. _admin_account:
Admin account - automatic creation
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
For administrative tasks, an admin user account will be needed. You can create it manually,
after deploying the system, or automatically.
To create it manually, follow the specific deployment method documentation.
To have the account created automatically, you just need to define a few environment variables:
.. code-block:: bash
INITIAL_ADMIN_ACCOUNT = ``root`` The first part of the e-mail address (ROOT@example.com)
INITIAL_ADMIN_DOMAIN = ``example.com`` the domain appendix. Most probably identical to the DOMAIN variable
INITIAL_ADMIN_PW = ``password`` the chosen password for the user
Also, environment variable ``INITIAL_ADMIN_MODE`` defines how the code should behave when it will
try to create the admin user:
- ``create`` (default) Will try to create user and will raise an exception if present
- ``ifmissing``: if user exists, nothing happens, else it will be created
- ``update``: user is created or, if it exists, its password gets updated
Depending on your particular deployment you most probably will want to change the default.
Advanced settings
-----------------

@ -117,7 +117,17 @@ Create the first admin account
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When the cluster is online you need to create you master user to access https://mail.example.com/admin
Enter the main ``admin`` pod to create the root account:
You can create it now manually, or have the system create it automatically.
If you want the system to create the admin user account automatically, see :ref:`admin_account`
about the environment variables needed (``INITIAL_ADMIN_*``).
Also, important, taking into consideration that a pod in Kubernetes can be stopped/rescheduled at
any time, you should set ``INITIAL_ADMIN_MODE`` to either ``update`` or ``ifmissing`` - depending on what you
want to happen to its password.
To create the admin user account manually, enter the main ``admin`` pod:
.. code-block:: bash
@ -131,13 +141,14 @@ And in the pod run the following command. The command uses following entries:
flask mailu admin root example.com password
- ``admin`` Make it an admin user
- ``root`` The first part of the e-mail adres (ROOT@example.com)
- ``root`` The first part of the e-mail address (ROOT@example.com)
- ``example.com`` the domain appendix
- ``password`` the chosen password for the user
Now you should be able to login on the mail account: https://mail.example.com/admin
Adaptations
-----------

@ -1,5 +1,11 @@
echo "Creating users ..."
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu admin admin mailu.io password || exit 1
echo "Users tests ..."
# Should fail, admin is already auto-created
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu admin admin mailu.io 'FooBar' && exit 1
echo "The above error was intended!"
# Should not fail, but does nothing; ifmissing mode
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu admin admin mailu.io 'FooBar' --mode=ifmissing || exit 1
# Should not fail and update the password; update mode
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu admin admin mailu.io 'password' --mode=update || exit 1
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu user user mailu.io 'password' 'SHA512-CRYPT' || exit 1
docker-compose -f tests/compose/core/docker-compose.yml exec admin flask mailu user 'user/with/slash' mailu.io 'password' 'SHA512-CRYPT' || exit 1
echo "Admin and user successfully created!"
echo "User testing succesfull!"

@ -140,3 +140,8 @@ REAL_IP_FROM=
# choose wether mailu bounces (no) or rejects (yes) mail when recipient is unknown (value: yes, no)
REJECT_UNLISTED_RECIPIENT=
# Test for initial admin create
INITIAL_ADMIN_ACCOUNT=admin
INITIAL_ADMIN_DOMAIN=mailu.io
INITIAL_ADMIN_PW=FooBar
Loading…
Cancel
Save