Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id A7C96200BCF for ; Mon, 5 Dec 2016 17:39:36 +0100 (CET) Received: by cust-asf.ponee.io (Postfix) id A68E1160B31; Mon, 5 Dec 2016 16:39:36 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id D2021160B09 for ; Mon, 5 Dec 2016 17:39:35 +0100 (CET) Received: (qmail 79296 invoked by uid 500); 5 Dec 2016 16:39:35 -0000 Mailing-List: contact commits-help@allura.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@allura.apache.org Delivered-To: mailing list commits@allura.apache.org Received: (qmail 79276 invoked by uid 99); 5 Dec 2016 16:39:35 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 05 Dec 2016 16:39:35 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id E585FE076F; Mon, 5 Dec 2016 16:39:34 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: brondsem@apache.org To: commits@allura.apache.org Date: Mon, 05 Dec 2016 16:39:34 -0000 Message-Id: X-Mailer: ASF-Git Admin Mailer Subject: [1/9] allura git commit: [#7981] don't allow overlapping subscriptions between Forums and its Threads archived-at: Mon, 05 Dec 2016 16:39:36 -0000 Repository: allura Updated Branches: refs/heads/master 23cf3566d -> 3b8240fc2 [#7981] don't allow overlapping subscriptions between Forums and its Threads Project: http://git-wip-us.apache.org/repos/asf/allura/repo Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/dec2ab0b Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/dec2ab0b Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/dec2ab0b Branch: refs/heads/master Commit: dec2ab0baa2fcbf3e7137cac4c4ead385d006c8b Parents: a02c913 Author: Dave Brondsema Authored: Fri Nov 18 17:52:02 2016 -0500 Committer: Dave Brondsema Committed: Mon Dec 5 11:39:20 2016 -0500 ---------------------------------------------------------------------- Allura/allura/controllers/site_admin.py | 7 ++--- Allura/allura/lib/search.py | 31 ++++++++++++++++++++ Allura/allura/model/artifact.py | 2 +- Allura/allura/model/notification.py | 3 +- .../allura/tests/functional/test_site_admin.py | 12 ++++---- .../forgediscussion/controllers/forum.py | 24 ++++++++++++++- requirements.txt | 2 +- 7 files changed, 66 insertions(+), 15 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/controllers/site_admin.py ---------------------------------------------------------------------- diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py index 459362e..a7ece1a 100644 --- a/Allura/allura/controllers/site_admin.py +++ b/Allura/allura/controllers/site_admin.py @@ -272,12 +272,9 @@ class SiteAdminController(object): if match: count = match.hits objects = match.docs - ids = [obj['id'].split('#')[1] for obj in objects] - ids = [bson.ObjectId(_id) for _id in ids if _id != 'None'] - mongo_objects = {} - for obj in model.query.find({'_id': {'$in': ids}}): - mongo_objects[str(obj._id)] = obj + ids = [obj['id'] for obj in objects] + mongo_objects = search.mapped_artifacts_from_index_ids(ids, model) for i in range(len(objects)): obj = objects[i] _id = obj['id'].split('#')[1] http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/lib/search.py ---------------------------------------------------------------------- diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py index 2ee9b82..02afa05 100644 --- a/Allura/allura/lib/search.py +++ b/Allura/allura/lib/search.py @@ -21,6 +21,7 @@ from logging import getLogger from urllib import urlencode from itertools import imap +import bson import markdown import jinja2 from tg import redirect, url @@ -330,3 +331,33 @@ def find_shortlinks(text): md.convert(text) link_index = md.treeprocessors['links'].alinks return [link for link in link_index if link is not None] + + +def artifacts_from_index_ids(index_ids, model, objectid_id=True): + ''' + :param list[str] index_ids: a list of search/subscription/artifact-reference index_id values + :param type model: the Artifact class + :param bool objectid_id: whether the _id values are ObjectIds + :return: instances of the model, for each id given + :rtype: list + ''' + # this could be made more flexible to not require the model passed in + ids = [index_id.split('#')[1] for index_id in index_ids] + if objectid_id: + ids = [bson.ObjectId(_id) for _id in ids if id != 'None'] + return model.query.find({'_id': {'$in': ids}}).all() + + +def mapped_artifacts_from_index_ids(index_ids, model, objectid_id=True): + ''' + :param list[str] index_ids: a list of search/subscription/artifact-reference index_id values + :param type model: the Artifact class + :param bool objectid_id: whether the _id values are ObjectIds + :return: instances of the model, keyed by str(_id) + :rtype: dict + ''' + models = artifacts_from_index_ids(index_ids, model, objectid_id=objectid_id) + map = {} + for m in models: + map[str(m._id)] = m + return map \ No newline at end of file http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/model/artifact.py ---------------------------------------------------------------------- diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py index 39316d2..523a7ad 100644 --- a/Allura/allura/model/artifact.py +++ b/Allura/allura/model/artifact.py @@ -201,7 +201,7 @@ class Artifact(MappedClass, SearchIndexable): from allura.model import Mailbox if user is None: user = c.user - Mailbox.subscribe( + return Mailbox.subscribe( user_id=user._id, project_id=self.app_config.project_id, app_config_id=self.app_config._id, http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/model/notification.py ---------------------------------------------------------------------- diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py index 52ef451..80ff6a6 100644 --- a/Allura/allura/model/notification.py +++ b/Allura/allura/model/notification.py @@ -486,8 +486,9 @@ class Mailbox(MappedClass): # tool for other_mbox in cls.query.find(dict( user_id=user_id, project_id=project_id, app_config_id=app_config_id)): - if other_mbox is not mbox: + if other_mbox != mbox: other_mbox.delete() + return mbox @classmethod def unsubscribe( http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/tests/functional/test_site_admin.py ---------------------------------------------------------------------- diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py index 7889136..c46e2b1 100644 --- a/Allura/allura/tests/functional/test_site_admin.py +++ b/Allura/allura/tests/functional/test_site_admin.py @@ -407,9 +407,9 @@ class TestUsersSearch(TestController): M.User(_id=_id, username='darth') ThreadLocalORMSession().flush_all() - @patch('allura.controllers.site_admin.search') - def test_default_fields(self, search): - search.site_admin_search.return_value = self.TEST_HIT + @patch('allura.controllers.site_admin.search.site_admin_search') + def test_default_fields(self, site_admin_search): + site_admin_search.return_value = self.TEST_HIT r = self.app.get('/nf/admin/search_users?q=fake&f=username') options = [o['value'] for o in r.html.findAll('option')] assert_equal(options, ['username', 'display_name', '__custom__']) @@ -417,9 +417,9 @@ class TestUsersSearch(TestController): assert_equal(ths, ['Username', 'Display name', 'Email', 'Registered', 'Status', 'Details']) - @patch('allura.controllers.site_admin.search') - def test_additional_fields(self, search): - search.site_admin_search.return_value = self.TEST_HIT + @patch('allura.controllers.site_admin.search.site_admin_search') + def test_additional_fields(self, site_admin_search): + site_admin_search.return_value = self.TEST_HIT with h.push_config(config, **{'search.user.additional_search_fields': 'email_addresses, url', 'search.user.additional_display_fields': 'url'}): r = self.app.get('/nf/admin/search_users?q=fake&f=username') http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/ForgeDiscussion/forgediscussion/controllers/forum.py ---------------------------------------------------------------------- diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py index bb0fa33..52b3b7c 100644 --- a/ForgeDiscussion/forgediscussion/controllers/forum.py +++ b/ForgeDiscussion/forgediscussion/controllers/forum.py @@ -16,7 +16,10 @@ # under the License. import logging +import re + import pymongo +from allura.lib.search import mapped_artifacts_from_index_ids from tg import expose, validate, redirect from tg import request @@ -116,7 +119,6 @@ class ForumController(DiscussionController): limit=limit, page=page) - @expose('jinja:forgediscussion:templates/discussionforums/deleted.html') def deleted(self): return dict() @@ -127,8 +129,28 @@ class ForumController(DiscussionController): def subscribe_to_forum(self, subscribe=None, unsubscribe=None, shortname=None, **kw): if subscribe: self.discussion.subscribe(type='direct') + + # unsubscribe from all individual threads that are part of this forum, so you don't have overlapping subscriptions + forumthread_index_prefix = (DM.ForumThread.__module__ + '.' + DM.ForumThread.__name__).replace('.', '/') + '#' + thread_mboxes = M.Mailbox.query.find(dict( + user_id=c.user._id, + project_id=c.project._id, + app_config_id=c.app.config._id, + artifact_index_id=re.compile('^' + re.escape(forumthread_index_prefix)), + )).all() + # get the ForumThread objects from the subscriptions + thread_index_ids = [mbox.artifact_index_id for mbox in thread_mboxes] + threads_by_id = mapped_artifacts_from_index_ids(thread_index_ids, DM.ForumThread, objectid_id=False) + for mbox in thread_mboxes: + thread_id = mbox.artifact_index_id.split('#')[1] + thread = threads_by_id[thread_id] + # only delete if the ForumThread is part of this forum + if thread.discussion_id == self.discussion._id: + mbox.delete() + elif unsubscribe: self.discussion.unsubscribe() + return { 'status': 'ok', 'subscribed': M.Mailbox.subscribed(artifact=self.discussion), http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/requirements.txt ---------------------------------------------------------------------- diff --git a/requirements.txt b/requirements.txt index 30f99f3..1d8dffd 100644 --- a/requirements.txt +++ b/requirements.txt @@ -21,7 +21,7 @@ httplib2==0.7.4 iso8601==0.1.4 Jinja2==2.8 Markdown==2.2.0 -Ming==0.5.4 +Ming==0.5.5 oauth2==1.5.170 # tg2 dep PasteDeploy must specified before TurboGears2, to avoid a version/allow-hosts problem Paste==1.7.5.1