diff --git a/docs/changelog.rst b/docs/changelog.rst index 3f1b589..8d24e5c 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -1,6 +1,15 @@ Changelog ========= +* :release:`0.2.0 <2014-12-27>` +* :support:`-` restrict permissions of mailbox base directories to be read only +* :feature:`-` add new mailbox handling tasks + :py:func:`osusers.tasks.create_file_mailbox` and + :py:func:`osusers.tasks.delete_file_mailbox` +* :support:`-` move celery routers into gvacommon that is in it's own + repository to be used by others (gva, gvaldap) +* :bug:`- major` sftp directories are now owned by root instead of user + * :release:`0.1.0 <2014-12-26>` * :support:`-` configure celery task serialization, add routing for ldap tasks diff --git a/docs/conf.py b/docs/conf.py index 4b944cd..ee786a2 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -62,9 +62,9 @@ copyright = u'2014, Jan Dittberner' # built documents. # # The short X.Y version. -version = '0.1.0' +version = '0.2.0' # The full version, including alpha/beta/rc tags. -release = '0.1.0' +release = '0.2.0' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/gvafile/gvacommon/.gitignore b/gvafile/gvacommon/.gitignore new file mode 100644 index 0000000..3bb2efd --- /dev/null +++ b/gvafile/gvacommon/.gitignore @@ -0,0 +1,2 @@ +.*.swp +*.pyc diff --git a/gvafile/gvacommon/__init__.py b/gvafile/gvacommon/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/gvafile/gvacommon/celeryrouters.py b/gvafile/gvacommon/celeryrouters.py new file mode 100644 index 0000000..e468813 --- /dev/null +++ b/gvafile/gvacommon/celeryrouters.py @@ -0,0 +1,24 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + + +class LdapRouter(object): + + def route_for_task(self, task, args=None, kwargs=None): + if 'ldap' in task: + return {'exchange': 'ldap', + 'exchange_type': 'direct', + 'queue': 'ldap'} + return None + + +class FileRouter(object): + + def route_for_task(self, task, args=None, kwargs=None): + if 'file' in task: + return {'exchange': 'file', + 'exchange_type': 'direct', + 'queue': 'file'} + return None + + diff --git a/gvafile/gvafile/settings/base.py b/gvafile/gvafile/settings/base.py index c204589..fc83245 100644 --- a/gvafile/gvafile/settings/base.py +++ b/gvafile/gvafile/settings/base.py @@ -283,8 +283,8 @@ CELERY_RESULT_BACKEND = 'amqp' CELERY_RESULT_PERSISTENT = True CELERY_TASK_RESULT_EXPIRES = None CELERY_ROUTES = ( - 'osusers.tasks.LdapRouter', - 'osusers.tasks.FileRouter', + 'gvacommon.celeryrouters.LdapRouter', + 'gvacommon.celeryrouters.FileRouter', ) CELERY_ACCEPT_CONTENT = ['pickle', 'yaml', 'json'] CELERY_TASK_SERIALIZER = 'json' diff --git a/gvafile/osusers/tasks.py b/gvafile/osusers/tasks.py index ada2e84..4a7105c 100644 --- a/gvafile/osusers/tasks.py +++ b/gvafile/osusers/tasks.py @@ -25,26 +25,6 @@ SETFACL_CMD = '/usr/bin/setfacl' RM_CMD = '/bin/rm' -class LdapRouter(object): - - def route_for_task(self, task, args=None, kwargs=None): - if 'ldap' in task: - return {'exchange': 'ldap', - 'exchange_type': 'direct', - 'queue': 'ldap'} - return None - - -class FileRouter(object): - - def route_for_task(self, task, args=None, kwargs=None): - if 'file' in task: - return {'exchange': 'file', - 'exchange_type': 'direct', - 'queue': 'file'} - return None - - def _build_sftp_directory_name(username): """ Constructs the SFTP directory name for a given username. @@ -76,7 +56,7 @@ def setup_file_sftp_userdir(username): sftp_directory = _build_sftp_directory_name(username) try: subprocess.check_output([ - SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username, + SUDO_CMD, INSTALL_CMD, '-o', 'root', '-g', username, '-m', '0750', '-d', sftp_directory], stderr=subprocess.STDOUT) subprocess.check_output([ SUDO_CMD, SETFACL_CMD, '-m', 'www-data:--x', @@ -131,7 +111,7 @@ def setup_file_mail_userdir(username): try: subprocess.check_output([ SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username, - '-m', '0750', '-d', mail_directory], stderr=subprocess.STDOUT) + '-m', '0500', '-d', mail_directory], stderr=subprocess.STDOUT) except subprocess.CalledProcessError: _logger.exception( 'could not create mail base directory for user %s', username) @@ -163,3 +143,57 @@ def delete_file_mail_userdir(username): raise GVAFileException( "could not remove mail base directory of user %s" % username) return mail_directory + + +@shared_task +def create_file_mailbox(username, mailboxname): + """ + This task creates a new mailbox directory for the given user and mailbox + name. + + :param str username: the user name + :param str mailboxname: the mailbox name + :raises GVAFileException: if the mailbox directory cannot be created + :return: the created mailbox directory name + :rtype: str + + """ + mailbox_directory = os.path.join( + _build_mail_directory_name(username), mailboxname) + try: + subprocess.check_output([ + SUDO_CMD, INSTALL_CMD, '-o', username, '-g', username, + '-m', '0700', '-d', mailbox_directory], stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + _logger.exception( + 'could not create mailbox %s for user %s', mailboxname, username) + raise GVAFileException( + "could not create mailbox %s for user %s" % (mailboxname, username) + ) + return mailbox_directory + + +@shared_task +def delete_file_mailbox(username, mailboxname): + """ + This task deletes the given mailbox of the given user. + + :param str username: the user name + :param str mailboxname: the mailbox name + :raises GVAFileException: if the mailbox directory cannot be deleted + :return: the deleted mailbox directory name + :rtype: str + + """ + mailbox_directory = os.path.join( + _build_mail_directory_name(username), mailboxname) + try: + subprocess.check_output([ + SUDO_CMD, RM_CMD, '-r', '-f', mailbox_directory], + stderr=subprocess.STDOUT) + except subprocess.CalledProcessError: + _logger.exception( + 'could not remove mailbox %s of user %s', mailboxname, username) + raise GVAFileException( + "could not remove mailbox %s of user %s" % (mailboxname, username)) + return mailbox_directory