Merge lp:~cjwatson/launchpad/git-private-code-import into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18764
Proposed branch: lp:~cjwatson/launchpad/git-private-code-import
Merge into: lp:launchpad
Diff against target: 95 lines (+50/-7)
2 files modified
lib/lp/code/xmlrpc/git.py (+2/-1)
lib/lp/code/xmlrpc/tests/test_git.py (+48/-6)
To merge this branch: bzr merge lp:~cjwatson/launchpad/git-private-code-import
Reviewer Review Type Date Requested Status
William Grant code Approve
Daniel Manrique (community) Abstain
Review via email: mp+353874@code.launchpad.net

Commit message

Fix incorrect visibility check that broke code imports targeted at private Git repositories.

To post a comment you must log in.
Revision history for this message
Daniel Manrique (roadmr) wrote :

LGTM, thanks! I'm not a Launchpad code reviewer and I don't know this codebase well enough, so I'll abstain, but this makes sense.

review: Abstain
Revision history for this message
William Grant (wgrant) :
review: Approve (code)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'lib/lp/code/xmlrpc/git.py'
2--- lib/lp/code/xmlrpc/git.py 2016-10-14 11:48:57 +0000
3+++ lib/lp/code/xmlrpc/git.py 2018-08-28 14:08:04 +0000
4@@ -108,7 +108,8 @@
5 # The authentication parameters specifically grant access to
6 # this repository, so we can bypass other checks.
7 # For the time being, this only works for code imports.
8- assert repository.repository_type == GitRepositoryType.IMPORTED
9+ assert (
10+ naked_repository.repository_type == GitRepositoryType.IMPORTED)
11 hosting_path = naked_repository.getInternalPath()
12 writable = True
13 private = naked_repository.private
14
15=== modified file 'lib/lp/code/xmlrpc/tests/test_git.py'
16--- lib/lp/code/xmlrpc/tests/test_git.py 2016-10-14 11:48:57 +0000
17+++ lib/lp/code/xmlrpc/tests/test_git.py 2018-08-28 14:08:04 +0000
18@@ -53,13 +53,14 @@
19 self.repository_set = getUtility(IGitRepositorySet)
20
21 def assertGitRepositoryNotFound(self, requester, path, permission="read",
22- can_authenticate=False):
23+ can_authenticate=False, macaroon_raw=None):
24 """Assert that the given path cannot be translated."""
25 if requester is not None:
26 requester = requester.id
27- fault = self.git_api.translatePath(
28- path, permission,
29- {"uid": requester, "can-authenticate": can_authenticate})
30+ auth_params = {"uid": requester, "can-authenticate": can_authenticate}
31+ if macaroon_raw is not None:
32+ auth_params["macaroon"] = macaroon_raw
33+ fault = self.git_api.translatePath(path, permission, auth_params)
34 self.assertEqual(
35 faults.GitRepositoryNotFound(path.strip("/")), fault)
36
37@@ -145,8 +146,8 @@
38 translation = self.git_api.translatePath(path, permission, auth_params)
39 login(ANONYMOUS)
40 self.assertEqual(
41- {"path": repository.getInternalPath(), "writable": writable,
42- "trailing": trailing, "private": private},
43+ {"path": removeSecurityProxy(repository).getInternalPath(),
44+ "writable": writable, "trailing": trailing, "private": private},
45 translation)
46
47 def assertCreates(self, requester, path, can_authenticate=False,
48@@ -663,6 +664,47 @@
49 self.assertPermissionDenied(
50 None, path, permission="write", macaroon_raw="nonsense")
51
52+ def test_translatePath_private_code_import(self):
53+ # A code import worker with a suitable macaroon can write to a
54+ # repository associated with a running private code import job.
55+ self.pushConfig("codeimport", macaroon_secret_key="some-secret")
56+ machine = self.factory.makeCodeImportMachine(set_online=True)
57+ code_imports = [
58+ self.factory.makeCodeImport(
59+ target_rcs_type=TargetRevisionControlSystems.GIT)
60+ for _ in range(2)]
61+ private_repository = code_imports[0].git_repository
62+ removeSecurityProxy(private_repository).transitionToInformationType(
63+ InformationType.PRIVATESECURITY, private_repository.owner)
64+ with celebrity_logged_in("vcs_imports"):
65+ jobs = [
66+ self.factory.makeCodeImportJob(code_import=code_import)
67+ for code_import in code_imports]
68+ issuer = getUtility(IMacaroonIssuer, "code-import-job")
69+ macaroons = [
70+ removeSecurityProxy(issuer).issueMacaroon(job) for job in jobs]
71+ path = u"/%s" % code_imports[0].git_repository.unique_name
72+ self.assertPermissionDenied(
73+ None, path, permission="write", macaroon_raw=macaroons[0])
74+ with celebrity_logged_in("vcs_imports"):
75+ getUtility(ICodeImportJobWorkflow).startJob(jobs[0], machine)
76+ self.assertTranslates(
77+ None, path, code_imports[0].git_repository, True,
78+ permission="write", macaroon_raw=macaroons[0].serialize(),
79+ private=True)
80+ # The expected faults are slightly different from the public case,
81+ # because we deny the existence of private repositories.
82+ self.assertGitRepositoryNotFound(
83+ None, path, permission="write",
84+ macaroon_raw=macaroons[1].serialize())
85+ self.assertGitRepositoryNotFound(
86+ None, path, permission="write",
87+ macaroon_raw=Macaroon(
88+ location=config.vhost.mainsite.hostname, identifier="another",
89+ key="another-secret").serialize())
90+ self.assertGitRepositoryNotFound(
91+ None, path, permission="write", macaroon_raw="nonsense")
92+
93 def test_notify(self):
94 # The notify call creates a GitRefScanJob.
95 repository = self.factory.makeGitRepository()