You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2015/04/02 23:24:51 UTC

[1/3] allura git commit: [#7850] Ability to close discussion on a ticket.

Repository: allura
Updated Branches:
  refs/heads/master 80736ccab -> d503b14a1


[#7850] Ability to close discussion on a ticket.


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/f42961eb
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/f42961eb
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/f42961eb

Branch: refs/heads/master
Commit: f42961eb2d54c1daaa0e4710fe32090adc65e25f
Parents: 80736cc
Author: Heith Seewald <hs...@slashdotmedia.com>
Authored: Wed Apr 1 13:37:36 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Apr 2 17:24:36 2015 -0400

----------------------------------------------------------------------
 ForgeTracker/forgetracker/model/ticket.py       | 38 ++++++++++---
 .../templates/tracker/search_help.html          |  2 +
 .../forgetracker/templates/tracker/ticket.html  |  3 ++
 .../templates/tracker_widgets/ticket_form.html  |  9 +++-
 .../forgetracker/tests/functional/test_root.py  | 57 ++++++++++++++++++++
 ForgeTracker/forgetracker/tracker_main.py       | 22 +++++---
 .../forgetracker/widgets/ticket_form.py         |  3 ++
 7 files changed, 120 insertions(+), 14 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 8218ec7..06626a1 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -62,7 +62,7 @@ from allura.model import (
 )
 from allura.model.timeline import ActivityObject
 from allura.model.notification import MailFooter
-from allura.model.types import MarkdownCache
+from allura.model.types import MarkdownCache, EVERYONE
 
 from allura.lib import security
 from allura.lib.search import search_artifact, SearchError
@@ -360,6 +360,10 @@ class Globals(MappedClass):
         if private:
             values['private'] = asbool(private)
 
+        discussion_disabled = post_data.get('discussion_disabled')
+        if discussion_disabled:
+            values['disabled_discussion'] = asbool(discussion_disabled)
+
         custom_values = {}
         custom_fields = {}
         for cf in self.custom_fields or []:
@@ -384,16 +388,17 @@ class Globals(MappedClass):
                             get_label(k),
                             new_user.display_name,
                             old_user.display_name)
-                elif k == 'private':
-                    def private_text(val):
+                elif k == 'private' or k == 'discussion_disabled':
+                    def _text(val):
                         if val:
                             return 'Yes'
                         else:
                             return 'No'
+
                     message += get_change_text(
                         get_label(k),
-                        private_text(v),
-                        private_text(getattr(ticket, k)))
+                        _text(v),
+                        _text(getattr(ticket, k)))
                 else:
                     message += get_change_text(
                         get_label(k),
@@ -681,6 +686,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             text=self.description,
             snippet_s=self.summary,
             private_b=self.private,
+            discussion_disabled_b=self.discussion_disabled,
             votes_up_i=self.votes_up,
             votes_down_i=self.votes_down,
             votes_total_i=(self.votes_up - self.votes_down),
@@ -827,7 +833,26 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
             self.acl = []
     private = property(_get_private, _set_private)
 
-    def commit(self):
+    def _set_discussion_disabled(self, is_disabled):
+        """ Sets a ticket's discussion thread ACL to control a users ability to post.
+
+        :param is_disabled: If True, an explicit deny will be created on the discussion thread ACL.
+        """
+        if is_disabled:
+            _deny_post = lambda role, perms: [ACE.deny(role, perm) for perm in perms]
+            self.discussion_thread.acl = _deny_post(EVERYONE, ('post', 'unmoderated_post'))
+        else:
+            self.discussion_thread.acl = []
+
+    def _get_discussion_disabled(self):
+        """ Checks the discussion thread ACL to determine if users are allowed to post."""
+        thread = Thread.query.get(ref_id=self.index_id())
+        if thread:
+            return bool(thread.acl)
+        return False
+    discussion_disabled = property(_get_discussion_disabled, _set_discussion_disabled)
+
+    def commit(self, **kwargs):
         VersionedArtifact.commit(self)
         monitoring_email = self.app.config.options.get('TicketMonitoringEmail')
         if self.version > 1:
@@ -1093,6 +1118,7 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
                         self.assigned_to_id) or None,
                     status=self.status,
                     private=self.private,
