email_server: Setup /var/mail, drop home setup view

Creating home directories is no longer necessary. We store all mail in /var/mail
and don't allow use of direct access to mail folder.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2021-10-25 21:45:49 -07:00 committed by James Valleroy
parent 88e372b8f8
commit 8d7bac70c9
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
6 changed files with 15 additions and 120 deletions

View File

@ -3,7 +3,6 @@
import logging import logging
from django.urls import reverse_lazy
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
import plinth.app import plinth.app
@ -112,13 +111,6 @@ class EmailServerApp(plinth.app.App):
parent_url_name='apps') parent_url_name='apps')
self.add(menu_item) self.add(menu_item)
shortcut = plinth.frontpage.Shortcut(
'shortcut_' + self.app_id, name=info.name,
short_description=info.short_description, icon='roundcube',
url=reverse_lazy('email_server:my_mail'), clients=manifest.clients,
login_required=True)
self.add(shortcut)
def _add_daemons(self): def _add_daemons(self):
for srvname in managed_services: for srvname in managed_services:
# Construct `listen_ports` parameter for the daemon # Construct `listen_ports` parameter for the daemon
@ -170,6 +162,7 @@ def setup(helper, old_version=None):
helper.install(packages_bloat, skip_recommends=True) helper.install(packages_bloat, skip_recommends=True)
# Setup # Setup
helper.call('post', audit.home.repair)
helper.call('post', audit.domain.repair) helper.call('post', audit.domain.repair)
helper.call('post', audit.ldap.repair) helper.call('post', audit.ldap.repair)
helper.call('post', audit.spam.repair) helper.call('post', audit.spam.repair)

View File

@ -1,70 +1,22 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
"""Privileged actions to setup users' dovecot mail home directory."""
import logging
import os
import pwd
import subprocess import subprocess
from django.core.exceptions import ValidationError from plinth import actions
from django.utils.translation import gettext_lazy as _
from plinth.actions import superuser_run
from plinth.errors import ActionError
from plinth.modules.email_server import interproc
logger = logging.getLogger(__name__)
def exists_nam(username): def repair():
"""Returns True if the user's home directory exists""" """Set correct permissions on /var/mail/ directory.
try:
passwd = pwd.getpwnam(username) For each user, /var/mail/<user> is the 'dovecot mail home' for that user.
except KeyError as e: Dovecot creates new directories with the same permissions as the parent
raise ValidationError(_('User does not exist')) from e directory. Ensure that 'others' can access /var/mail/.
return _exists(passwd)
"""
actions.superuser_run('email_server', ['home', 'set_up'])
def exists_uid(uid_number): def action_set_up():
"""Returns True if the user's home directory exists""" """Run chmod on /var/mail to remove all permissions for 'others'."""
try: subprocess.run(['chmod', 'o-rwx', '/var/mail'], check=True)
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:
superuser_run('email_server', ['home', 'mk', arg_type, user_info])
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, check=False)
if completed.returncode != 0:
interproc.log_subprocess(completed)
raise OSError('Could not create home directory')

View File

@ -19,10 +19,6 @@
{% trans "Manage Spam" %} {% trans "Manage Spam" %}
<span class="fa fa-external-link"></span> <span class="fa fa-external-link"></span>
</a> </a>
<a class="btn btn-default" role="button"
href="{% url 'email_server:my_mail' %}">
{% trans "Setup My Home" %}
</a>
<a class="btn btn-default" role="button" <a class="btn btn-default" role="button"
href="{% url 'email_server:aliases' %}"> href="{% url 'email_server:aliases' %}">
{% trans "Manage Aliases" %} {% trans "Manage Aliases" %}

View File

@ -1,30 +0,0 @@
{% extends "base.html" %}
{% comment %}
# SPDX-License-Identifier: AGPL-3.0-or-later
{% endcomment %}
{% load i18n %}
{% block content %}
<h2>Setup My Home</h2>
{% if not has_homedir %}
<p>
{% trans "You do not have a home directory." %}
<span>
{% trans "Create one to begin receiving emails." %}
</span>
</p>
<form action="{{ request.path }}" method="post">
{% csrf_token %}
<button class="btn btn-primary" type="submit" name="btn_mkhome">
{% trans "Create home directory" %}
</button>
</form>
{% else %}
<p>{% trans "Your home directory is ready to receive emails." %}</p>
{% endif %}
{% endblock %}

View File

@ -10,8 +10,6 @@ urlpatterns = [
path('apps/email_server/', views.EmailServerView.as_view(), name='index'), path('apps/email_server/', views.EmailServerView.as_view(), name='index'),
path('apps/email_server/domains', views.DomainsView.as_view(), path('apps/email_server/domains', views.DomainsView.as_view(),
name='domains'), name='domains'),
path('apps/email_server/my_mail',
non_admin_view(views.MyMailView.as_view()), name='my_mail'),
path('apps/email_server/my_aliases', path('apps/email_server/my_aliases',
non_admin_view(views.AliasView.as_view()), name='aliases'), non_admin_view(views.AliasView.as_view()), name='aliases'),
path('apps/email_server/config.xml', public(views.XmlView.as_view())), path('apps/email_server/config.xml', public(views.XmlView.as_view())),

View File

@ -99,20 +99,6 @@ class EmailServerView(ExceptionsMixin, AppView):
plinth.actions.superuser_run('service', ['reload', service]) plinth.actions.superuser_run('service', ['reload', service])
class MyMailView(TemplateView):
template_name = 'my_mail.html'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
nam = self.request.user.username
context['has_homedir'] = audit.home.exists_nam(nam)
return context
def post(self, request):
audit.home.put_nam(request.user.username)
return self.render_to_response(self.get_context_data())
class AliasView(FormView): class AliasView(FormView):
"""View to create, list, enable, disable and delete aliases. """View to create, list, enable, disable and delete aliases.