You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by tv...@apache.org on 2013/07/02 23:37:15 UTC

[1/2] git commit: [#4656] Refactor project name validation

Updated Branches:
  refs/heads/tv/4656 [created] 29e530164


[#4656] Refactor project name validation

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/4a72332a
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/4a72332a
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/4a72332a

Branch: refs/heads/tv/4656
Commit: 4a72332abe4429f43f79224d5f0aacc61cf82ded
Parents: ebc7e43
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Jul 2 19:56:40 2013 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Tue Jul 2 19:56:40 2013 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/project.py | 16 ++++++------
 Allura/allura/lib/plugin.py          | 41 ++++++++++++++++++++++++-------
 2 files changed, 41 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4a72332a/Allura/allura/controllers/project.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/project.py b/Allura/allura/controllers/project.py
index bff0399..e5edd80 100644
--- a/Allura/allura/controllers/project.py
+++ b/Allura/allura/controllers/project.py
@@ -175,21 +175,23 @@ class NeighborhoodController(object):
 
     @expose('json:')
     def suggest_name(self, project_name=''):
-        result = dict()
-        result['suggested_name'] = re.sub("[^A-Za-z0-9]", "", project_name).lower()[:15]
-        return result
+        provider = plugin.ProjectRegistrationProvider.get()
+        return dict(suggested_name=provider.suggest_name(project_name,
+            self.neighborhood))
 
     @expose('json:')
     def check_names(self, project_name='', unix_name=''):
+        provider = plugin.ProjectRegistrationProvider.get()
         result = dict()
         try:
             W.add_project.fields['project_name'].validate(project_name, '')
         except Invalid as e:
             result['name_message'] = str(e)
-        if not h.re_project_name.match(unix_name) or not (3 <= len(unix_name) <= 15):
-            result['unixname_message'] = 'Please use only letters, numbers, and dashes 3-15 characters long.'
-        else:
-            result['unixname_message'] = plugin.ProjectRegistrationProvider.get().name_taken(unix_name, self.neighborhood)
+
+        unixname_invalid_err = provider.validate_project_shortname(unix_name,
+                self.neighborhood)
+        result['unixname_message'] = (unixname_invalid_err or
+                provider.name_taken(unix_name, self.neighborhood))
         return result
 
     @h.vardec

http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/4a72332a/Allura/allura/lib/plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/plugin.py b/Allura/allura/lib/plugin.py
index 855e71c..c0319f7 100644
--- a/Allura/allura/lib/plugin.py
+++ b/Allura/allura/lib/plugin.py
@@ -365,6 +365,10 @@ class ProjectRegistrationProvider(object):
         return app_globals.Globals().entry_points['registration'][method]()
 
     def name_taken(self, project_name, neighborhood):
+        """Return False if ``project_name`` is available in ``neighborhood``.
+        If unavailable, return an error message (str) explaining why.
+
+        """
         from allura import model as M
         p = M.Project.query.get(shortname=project_name, neighborhood_id=neighborhood._id)
         if p:
@@ -375,18 +379,28 @@ class ProjectRegistrationProvider(object):
         return False
 
     def extra_name_checks(self):
-        '''This should be a list or iterator containing tuples.
-        The first tiem in the tuple should be an error message and the
-        second should be a regex. If the user attempts to register a
-        project with a name that matches the regex, the field will
-        be marked invalid with the message displayed to the user.
-        '''
+        """Return an iterable of ``(error_message, regex)`` tuples.
+
+        If user attempts to register a project with a name that matches
+        ``regex``, the field will be marked invalid, and ``error_message``
+        displayed to the user.
+
+        """
         return []
 
+    def suggest_name(self, project_name, neighborhood):
+        """Return a suggested project shortname for the full ``project_name``.
+
+        Example: "My Great Project" -> "mygreatproject"
+
+        """
+        return re.sub("[^A-Za-z0-9]", "", project_name).lower()
+
     def rate_limit(self, user, neighborhood):
-        '''Check the various config-defined project registration rate
+        """Check the various config-defined project registration rate
         limits, and if any are exceeded, raise ProjectRatelimitError.
-        '''
+
+        """
         if security.has_access(neighborhood, 'admin', user=user)():
             return
         # have to have the replace because, despite being UTC,
@@ -468,13 +482,22 @@ class ProjectRegistrationProvider(object):
             check_shortname = shortname.replace('u/', '', 1)
         else:
             check_shortname = shortname
-        if not h.re_project_name.match(check_shortname):
+        err = self.validate_project_shortname(check_shortname, neighborhood)
+        if err:
             raise ValueError('Invalid project shortname: %s' % shortname)
 
         p = M.Project.query.get(shortname=shortname, neighborhood_id=neighborhood._id)
         if p:
             raise forge_exc.ProjectConflict('%s already exists in nbhd %s' % (shortname, neighborhood._id))
 
+    def validate_project_shortname(self, shortname, neighborhood):
+        """Return an error message if ``shortname`` is invalid for
+        ``neighborhood``, else return None.
+
+        """
+        if not h.re_project_name.match(shortname):
+            return 'Please use only letters, numbers, and dashes 3-15 characters long.'
+
     def _create_project(self, neighborhood, shortname, project_name, user, user_project, private_project, apps):
         '''
         Actually create the project, no validation.  This should not be called directly


[2/2] git commit: [#4656] Add tests for new provider methods

Posted by tv...@apache.org.
[#4656] Add tests for new provider methods

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/29e53016
Tree: http://git-wip-us.apache.org/repos/asf/incubator-allura/tree/29e53016
Diff: http://git-wip-us.apache.org/repos/asf/incubator-allura/diff/29e53016

Branch: refs/heads/tv/4656
Commit: 29e5301647466948712d02154cfbdcf528c6f57c
Parents: 4a72332
Author: Tim Van Steenburgh <tv...@gmail.com>
Authored: Tue Jul 2 21:36:57 2013 +0000
Committer: Tim Van Steenburgh <tv...@gmail.com>
Committed: Tue Jul 2 21:36:57 2013 +0000

----------------------------------------------------------------------
 Allura/allura/tests/test_plugin.py | 23 +++++++++++++++++++----
 1 file changed, 19 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-allura/blob/29e53016/Allura/allura/tests/test_plugin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_plugin.py b/Allura/allura/tests/test_plugin.py
index 6e1a07a..aa2aaeb 100644
--- a/Allura/allura/tests/test_plugin.py
+++ b/Allura/allura/tests/test_plugin.py
@@ -16,7 +16,7 @@
 #       under the License.
 
 from nose.tools import assert_equals
-from mock import MagicMock, patch
+from mock import Mock, MagicMock, patch
 
 from allura import model as M
 from allura.lib.utils import TruthyCallable
@@ -25,16 +25,31 @@ from allura.lib.plugin import ProjectRegistrationProvider
 
 class TestProjectRegistrationProvider(object):
 
+    def setUp(self):
+        self.provider = ProjectRegistrationProvider()
+
     @patch('allura.lib.security.has_access')
     def test_validate_project_15char_user(self, has_access):
         has_access.return_value = TruthyCallable(lambda: True)
-        provider = ProjectRegistrationProvider()
         nbhd = M.Neighborhood()
-        provider.validate_project(
+        self.provider.validate_project(
             neighborhood=nbhd,
             shortname='u/' + ('a' * 15),
             project_name='15 char username',
             user=MagicMock(),
             user_project=True,
             private_project=False,
-        )
\ No newline at end of file
+        )
+
+    def test_suggest_name(self):
+        f = self.provider.suggest_name
+        assert_equals(f('A More Than Fifteen Character Name', Mock()),
+                'amorethanfifteencharactername')
+
+    def test_validate_project_shortname(self):
+        f = self.provider.validate_project_shortname
+        p = Mock()
+        assert_equals(f('thisislegit', p), None)
+        assert_equals(f('this is invalid and too long', p),
+                'Please use only letters, numbers, and dashes '
+                '3-15 characters long.')