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 2013/05/03 23:57:40 UTC

[10/50] git commit: [#5332] Relax mount point name rules for repos

[#5332] Relax mount point name rules for repos

Signed-off-by: Tim Van Steenburgh <tv...@gmail.com>


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

Branch: refs/heads/db/6007
Commit: ba32ac79881cb1ba74cea0ea279a426c5e416801
Parents: f2c3475
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Thu Apr 25 18:34:31 2013 +0000
Committer: Dave Brondsema <db...@slashdotmedia.com>
Committed: Mon Apr 29 14:44:04 2013 +0000

----------------------------------------------------------------------
 Allura/allura/app.py                               |   30 +++++++++++++--
 Allura/allura/controllers/project.py               |    4 +-
 Allura/allura/controllers/rest.py                  |    2 -
 .../allura/ext/admin/templates/project_tools.html  |   23 +++++++++--
 Allura/allura/lib/helpers.py                       |    3 +-
 Allura/allura/lib/repository.py                    |    1 +
 Allura/allura/model/project.py                     |    2 +-
 Allura/allura/public/nf/js/project_tools.js        |   12 +++++-
 Allura/allura/tests/unit/test_app.py               |   13 ++++++
 9 files changed, 74 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/app.py b/Allura/allura/app.py
index bf874bf..124f084 100644
--- a/Allura/allura/app.py
+++ b/Allura/allura/app.py
@@ -28,7 +28,7 @@ from bson import ObjectId
 from ming.orm import session, state
 from ming.utils import LazyProperty
 
-from allura.lib.helpers import push_config, vardec
+from allura.lib import helpers as h
 from allura.lib.security import require, has_access, require_access
 from allura import model
 from allura.controllers import BaseController
@@ -144,6 +144,10 @@ class Application(object):
     :cvar bool hidden: Default is False, Application is not hidden from the
         list of a project's installed tools.
     :cvar str tool_description: Text description of this Application.
+    :cvar bool relaxed_mount_points: Set to True to relax the default mount point
+        naming restrictions for this Application. Default is False. See
+        :attr:`default mount point naming rules <allura.lib.helpers.re_tool_mount_point>` and
+        :attr:`relaxed mount point naming rules <allura.lib.helpers.re_relaxed_tool_mount_point>`.
     :cvar Controller root: Serves content at
         /<neighborhood>/<project>/<app>/. Default is None - subclasses should
         override.
@@ -154,7 +158,6 @@ class Application(object):
         /<neighborhood>/<project>/<admin>/<app>/. Default is a
         :class:`DefaultAdminController` instance.
     :cvar dict icons: Mapping of icon sizes to application-specific icon paths.
-
     """
 
     __version__ = None
@@ -178,6 +181,7 @@ class Application(object):
     tool_description="This is a tool for Allura forge."
     default_mount_label='Tool Name'
     default_mount_point='tool'
+    relaxed_mount_points=False
     ordinal=0
     hidden = False
     icons={
@@ -203,6 +207,24 @@ class Application(object):
         return self.config.parent_security_context()
 
     @classmethod
+    def validate_mount_point(cls, mount_point):
+        """Check if ``mount_point`` is valid for this Application.
+
+        In general, subclasses should not override this, but rather toggle
+        the strictness of allowed mount point names by toggling
+        :attr:`Application.relaxed_mount_points`.
+
+        :param mount_point: the mount point to validate
+        :type mount_point: str
+        :rtype: A :class:`regex Match object <_sre.SRE_Match>` if the mount
+                point is valid, else None
+
+        """
+        re = (h.re_relaxed_tool_mount_point if cls.relaxed_mount_points
+                else h.re_tool_mount_point)
+        return re.match(mount_point)
+
+    @classmethod
     def status_int(self):
         return self.status_map.index(self.status)
 
@@ -450,7 +472,7 @@ class DefaultAdminController(BaseController):
     @expose()
     @require_post()
     def configure(self, **kw):
-        with push_config(c, app=self.app):
+        with h.push_config(c, app=self.app):
             require_access(self.app, 'configure')
             is_admin = self.app.config.tool_name == 'admin'
             if kw.pop('delete', False):
@@ -481,7 +503,7 @@ class DefaultAdminController(BaseController):
 
     @without_trailing_slash
     @expose()
-    @vardec
+    @h.vardec
     @require_post()
     def update(self, card=None, **kw):
         self.app.config.acl = []

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index 2f59a38..75e7792 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -317,8 +317,6 @@ class ProjectController(object):
     @expose()
     def _lookup(self, name, *remainder):
         name = unquote(name)
-        if not h.re_path_portion.match(name):
-            raise exc.HTTPNotFound, name
         subproject = M.Project.query.get(shortname=c.project.shortname + '/' + name,
                                          neighborhood_id=c.project.neighborhood_id)
         if subproject:
@@ -592,7 +590,7 @@ class NeighborhoodAdminController(object):
 
 
         for tool in validate_tools.keys():
-            if not h.re_tool_mount_point.match(tool):
+            if tool not in g.entry_points['tool']:
                 flash('Anchored tools "%s" is invalid' % anchored_tools,'error')
                 result = False
         if result:

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/controllers/rest.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/rest.py b/Allura/allura/controllers/rest.py
index cf03733..8ae0c70 100644
--- a/Allura/allura/controllers/rest.py
+++ b/Allura/allura/controllers/rest.py
@@ -257,8 +257,6 @@ class ProjectRestController(object):
     def _lookup(self, name, *remainder):
         if not name:
             return self, ()
-        if not h.re_path_portion.match(name):
-            raise exc.HTTPNotFound, name
         subproject = M.Project.query.get(shortname=c.project.shortname + '/' + name,
                                          neighborhood_id=c.project.neighborhood_id,
                                          deleted=False)

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/ext/admin/templates/project_tools.html
----------------------------------------------------------------------
diff --git a/Allura/allura/ext/admin/templates/project_tools.html b/Allura/allura/ext/admin/templates/project_tools.html
index 6516039..dc7646c 100644
--- a/Allura/allura/ext/admin/templates/project_tools.html
+++ b/Allura/allura/ext/admin/templates/project_tools.html
@@ -30,7 +30,7 @@
   <div class="nested-grid-container">
     {% for tool in installable_tools %}
       <span class="tcenter grid-4 installable_tool">
-        <a class="install_trig" data-tool="{{ tool['name'] }}">
+        <a class="install_trig" data-tool="{{ tool['name'] }}" data-relaxed-mount-points="{{ tool.app.relaxed_mount_points and 'true' or 'false' }}">
           <span class="tool_title">{{ tool['app'].tool_label }}{{' (%s)' % tool.app.status if tool.app.status != 'production' else ''}}</span><br />
           <img src="{{ g.theme.app_icon_url(tool['app'], 32) or 'unk.png' }}" alt="">
         </a>
@@ -50,9 +50,24 @@
     <div class="grid-13"><input type="text" name="new.mount_label" class="new_mount_label"></div>
     <label class="grid-13">Mount Point</label>
     <div class="grid-13"><input type="text" name="new.mount_point" class="new_mount_point"></div>
-    <div class="grid-13"><small>* The mount point is the name of the tool as it will appear in a URL.
-      A valid mount point must begin with a letter, contain only letters, numbers, and dashes,
-      and be from 1-63 characters in length.</small></div>
+    <div class="grid-13">
+      <small>
+        * The mount point is the name of the tool as it will appear in a URL.
+        <span class="mount-point-name-rules tool">
+          A valid mount point for this tool must begin with a letter, contain only letters,
+          numbers, and dashes, and be from 1-63 characters in length.
+        </span>
+        <span class="mount-point-name-rules tool-relaxed">
+          A valid mount point for this tool must begin with a letter or number, contain only
+          letters, numbers, dashes, underscores, periods, and plus signs, and be
+          from 1-63 characters in length.
+        </span>
+        <span class="mount-point-name-rules subproject">
+          A valid subproject mount point must begin with a letter, contain only letters,
+          numbers, and dashes, and be from 3-63 characters in length.
+        </span>
+      </small>
+    </div>
     <hr>
     <div class="grid-13">&nbsp;</div>
     <div class="grid-13">

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index ea2b4d2..b118efe 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -53,8 +53,9 @@ from allura.lib import AsciiDammit
 from .security import has_access
 
 re_path_portion_fragment = re.compile(r'[a-z][-a-z0-9]*')
-re_path_portion = re.compile(r'^[a-z][-a-z0-9]{2,}$')
+re_path_portion = re.compile(r'^[a-z][-a-z0-9]{2,62}$')
 re_tool_mount_point = re.compile(r'^[a-z][-a-z0-9]{0,62}$')
+re_relaxed_tool_mount_point = re.compile(r'^[a-z0-9][-a-z0-9_\.\+]{0,62}$')
 re_clean_vardec_key = re.compile(r'''\A
 ( # first part
 \w+# name...

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/lib/repository.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/repository.py b/Allura/allura/lib/repository.py
index 69736b6..3a432ec 100644
--- a/Allura/allura/lib/repository.py
+++ b/Allura/allura/lib/repository.py
@@ -53,6 +53,7 @@ class RepositoryApp(Application):
     tool_label='Repository'
     default_mount_label='Code'
     default_mount_point='code'
+    relaxed_mount_points=True
     ordinal=2
     forkable=False
     default_branch_name=None # master or default or some such

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/model/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/project.py b/Allura/allura/model/project.py
index d207aab..b3f1131 100644
--- a/Allura/allura/model/project.py
+++ b/Allura/allura/model/project.py
@@ -547,7 +547,7 @@ class Project(MappedClass, ActivityNode, ActivityObject):
             for x in range(10):
                 if self.app_instance(mount_point) is None: break
                 mount_point = base_mount_point + '-%d' % x
-        if not h.re_tool_mount_point.match(mount_point):
+        if not App.validate_mount_point(mount_point):
             raise exceptions.ToolError, 'Mount point "%s" is invalid' % mount_point
         # HACK: reserved url components
         if mount_point in ('feed', 'index', 'icon', '_nav.json'):

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/public/nf/js/project_tools.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/project_tools.js b/Allura/allura/public/nf/js/project_tools.js
index 3a5b5d7..b148ba4 100644
--- a/Allura/allura/public/nf/js/project_tools.js
+++ b/Allura/allura/public/nf/js/project_tools.js
@@ -28,20 +28,30 @@
     var new_mount_point = install_form.find('input.new_mount_point');
     var new_mount_label = install_form.find('input.new_mount_label');
     var install_tool_label = $('#install_tool_label');
+    var mount_point_rule_names = $('#install_form .mount-point-rule-names');
     install_popup.append(install_form.show());
     $('a.install_trig').click(function () {
-        var datatool = $(this).attr('data-tool');
+        var datatool = $(this).data('tool');
+        var relaxed_mount_points = $(this).data('relaxed-mount-points');
+        install_form.find('.mount-point-name-rules').hide();
         if (datatool) {
             var tool = defaults[datatool];
             install_tool_label.html(tool.default_label);
             new_ep_name.val(datatool);
             new_mount_point.val(tool.default_mount);
             new_mount_label.val(tool.default_label);
+            if (relaxed_mount_points) {
+              install_form.find('.mount-point-name-rules.tool-relaxed').show();
+            }
+            else {
+              install_form.find('.mount-point-name-rules.tool').show();
+            }
         } else {
             install_tool_label.html("Subproject");
             new_ep_name.val('');
             new_mount_point.val('');
             new_mount_label.val('');
+            install_form.find('.mount-point-name-rules.subproject').show();
         }
     });
     // Edit popup

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/ba32ac79/Allura/allura/tests/unit/test_app.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/unit/test_app.py b/Allura/allura/tests/unit/test_app.py
index 668ac65..8f0c0db 100644
--- a/Allura/allura/tests/unit/test_app.py
+++ b/Allura/allura/tests/unit/test_app.py
@@ -15,6 +15,9 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
+import re
+from unittest import TestCase
+
 from allura.app import Application
 from allura import model
 from allura.tests.unit import WithDatabase
@@ -22,6 +25,16 @@ from allura.tests.unit.patches import fake_app_patch
 from allura.tests.unit.factories import create_project, create_app_config
 
 
+class TestApplication(TestCase):
+
+    def test_validate_mount_point(self):
+        app = Application
+        mount_point = '1.2+foo_bar'
+        self.assertIsNone(app.validate_mount_point(mount_point))
+        app.relaxed_mount_points = True
+        self.assertIsNotNone(app.validate_mount_point(mount_point))
+
+
 class TestInstall(WithDatabase):
     patches = [fake_app_patch]