From a74ba50611fec28ef6b70994cf863061f4d19262 Mon Sep 17 00:00:00 2001 From: Sofia Papagiannaki Date: Tue, 10 Apr 2012 12:15:40 +0300 Subject: [PATCH] Send sharing notifications. Fixes #2295 --- snf-pithos-app/README | 4 ++++ snf-pithos-app/pithos/api/dispatch.py | 24 ++++++++++++++++++++ .../pithos/backends/lib/sqlalchemy/permissions.py | 17 ++++++++++++++ .../pithos/backends/lib/sqlite/permissions.py | 17 ++++++++++++++ snf-pithos-backend/pithos/backends/modular.py | 9 +++++++- 5 files changed, 70 insertions(+), 1 deletion(-) diff --git a/snf-pithos-app/README b/snf-pithos-app/README index 42d3a50..3f6bbd0 100644 --- a/snf-pithos-app/README +++ b/snf-pithos-app/README @@ -47,6 +47,10 @@ To update checksums asynchronously, enable the queue, install snf-pithos-tools a pithos-dispatcher --exchange=pithos --key=pithos.object --callback=pithos.api.dispatch.update_md5 +To send sharing notifications:: + + pithos-dispatcher --exchange=pithos --key=pithos.sharing --callback=pithos.api.dispatch.send_sharing_notification + Administrator functions ----------------------- diff --git a/snf-pithos-app/pithos/api/dispatch.py b/snf-pithos-app/pithos/api/dispatch.py index 09761da..d4c2561 100644 --- a/snf-pithos-app/pithos/api/dispatch.py +++ b/snf-pithos-app/pithos/api/dispatch.py @@ -5,6 +5,11 @@ from pithos.api.settings import (BACKEND_DB_MODULE, BACKEND_DB_CONNECTION, from pithos.backends import connect_backend from pithos.api.util import hashmap_md5 +from django.core.mail import send_mail +from django.utils.translation import ugettext as _ + +from astakos.im.settings import DEFAULT_FROM_EMAIL + def update_md5(m): if m['resource'] != 'object' or m['details']['action'] != 'object update': return @@ -33,3 +38,22 @@ def update_md5(m): print 'WARNING: Can not update checksum for path "%s" (%s)' % (path, e) backend.close() + +def send_sharing_notification(m): + if m['resource'] != 'sharing': + return + + members = m['details']['members'] + user = m['details']['user'] + path = m['value'] + account, container, name = path.split('/', 2) + + subject = 'Invitation to a Pithos+ shared object' + from_email = DEFAULT_FROM_EMAIL + recipient_list = members + message = 'User %s has invited you to a Pithos+ shared object. You can view it under "Shared to me" at "%s".' %(user, path) + try: + send_mail(subject, message, from_email, recipient_list) + print 'INFO: Sharing notification sent for path "%s" to %s' % (path, ','.join(recipient_list)) + except (SMTPException, socket.error) as e: + print 'WARNING: Can not update send email for sharing "%s" (%s)' % (path, e) diff --git a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py index 2e03c95..af902f8 100644 --- a/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py +++ b/snf-pithos-backend/pithos/backends/lib/sqlalchemy/permissions.py @@ -92,6 +92,23 @@ class Permissions(XFeatures, Groups, Public): del(permissions[WRITE]) return permissions + def access_members(self, path): + feature = self.xfeature_get(path) + if not feature: + return [] + permissions = self.feature_dict(feature) + members = set() + members.update(permissions.get(READ, [])) + members.update(permissions.get(WRITE, [])) + for m in set(members): + parts = m.split(':', 1) + if len(parts) != 2: + continue + user, group = parts + members.remove(m) + members.update(self.group_members(user, group)) + return list(members) + def access_clear(self, path): """Revoke access to path (both permissions and public).""" diff --git a/snf-pithos-backend/pithos/backends/lib/sqlite/permissions.py b/snf-pithos-backend/pithos/backends/lib/sqlite/permissions.py index 476aaf2..6d5d13c 100644 --- a/snf-pithos-backend/pithos/backends/lib/sqlite/permissions.py +++ b/snf-pithos-backend/pithos/backends/lib/sqlite/permissions.py @@ -89,6 +89,23 @@ class Permissions(XFeatures, Groups, Public): del(permissions[WRITE]) return permissions + def access_members(self, path): + feature = self.xfeature_get(path) + if not feature: + return [] + permissions = self.feature_dict(feature) + members = set() + members.update(permissions.get(READ, [])) + members.update(permissions.get(WRITE, [])) + for m in set(members): + parts = m.split(':', 1) + if len(parts) != 2: + continue + user, group = parts + members.remove(m) + members.update(self.group_members(user, group)) + return members + def access_clear(self, path): """Revoke access to path (both permissions and public).""" diff --git a/snf-pithos-backend/pithos/backends/modular.py b/snf-pithos-backend/pithos/backends/modular.py index 0dfd580..1153f23 100644 --- a/snf-pithos-backend/pithos/backends/modular.py +++ b/snf-pithos-backend/pithos/backends/modular.py @@ -104,9 +104,9 @@ def backend_method(func=None, autocommit=1): try: self.messages = [] ret = func(self, *args, **kw) - self.wrapper.commit() for m in self.messages: self.queue.send(*m) + self.wrapper.commit() return ret except: self.wrapper.rollback() @@ -603,6 +603,7 @@ class ModularBackend(BaseBackend): path = self._lookup_object(account, container, name)[0] self._check_permissions(path, permissions) self.permissions.access_set(path, permissions) + self._report_sharing_change(user, account, path, {'members':self.permissions.access_members(path)}) @backend_method def get_object_public(self, user, account, container, name): @@ -671,6 +672,7 @@ class ModularBackend(BaseBackend): if permissions is not None: self.permissions.access_set(path, permissions) + self._report_sharing_change(user, account, path, {'members':self.permissions.access_members(path)}) self._report_object_change(user, account, path, details={'version': dest_version_id, 'action': 'object update'}) return dest_version_id @@ -1018,6 +1020,11 @@ class ModularBackend(BaseBackend): details.update({'user': user}) self.messages.append((QUEUE_MESSAGE_KEY_PREFIX % ('object',), account, QUEUE_INSTANCE_ID, 'object', path, details)) + def _report_sharing_change(self, user, account, path, details={}): + logger.debug("_report_permissions_change: %s %s %s %s", user, account, path, details) + details.update({'user': user}) + self.messages.append((QUEUE_MESSAGE_KEY_PREFIX % ('sharing',), account, QUEUE_INSTANCE_ID, 'sharing', path, details)) + # Policy functions. def _check_policy(self, policy): -- 1.7.10.4