diff --git a/actions/email_server b/actions/email_server index 39b39610c..1cc122e5d 100755 --- a/actions/email_server +++ b/actions/email_server @@ -32,9 +32,9 @@ def main(): parser = argparse.ArgumentParser() group = parser.add_mutually_exclusive_group(required=True) - group.add_argument('-i', nargs=2, dest='ipc') - group.add_argument('-t', nargs=1, dest='touch_file') + group.add_argument('-i', nargs='+', dest='ipc') + # Select the first non-empty dict item adict = vars(parser.parse_args()) generator = (kv for kv in adict.items() if kv[1] is not None) subcommand, arguments = next(generator) @@ -49,7 +49,7 @@ def main(): @reserved_for_root -def subcommand_ipc(module_name, action_name): +def subcommand_ipc(module_name, action_name, *args): import plinth.modules.email_server.audit as audit # We only run actions defined in the audit module @@ -63,18 +63,7 @@ def subcommand_ipc(module_name, action_name): logger.critical('Bad action: %s/%r', module_name, action_name) sys.exit(EXIT_SYNTAX) - function() - - -def subcommand_touch_file(path): - import pathlib - - if os.getuid() == 0: - logger.critical('Do not run the `-t` option as root') - sys.exit(EXIT_PERM) - - # mode is influenced by umask - pathlib.Path(path).touch(mode=0o660, exist_ok=True) + function(*args) def _log_additional_info(): diff --git a/plinth/modules/email_server/__init__.py b/plinth/modules/email_server/__init__.py index 15fe9df30..4a8137cae 100644 --- a/plinth/modules/email_server/__init__.py +++ b/plinth/modules/email_server/__init__.py @@ -63,7 +63,7 @@ class EmailServerApp(plinth.app.App): name=info.name, short_description=info.short_description, icon='roundcube', - url=reverse_lazy('email_server:my_aliases'), + url=reverse_lazy('email_server:my_mail'), clients=manifest.clients, login_required=True ) diff --git a/plinth/modules/email_server/audit/__init__.py b/plinth/modules/email_server/audit/__init__.py index 41f1b99c6..4adc7489b 100644 --- a/plinth/modules/email_server/audit/__init__.py +++ b/plinth/modules/email_server/audit/__init__.py @@ -3,8 +3,9 @@ Provides diagnosis and repair of email server configuration issues """ -from . import ldap from . import domain +from . import home +from . import ldap from . import spam -__all__ = ['ldap', 'domain', 'spam'] +__all__ = ['domain', 'home', 'ldap', 'spam'] diff --git a/plinth/modules/email_server/audit/home.py b/plinth/modules/email_server/audit/home.py new file mode 100644 index 000000000..dc14a61c4 --- /dev/null +++ b/plinth/modules/email_server/audit/home.py @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: AGPL-3.0-or-later + +import logging +import os +import pwd +import subprocess + +from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +from plinth.actions import superuser_run +from plinth.errors import ActionError + +logger = logging.getLogger(__name__) + + +def exists_nam(username): + """Returns True if the user's home directory exists""" + try: + passwd = pwd.getpwnam(username) + except KeyError as e: + raise ValidationError(_('User does not exist')) from e + return _exists(passwd) + + +def exists_uid(uid_number): + """Returns True if the user's home directory exists""" + try: + passwd = pwd.getpwuid(uid_number) + except KeyError as e: + raise ValidationError(_('User does not exist')) from e + return _exists(passwd) + + +def _exists(passwd): + return os.path.exists(passwd.pw_dir) + + +def put_nam(username): + """Create a home directory for the user (identified by username)""" + _put('nam', username) + + +def put_uid(uid_number): + """Create a home directory for the user (identified by UID)""" + _put('uid', str(uid_number)) + + +def _put(arg_type, user_info): + try: + args = ['-i', 'home', 'mk', arg_type, user_info] + superuser_run('email_server', args) + except ActionError as e: + raise RuntimeError('Action script failure') from e + + +def action_mk(arg_type, user_info): + if arg_type == 'nam': + passwd = pwd.getpwnam(user_info) + elif arg_type == 'uid': + passwd = pwd.getpwuid(int(user_info)) + else: + raise ValueError('Unknown arg_type') + + args = ['sudo', '-n', '--user=#' + str(passwd.pw_uid)] + args.extend(['/bin/sh', '-c', 'mkdir -p ~']) + completed = subprocess.run(args, capture_output=True) + if completed.returncode != 0: + logger.critical('Subprocess returned %d', completed.returncode) + logger.critical('Stdout: %r', completed.stdout) + logger.critical('Stderr: %r', completed.stderr) + raise OSError('Could not create home directory') diff --git a/plinth/modules/email_server/templates/alias.html b/plinth/modules/email_server/templates/alias.html index cab40ab5c..1980b66f6 100644 --- a/plinth/modules/email_server/templates/alias.html +++ b/plinth/modules/email_server/templates/alias.html @@ -1,24 +1,12 @@ {# SPDX-License-Identifier: AGPL-3.0-or-later #} -{% extends "app.html" %} +{% extends "form_base.html" %} {% load bootstrap %} {% load i18n %} -{% block configuration %} +{% block content %} - {{ tabs|safe }} -
- {% trans "There was a problem with your request. Please try again." %} -
- {% for message in error %} -{{ message }}
- {% endfor %} -{% trans "You have no email aliases." %}
diff --git a/plinth/modules/email_server/templates/email_server.html b/plinth/modules/email_server/templates/email_server.html index 89557bdb5..9f0a3125d 100644 --- a/plinth/modules/email_server/templates/email_server.html +++ b/plinth/modules/email_server/templates/email_server.html @@ -3,8 +3,12 @@ {% load i18n %} -{% block configuration %} +{% block content %} {{ tabs|safe }} + {{ block.super }} +{% endblock %} + +{% block extra_content %}
{% trans "Visit Rspamd administration interface" %}
diff --git a/plinth/modules/email_server/templates/form_base.html b/plinth/modules/email_server/templates/form_base.html
new file mode 100644
index 000000000..390c0936b
--- /dev/null
+++ b/plinth/modules/email_server/templates/form_base.html
@@ -0,0 +1,19 @@
+{# SPDX-License-Identifier: AGPL-3.0-or-later #}
+{% extends "base.html" %}
+
+{% load i18n %}
+
+{% block content %}
+ {{ tabs|safe }}
+ {{ block.super }}
+ {% if error %}
+
+ {% trans "There was a problem with your request. Please try again." %}
+ {{ message }}
+ Roundcube login
+