From 17117d45cca7d55c2337d97f5f660d29fb8cd5af Mon Sep 17 00:00:00 2001 From: Adam Coldrick Date: Thu, 21 Jun 2018 08:00:26 +0100 Subject: [PATCH] Support quoted project names in GET requests by name Currently the webclient quotes the project name before sending the request, which causes a 404 if there is a / in the project name since the API doesn't unquote the name before searching for it. This commit makes the API less opinionated by unquoting provided project names before searching for them, which should make it less frustrating to use. Change-Id: I9a0158231f54809b90198875712ac0cbd543a254 --- storyboard/api/v1/projects.py | 3 ++- storyboard/tests/api/test_projects.py | 18 +++++++++++++++++- storyboard/tests/db/test_load_projects.py | 2 +- storyboard/tests/mock_data.py | 2 +- 4 files changed, 21 insertions(+), 4 deletions(-) diff --git a/storyboard/api/v1/projects.py b/storyboard/api/v1/projects.py index 9d698831..55a79356 100644 --- a/storyboard/api/v1/projects.py +++ b/storyboard/api/v1/projects.py @@ -18,6 +18,7 @@ from pecan.decorators import expose from pecan import response from pecan import rest from pecan.secure import secure +from six.moves.urllib.parse import unquote from wsme import types as wtypes import wsmeext.pecan as wsme_pecan @@ -221,7 +222,7 @@ class ProjectsController(rest.RestController): def _route(self, args, request): if request.method == 'GET' and len(args) > 0: # It's a request by a name or id - something = args[0] + something = unquote(args[0]) if something == "search": # Request to a search endpoint diff --git a/storyboard/tests/api/test_projects.py b/storyboard/tests/api/test_projects.py index 07842313..6b1ea10b 100644 --- a/storyboard/tests/api/test_projects.py +++ b/storyboard/tests/api/test_projects.py @@ -26,7 +26,7 @@ class TestProjects(base.FunctionalTest): self.resource = '/projects' self.project_01 = { - 'name': 'test-project', + 'name': 'tests/test-project', 'description': 'some description' } @@ -43,6 +43,22 @@ class TestProjects(base.FunctionalTest): self.assertEqual('Project 3 Description - foo', response['description']) + def test_get_by_name(self): + project = self.get_json( + path=self.resource + '/tests/project3') + + self.assertEqual('tests/project3', project['name']) + self.assertEqual('Project 1 Description - foo', + project['description']) + + def test_get_by_name_quoted(self): + project = self.get_json( + path=self.resource + '/tests%2Fproject3') + + self.assertEqual('tests/project3', project['name']) + self.assertEqual('Project 1 Description - foo', + project['description']) + def test_get_nonexistent(self): response = self.get_json(path=self.resource + "/999", expect_errors=True) diff --git a/storyboard/tests/db/test_load_projects.py b/storyboard/tests/db/test_load_projects.py index de6a8a39..16d3c988 100644 --- a/storyboard/tests/db/test_load_projects.py +++ b/storyboard/tests/db/test_load_projects.py @@ -45,7 +45,7 @@ class TestLoadProjects(base.BaseDbTestCase): # Loaded + mock_data project_names = ["Test-Project", "Test-Project-Two", - "project1", "project2", "project3"] + "project1", "project2", "tests/project3"] project_ids = [] for project in projects: self.assertIn(project.name, project_names) diff --git a/storyboard/tests/mock_data.py b/storyboard/tests/mock_data.py index f84f70f9..7d1eb5eb 100644 --- a/storyboard/tests/mock_data.py +++ b/storyboard/tests/mock_data.py @@ -124,7 +124,7 @@ def load(): description='Project 2 Description - bar'), Project( id=3, - name='project3', + name='tests/project3', description='Project 1 Description - foo') ])