← Back to team overview

launchpad-reviewers team mailing list archive

[Merge] ~lgp171188/launchpad:allow-editing-code-import-url-webservice-api into launchpad:master

 

Guruprasad has proposed merging ~lgp171188/launchpad:allow-editing-code-import-url-webservice-api into launchpad:master.

Commit message:
Allow setting the code import URL using the Launchpad API

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~lgp171188/launchpad/+git/launchpad/+merge/412509
-- 
Your team Launchpad code reviewers is requested to review the proposed merge of ~lgp171188/launchpad:allow-editing-code-import-url-webservice-api into launchpad:master.
diff --git a/lib/lp/code/configure.zcml b/lib/lp/code/configure.zcml
index 8079ed3..6417c89 100644
--- a/lib/lp/code/configure.zcml
+++ b/lib/lp/code/configure.zcml
@@ -660,7 +660,7 @@
                        getImportDetailsForDisplay"/>
     <require
        permission="launchpad.Edit"
-       attributes="updateURL"/>
+       attributes="updateURL setURL"/>
 
     <require
        permission="launchpad.AnyPerson"
diff --git a/lib/lp/code/interfaces/codeimport.py b/lib/lp/code/interfaces/codeimport.py
index 36f2fd7..8059d11 100644
--- a/lib/lp/code/interfaces/codeimport.py
+++ b/lib/lp/code/interfaces/codeimport.py
@@ -15,9 +15,13 @@ from lazr.restful.declarations import (
     export_write_operation,
     exported,
     exported_as_webservice_entry,
+    mutator_for,
+    operation_for_version,
+    operation_parameters,
     REQUEST_USER,
     )
 from lazr.restful.fields import ReferenceChoice
+from lazr.restful.interface import copy_field
 from zope.interface import (
     Attribute,
     Interface,
@@ -228,6 +232,20 @@ class ICodeImport(Interface):
             None if no changes were made.
         """
 
+    @mutator_for(url)
+    @call_with(user=REQUEST_USER)
+    @operation_parameters(url=copy_field(url))
+    @export_write_operation()
+    @operation_for_version("devel")
+    def setURL(url, user):
+        """
+        Set the url for ICodeImport.
+
+        :param url: The URL for the code import.
+        :param user: The user setting the URL.
+        :return: None.
+        """
+
     def updateURL(new_url, user):
         """Update the URL for this `CodeImport`.
 
diff --git a/lib/lp/code/model/codeimport.py b/lib/lp/code/model/codeimport.py
index b8d0da8..c2b028e 100644
--- a/lib/lp/code/model/codeimport.py
+++ b/lib/lp/code/model/codeimport.py
@@ -246,6 +246,9 @@ class CodeImport(StormBase):
             code_import_updated(self, event, new_whiteboard, user)
         return event
 
+    def setURL(self, url, user):
+        self.updateURL(url, user)
+
     def updateURL(self, new_url, user):
         if self.url != new_url:
             data = {"url": new_url}
diff --git a/lib/lp/code/model/tests/test_codeimport.py b/lib/lp/code/model/tests/test_codeimport.py
index 22fbe77..a8d4bc3 100644
--- a/lib/lp/code/model/tests/test_codeimport.py
+++ b/lib/lp/code/model/tests/test_codeimport.py
@@ -8,6 +8,7 @@ from datetime import (
     timedelta,
     )
 from functools import partial
+import json
 
 import pytz
 from storm.store import Store
@@ -45,10 +46,14 @@ from lp.code.tests.codeimporthelpers import make_running_import
 from lp.code.tests.helpers import GitHostingFixture
 from lp.registry.interfaces.person import IPersonSet
 from lp.services.database.interfaces import IStore
+from lp.services.webapp.interfaces import OAuthPermission
 from lp.testing import (
+    ANONYMOUS,
+    api_url,
     login,
     login_person,
     logout,
+    person_logged_in,
     TestCaseWithFactory,
     time_counter,
     )
@@ -57,6 +62,7 @@ from lp.testing.layers import (
     LaunchpadFunctionalLayer,
     LaunchpadZopelessLayer,
     )
+from lp.testing.pages import webservice_for_person
 
 
 class TestCodeImportBase(WithScenarios, TestCaseWithFactory):
@@ -829,4 +835,60 @@ class TestRequestImport(TestCodeImportBase):
             requester)
 
 
+class TestCodeImportWebservice(TestCodeImportBase):
+    """Tests for the web service."""
+
+    layer = DatabaseFunctionalLayer
+
+    def test_codeimport_owner_can_set_url(self):
+        # Repository owner can set the code import URL.
+        owner_db = self.factory.makePerson()
+        initial_import_url = self.factory.getUniqueURL()
+        code_import = self.factory.makeCodeImport(
+            owner=owner_db,
+            registrant=owner_db,
+            git_repo_url=initial_import_url,
+            rcs_type=RevisionControlSystems.GIT,
+            target_rcs_type=self.target_rcs_type,
+        )
+        webservice = webservice_for_person(
+            owner_db, permission=OAuthPermission.WRITE_PRIVATE)
+        webservice.default_api_version = "devel"
+        with person_logged_in(ANONYMOUS):
+            code_import_url = api_url(code_import)
+
+        new_url = "https://example.com/foo/bar.git";
+        response = webservice.patch(
+            code_import_url, "application/json",
+            json.dumps({"url": new_url})
+        )
+        self.assertEqual(209, response.status)
+        code_import_json = webservice.get(code_import_url).jsonBody()
+        self.assertEqual(new_url, code_import_json['url'])
+
+    def test_codeimport_users_without_permission_cannot_set_url(self):
+        # The users without the Launchpad.Edit permission cannot set the
+        # code import URL.
+        owner_db = self.factory.makePerson()
+        code_import = self.factory.makeCodeImport(
+            owner=owner_db,
+            registrant=owner_db,
+            target_rcs_type=self.target_rcs_type
+        )
+        another_person = self.factory.makePerson()
+        webservice = webservice_for_person(
+            another_person, permission=OAuthPermission.WRITE_PRIVATE)
+        webservice.default_api_version = "devel"
+
+        with person_logged_in(ANONYMOUS):
+            code_import_url = api_url(code_import)
+
+        new_url = "https://example.com/foo/bar.git";
+        response = webservice.patch(
+            code_import_url, "application/json",
+            json.dumps({"url": new_url}),
+        )
+        self.assertEqual(401, response.status)
+
+
 load_tests = load_tests_apply_scenarios