+                    discussion_disabled=self.discussion_disabled,
                     attachments=[dict(bytes=attach.length,
                                       url=h.absurl(
                                           attach.url(

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/templates/tracker/search_help.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/search_help.html b/ForgeTracker/forgetracker/templates/tracker/search_help.html
index 8ec03bb..6f6bd28 100644
--- a/ForgeTracker/forgetracker/templates/tracker/search_help.html
+++ b/ForgeTracker/forgetracker/templates/tracker/search_help.html
@@ -45,6 +45,7 @@
     <li>Status of the ticket - status</li>
     <li>Title of the ticket - summary</li>
     <li>Private ticket - private</li>
+    <li>Discussion Disabled ticket - discussion_disabled</li>
     <li>Votes up/down of the ticket - votes_up/votes_down (if enabled in tool options)</li>
     <li>Votes total of the ticket - votes_total</li>
     <li>Imported legacy id - import_id</li>
@@ -90,6 +91,7 @@
     <li>Status of the ticket - status_s</li>
     <li>Title of the ticket - snippet_s</li>
     <li>Private ticket - private_b</li>
+    <li>Discussion disabled ticket - discussion_disabled_b</li>
     {% if c.app.globals.custom_fields %}
     <li>Custom fields:
         <ul>

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/templates/tracker/ticket.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/ticket.html b/ForgeTracker/forgetracker/templates/tracker/ticket.html
index 2d3dd30..27331c8 100644
--- a/ForgeTracker/forgetracker/templates/tracker/ticket.html
+++ b/ForgeTracker/forgetracker/templates/tracker/ticket.html
@@ -136,6 +136,9 @@
     <div class="grid-4">
       <label class="simple">Private:</label>
       {{'Yes' if ticket.private else 'No'}}
+        {% if ticket.discussion_disabled %}
+            <label class="simple"><span class="closed">Discussion Disabled</span></label>
+        {% endif %}
     </div>
   </div>
 </div>

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/templates/tracker_widgets/ticket_form.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker_widgets/ticket_form.html b/ForgeTracker/forgetracker/templates/tracker_widgets/ticket_form.html
index 63a448d..25f82a1 100644
--- a/ForgeTracker/forgetracker/templates/tracker_widgets/ticket_form.html
+++ b/ForgeTracker/forgetracker/templates/tracker_widgets/ticket_form.html
@@ -51,8 +51,13 @@
     <label class="cr">Labels:</label>
     {{widget.display_field_by_name('labels')|safe}}
   </div>
-  <div class="grid-6">
-    {{widget.display_field_by_name('private')}}
+    <div class="grid-6">
+        {{widget.display_field_by_name('private')}}
+        {% if h.has_access(ticket, 'edit') %}
+        {# Only users with the ability to edit will be able to see the Discussion Disable option.
+            This also serves to hide the checkbox when creating new tickets #}
+            <div>{{widget.display_field_by_name('discussion_disabled')}}</div>
+        {% endif %}
   </div>
   <div style="clear:both">&nbsp;</div>
   <div class="grid-6">

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index b2c5c11..4a2e598 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -625,6 +625,63 @@ class TestFunctionalController(TrackerTestController):
         response = self.app.get('/bugs/1/')
         assert_true('<li><strong>private</strong>: No --&gt; Yes</li>' in response)
 
+    def test_discussion_disabled_ticket(self):
+        response = self.new_ticket(summary='test discussion disabled ticket').follow()
+        # New tickets will not show discussion disabled
+        assert_not_in('<span class="closed">Discussion Disabled</span>', response)
+
+        ticket_params = {
+            'ticket_form.summary': 'test discussion disabled ticket',
+            'ticket_form.description': '',
+            'ticket_form.status': 'open',
+            'ticket_form._milestone': '1.0',
+            'ticket_form.assigned_to': '',
+            'ticket_form.labels': '',
+            'ticket_form.comment': 'no more comments allowed',
+            'ticket_form.discussion_disabled': 'on',
+        }
+
+        # Disable Discussion
+        response = self.app.post('/bugs/1/update_ticket_from_widget', ticket_params).follow()
+        assert_in('<li><strong>discussion</strong>: enabled --&gt; disabled</li>', response)
+        assert_in('<span class="closed">Discussion Disabled</span>', response)
+        assert_in('edit_post_form reply', response)  # Make sure admin can still comment
+
+        # Unauthorized user cannot comment or even see form fields
+        env = dict(username='*anonymous')
+        r = self.app.get('/p/test/bugs/1', extra_environ=env)
+        assert_not_in('edit_post_form reply', r)
+
+        env = dict(username='test-admin')
+        r = self.app.get('/p/test/bugs/1', extra_environ=env)
+
+        # Test re-enabling discussions
+        ticket_params['ticket_form.discussion_disabled'] = 'off'
+        response = self.app.post('/bugs/1/update_ticket_from_widget', ticket_params).follow()
+        assert_in('<li><strong>discussion</strong>: disabled --&gt; enabled</li>', response)
+        assert_not_in('<span class="closed">Discussion Disabled</span>', response)
+
+        # Test solr search
+        M.MonQTask.run_ready()
+        ThreadLocalORMSession.flush_all()
+        # At this point, there is one ticket and it has discussion_disabled set to False
+        r = self.app.get('/bugs/search/?q=discussion_disabled_b:False')
+        assert_in('1 results', r)
+        assert_in('test discussion disabled ticket', r)
+
+        # Set discussion_disabled to True and search again
+        ticket_params['ticket_form.discussion_disabled'] = 'on'
+        self.app.post('/bugs/1/update_ticket_from_widget', ticket_params)
+        M.MonQTask.run_ready()
+        ThreadLocalORMSession.flush_all()
+        r = self.app.get('/bugs/search/?q=discussion_disabled_b:True')
+        assert_in('1 results', r)
+        assert_in('test discussion disabled ticket', r)
+
+        # Make sure there are no other tickets or false positives for good measure.
+        r = self.app.get('/bugs/search/?q=discussion_disabled_b:False')
+        assert_in('0 results', r)
+
     @td.with_tool('test', 'Tickets', 'doc-bugs')
     def test_two_trackers(self):
         summary = 'test two trackers'

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index aedf6ff..b846f42 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -127,6 +127,8 @@ def get_label(name):
         return 'Owner'
     if name == 'private':
         return 'Private'
+    if name == 'discussion_disabled':
+        return 'Discussion Disabled'
 
 
 def get_change_text(name, new_value, old_value):
@@ -371,9 +373,9 @@ class ForgeTrackerApp(Application):
         });""" % {'app_url': c.app.url}
 
     def has_custom_field(self, field):
-        '''Checks if given custom field is defined. (Custom field names
-        must start with '_'.)
-        '''
+        """Checks if given custom field is defined.
+        (Custom field names must start with '_'.)
+        """
         for f in self.globals.custom_fields:
             if f['name'] == field:
                 return True
@@ -424,7 +426,7 @@ class ForgeTrackerApp(Application):
                custom_fields=dict())
 
     def uninstall(self, project):
-        "Remove all the tool's artifacts from the database"
+        """Remove all the tool's artifacts from the database"""
         app_config_id = {'app_config_id': c.app.config._id}
         TM.TicketAttachment.query.remove(app_config_id)
         TM.Ticket.query.remove(app_config_id)
@@ -834,12 +836,12 @@ class RootController(BaseController, FeedController):
 
     @expose('jinja:allura:templates/markdown_syntax.html')
     def markdown_syntax(self):
-        'Static page explaining markdown.'
+        """Static page explaining markdown."""
         return dict()
 
     @expose('jinja:allura:templates/markdown_syntax_dialog.html')
     def markdown_syntax_dialog(self):
-        'Static page explaining markdown.'
+        """Static page explaining markdown."""
         return dict()
 
     @expose()
@@ -1408,10 +1410,18 @@ class TicketController(BaseController, FeedController):
             else:
                 self.ticket.assigned_to_id = None
             changes['assigned_to'] = self.ticket.assigned_to
+
+        # Register a key with the changelog -->
+        # Update the ticket property from the post_data -->
+        # Set the value of the changelog key again in case it has changed.
         changes['private'] = 'Yes' if self.ticket.private else 'No'
         self.ticket.private = post_data.get('private', False)
         changes['private'] = 'Yes' if self.ticket.private else 'No'
 
+        changes['discussion'] = 'disabled' if self.ticket.discussion_disabled else 'enabled'
+        self.ticket.discussion_disabled = post_data.get('discussion_disabled', False)
+        changes['discussion'] = 'disabled' if self.ticket.discussion_disabled else 'enabled'
+
         if 'attachment' in post_data:
             attachment = post_data['attachment']
             self.ticket.add_multiple_attachments(attachment)

http://git-wip-us.apache.org/repos/asf/allura/blob/f42961eb/ForgeTracker/forgetracker/widgets/ticket_form.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/widgets/ticket_form.py b/ForgeTracker/forgetracker/widgets/ticket_form.py
index d107aeb..476d9b3 100644
--- a/ForgeTracker/forgetracker/widgets/ticket_form.py
+++ b/ForgeTracker/forgetracker/widgets/ticket_form.py
@@ -117,6 +117,9 @@ class GenericTicketForm(ew.SimpleForm):
             ew.Checkbox(name='private', label='Mark as Private',
                         validator=v.AnonymousValidator(),
                         attrs={'class': 'unlabeled'}),
+            ew.Checkbox(name='discussion_disabled', label='Discussion Disabled',
+                        validator=fev.StringBool(),
+                        attrs={'class': 'unlabeled'}),
             ew.InputField(name='attachment', label='Attachment', field_type='file', attrs={
                           'multiple': 'True'}, validator=fev.FieldStorageUploadConverter(if_missing=None)),
             ffw.MarkdownEdit(name='comment', label='Comment',


[3/3] allura git commit: [#7850] more readable ACL setup

Posted by br...@apache.org.
[#7850] more readable ACL setup


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/d503b14a
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/d503b14a
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/d503b14a

Branch: refs/heads/master
Commit: d503b14a1527386dba55cc95c2b8b20d94beb780
Parents: ba7374b
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Apr 2 17:24:20 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Apr 2 17:24:37 2015 -0400

----------------------------------------------------------------------
 ForgeTracker/forgetracker/model/ticket.py | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/d503b14a/ForgeTracker/forgetracker/model/ticket.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/model/ticket.py b/ForgeTracker/forgetracker/model/ticket.py
index 06626a1..e26f57a 100644
--- a/ForgeTracker/forgetracker/model/ticket.py
+++ b/ForgeTracker/forgetracker/model/ticket.py
@@ -820,8 +820,8 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         if bool_flag:
             role_developer = ProjectRole.by_name('Developer')
             role_creator = ProjectRole.by_user(self.reported_by, upsert=True)
-            _allow_all = lambda role, perms: [
-                ACE.allow(role._id, perm) for perm in perms]
+            def _allow_all(role, perms):
+                return [ACE.allow(role._id, perm) for perm in perms]
             # maintain existing access for developers and the ticket creator,
             # but revoke all access for everyone else
             acl = _allow_all(role_developer, security.all_allowed(self, role_developer))
@@ -839,8 +839,8 @@ class Ticket(VersionedArtifact, ActivityObject, VotableArtifact):
         :param is_disabled: If True, an explicit deny will be created on the discussion thread ACL.
         """
         if is_disabled:
-            _deny_post = lambda role, perms: [ACE.deny(role, perm) for perm in perms]
-            self.discussion_thread.acl = _deny_post(EVERYONE, ('post', 'unmoderated_post'))
+            self.discussion_thread.acl = [ACE.deny(EVERYONE, 'post'),
+                                          ACE.deny(EVERYONE, 'unmoderated_post')]
         else:
             self.discussion_thread.acl = []
 


[2/3] allura git commit: [#7850] clean up tests

Posted by br...@apache.org.
[#7850] clean up tests


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/ba7374be
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/ba7374be
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/ba7374be

Branch: refs/heads/master
Commit: ba7374be65f2a7bd4738e00c058aa76fed3c3649
Parents: f42961e
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Apr 2 17:24:08 2015 -0400
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Thu Apr 2 17:24:37 2015 -0400

----------------------------------------------------------------------
 ForgeTracker/forgetracker/tests/functional/test_rest.py | 1 +
 ForgeTracker/forgetracker/tests/functional/test_root.py | 3 ---
 2 files changed, 1 insertion(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/ba7374be/ForgeTracker/forgetracker/tests/functional/test_rest.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_rest.py b/ForgeTracker/forgetracker/tests/functional/test_rest.py
index 7c650be..aa728e1 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_rest.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_rest.py
@@ -96,6 +96,7 @@ class TestRestUpdateTicket(TestTrackerApiBase):
                         'reported_by', 'reported_by_id', '_id', 'votes_up', 'votes_down'):
             del args[bad_key]
         args['private'] = str(args['private'])
+        args['discussion_disabled'] = str(args['discussion_disabled'])
         ticket_view = self.api_post(
             '/rest/p/test/bugs/1/save', wrap_args='ticket_form', params=h.encode_keys(args))
         assert ticket_view.status_int == 200, ticket_view.showbrowser()

http://git-wip-us.apache.org/repos/asf/allura/blob/ba7374be/ForgeTracker/forgetracker/tests/functional/test_root.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tests/functional/test_root.py b/ForgeTracker/forgetracker/tests/functional/test_root.py
index 4a2e598..0e92b1f 100644
--- a/ForgeTracker/forgetracker/tests/functional/test_root.py
+++ b/ForgeTracker/forgetracker/tests/functional/test_root.py
@@ -652,9 +652,6 @@ class TestFunctionalController(TrackerTestController):
         r = self.app.get('/p/test/bugs/1', extra_environ=env)
         assert_not_in('edit_post_form reply', r)
 
-        env = dict(username='test-admin')
-        r = self.app.get('/p/test/bugs/1', extra_environ=env)
-
         # Test re-enabling discussions
         ticket_params['ticket_form.discussion_disabled'] = 'off'
         response = self.app.post('/bugs/1/update_ticket_from_widget', ticket_params).follow()