Merge lp:~cjwatson/launchpad/drop-old-git-permissions-protocol into lp:launchpad

Proposed by Colin Watson
Status: Merged
Merged at revision: 18970
Proposed branch: lp:~cjwatson/launchpad/drop-old-git-permissions-protocol
Merge into: lp:launchpad
Diff against target: 340 lines (+85/-165)
2 files modified
lib/lp/code/xmlrpc/git.py (+10/-23)
lib/lp/code/xmlrpc/tests/test_git.py (+75/-142)
To merge this branch: bzr merge lp:~cjwatson/launchpad/drop-old-git-permissions-protocol
Reviewer Review Type Date Requested Status
Tom Wardill (community) Approve
Review via email: mp+368061@code.launchpad.net

Commit message

Drop support for ref paths being text in GitAPI.checkRefPermissions.

Description of the change

turnip was upgraded on production a while back, so ref paths are now always bytes.

To post a comment you must log in.
Revision history for this message
Tom Wardill (twom) :
review: Approve

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 2019-05-09 15:44:59 +0000
3+++ lib/lp/code/xmlrpc/git.py 2019-05-29 11:39:29 +0000
4@@ -466,29 +466,16 @@
5 (xmlrpc_client.Binary(ref_path.data), [])
6 for ref_path in ref_paths]
7
8- if all(isinstance(ref_path, xmlrpc_client.Binary)
9- for ref_path in ref_paths):
10- # New protocol: caller sends paths as bytes; Launchpad returns a
11- # list of (path, permissions) tuples. (XML-RPC doesn't support
12- # dict keys being bytes.)
13- ref_paths = [ref_path.data for ref_path in ref_paths]
14- return [
15- (xmlrpc_client.Binary(ref_path),
16- self._renderPermissions(permissions))
17- for ref_path, permissions in repository.checkRefPermissions(
18- requester, ref_paths).items()
19- ]
20- else:
21- # Old protocol: caller sends paths as text; Launchpad returns a
22- # dict of {path: permissions}.
23- # XXX cjwatson 2018-11-21: Remove this once turnip has migrated
24- # to the new protocol. git ref paths are not required to be
25- # valid UTF-8.
26- return {
27- ref_path: self._renderPermissions(permissions)
28- for ref_path, permissions in repository.checkRefPermissions(
29- requester, ref_paths).items()
30- }
31+ # Caller sends paths as bytes; Launchpad returns a list of (path,
32+ # permissions) tuples. (XML-RPC doesn't support dict keys being
33+ # bytes.)
34+ ref_paths = [ref_path.data for ref_path in ref_paths]
35+ return [
36+ (xmlrpc_client.Binary(ref_path),
37+ self._renderPermissions(permissions))
38+ for ref_path, permissions in repository.checkRefPermissions(
39+ requester, ref_paths).items()
40+ ]
41
42 def checkRefPermissions(self, translated_path, ref_paths, auth_params):
43 """See `IGitAPI`."""
44
45=== modified file 'lib/lp/code/xmlrpc/tests/test_git.py'
46--- lib/lp/code/xmlrpc/tests/test_git.py 2019-05-09 15:44:59 +0000
47+++ lib/lp/code/xmlrpc/tests/test_git.py 2019-05-29 11:39:29 +0000
48@@ -11,7 +11,6 @@
49 Equals,
50 IsInstance,
51 MatchesAll,
52- MatchesDict,
53 MatchesListwise,
54 MatchesSetwise,
55 MatchesStructure,
56@@ -193,25 +192,18 @@
57 permissions, macaroon_raw=None):
58 auth_params = _make_auth_params(requester, macaroon_raw=macaroon_raw)
59 translated_path = removeSecurityProxy(repository).getInternalPath()
60- if all(isinstance(ref_path, bytes) for ref_path in ref_paths):
61- ref_paths = [
62- xmlrpc_client.Binary(ref_path) for ref_path in ref_paths]
63- results = self.git_api.checkRefPermissions(
64- translated_path, ref_paths, auth_params)
65- self.assertThat(results, MatchesSetwise(*(
66- MatchesListwise([
67- MatchesAll(
68- IsInstance(xmlrpc_client.Binary),
69- MatchesStructure.byEquality(data=ref_path)),
70- Equals(ref_permissions),
71- ])
72- for ref_path, ref_permissions in permissions.items())))
73- else:
74- results = self.git_api.checkRefPermissions(
75- translated_path, ref_paths, auth_params)
76- self.assertThat(results, MatchesDict({
77- ref_path: Equals(ref_permissions)
78- for ref_path, ref_permissions in permissions.items()}))
79+ ref_paths = [
80+ xmlrpc_client.Binary(ref_path) for ref_path in ref_paths]
81+ results = self.git_api.checkRefPermissions(
82+ translated_path, ref_paths, auth_params)
83+ self.assertThat(results, MatchesSetwise(*(
84+ MatchesListwise([
85+ MatchesAll(
86+ IsInstance(xmlrpc_client.Binary),
87+ MatchesStructure.byEquality(data=ref_path)),
88+ Equals(ref_permissions),
89+ ])
90+ for ref_path, ref_permissions in permissions.items())))
91
92 def test_translatePath_private_repository(self):
93 requester = self.factory.makePerson()
94@@ -380,10 +372,10 @@
95 rule=rule, grantee=stable_team, can_create=True)
96
97 test_ref_paths = [
98- 'refs/heads/stable/next', 'refs/heads/stable/protected',
99- 'refs/heads/stable/foo', 'refs/heads/archived/foo',
100- 'refs/heads/foo/next', 'refs/heads/unprotected',
101- 'refs/tags/1.0',
102+ b'refs/heads/stable/next', b'refs/heads/stable/protected',
103+ b'refs/heads/stable/foo', b'refs/heads/archived/foo',
104+ b'refs/heads/foo/next', b'refs/heads/unprotected',
105+ b'refs/tags/1.0',
106 ]
107
108 return (user_a, user_b, user_c, stable_team, next_team, repository,
109@@ -391,76 +383,52 @@
110
111 def test_checkRefPermissions_scenario_one_user_a(self):
112 user_a, _, _, _, _, repo, paths = self._make_scenario_one_repository()
113-
114- results = self.git_api.checkRefPermissions(
115- repo.getInternalPath(),
116- paths,
117- {'uid': user_a.id})
118-
119- self.assertThat(results, MatchesDict({
120- 'refs/heads/stable/next': Equals(['push', 'force_push']),
121- 'refs/heads/stable/protected': Equals(['create', 'push']),
122- 'refs/heads/stable/foo': Equals(['create', 'push']),
123- 'refs/heads/archived/foo': Equals([]),
124- 'refs/heads/foo/next': Equals(['create', 'push']),
125- 'refs/heads/unprotected': Equals(['create', 'push', 'force_push']),
126- 'refs/tags/1.0': Equals(['create']),
127- }))
128+ self.assertHasRefPermissions(user_a, repo, paths, {
129+ b'refs/heads/stable/next': ['push', 'force_push'],
130+ b'refs/heads/stable/protected': ['create', 'push'],
131+ b'refs/heads/stable/foo': ['create', 'push'],
132+ b'refs/heads/archived/foo': [],
133+ b'refs/heads/foo/next': ['create', 'push'],
134+ b'refs/heads/unprotected': ['create', 'push', 'force_push'],
135+ b'refs/tags/1.0': ['create'],
136+ })
137
138 def test_checkRefPermissions_scenario_one_user_b(self):
139 _, user_b, _, _, _, repo, paths = self._make_scenario_one_repository()
140-
141- results = self.git_api.checkRefPermissions(
142- repo.getInternalPath(),
143- paths,
144- {'uid': user_b.id})
145-
146- self.assertThat(results, MatchesDict({
147- 'refs/heads/stable/next': Equals(['push', 'force_push']),
148- 'refs/heads/stable/protected': Equals([]),
149- 'refs/heads/stable/foo': Equals(['push']),
150- 'refs/heads/archived/foo': Equals(['create']),
151- 'refs/heads/foo/next': Equals(['push', 'force_push']),
152- 'refs/heads/unprotected': Equals([]),
153- 'refs/tags/1.0': Equals(['create']),
154- }))
155+ self.assertHasRefPermissions(user_b, repo, paths, {
156+ b'refs/heads/stable/next': ['push', 'force_push'],
157+ b'refs/heads/stable/protected': [],
158+ b'refs/heads/stable/foo': ['push'],
159+ b'refs/heads/archived/foo': ['create'],
160+ b'refs/heads/foo/next': ['push', 'force_push'],
161+ b'refs/heads/unprotected': [],
162+ b'refs/tags/1.0': ['create'],
163+ })
164
165 def test_checkRefPermissions_scenario_one_user_c(self):
166 _, _, user_c, _, _, repo, paths = self._make_scenario_one_repository()
167-
168- results = self.git_api.checkRefPermissions(
169- repo.getInternalPath(),
170- paths,
171- {'uid': user_c.id})
172-
173- self.assertThat(results, MatchesDict({
174- 'refs/heads/stable/next': Equals(['push', 'force_push']),
175- 'refs/heads/stable/protected': Equals([]),
176- 'refs/heads/stable/foo': Equals([]),
177- 'refs/heads/archived/foo': Equals([]),
178- 'refs/heads/foo/next': Equals(['push', 'force_push']),
179- 'refs/heads/unprotected': Equals([]),
180- 'refs/tags/1.0': Equals([]),
181- }))
182+ self.assertHasRefPermissions(user_c, repo, paths, {
183+ b'refs/heads/stable/next': ['push', 'force_push'],
184+ b'refs/heads/stable/protected': [],
185+ b'refs/heads/stable/foo': [],
186+ b'refs/heads/archived/foo': [],
187+ b'refs/heads/foo/next': ['push', 'force_push'],
188+ b'refs/heads/unprotected': [],
189+ b'refs/tags/1.0': [],
190+ })
191
192 def test_checkRefPermissions_scenario_one_user_d(self):
193 user_d = self.factory.makePerson()
194- _, _, user_c, _, _, repo, paths = self._make_scenario_one_repository()
195-
196- results = self.git_api.checkRefPermissions(
197- repo.getInternalPath(),
198- paths,
199- {'uid': user_d.id})
200-
201- self.assertThat(results, MatchesDict({
202- 'refs/heads/stable/next': Equals([]),
203- 'refs/heads/stable/protected': Equals([]),
204- 'refs/heads/stable/foo': Equals([]),
205- 'refs/heads/archived/foo': Equals([]),
206- 'refs/heads/foo/next': Equals([]),
207- 'refs/heads/unprotected': Equals([]),
208- 'refs/tags/1.0': Equals([]),
209- }))
210+ _, _, _, _, _, repo, paths = self._make_scenario_one_repository()
211+ self.assertHasRefPermissions(user_d, repo, paths, {
212+ b'refs/heads/stable/next': [],
213+ b'refs/heads/stable/protected': [],
214+ b'refs/heads/stable/foo': [],
215+ b'refs/heads/archived/foo': [],
216+ b'refs/heads/foo/next': [],
217+ b'refs/heads/unprotected': [],
218+ b'refs/tags/1.0': [],
219+ })
220
221 def _make_scenario_two_repository(self):
222 user_a = self.factory.makePerson()
223@@ -485,52 +453,37 @@
224 self.factory.makeGitRuleGrant(
225 rule=rule, grantee=user_b, can_push=True)
226
227- test_ref_paths = ['refs/heads/master', 'refs/heads/foo',
228- 'refs/tags/1.0', 'refs/other']
229+ test_ref_paths = [b'refs/heads/master', b'refs/heads/foo',
230+ b'refs/tags/1.0', b'refs/other']
231 return user_a, user_b, repository, test_ref_paths
232
233 def test_checkRefPermissions_scenario_two_user_a(self):
234 user_a, _, repo, paths = self._make_scenario_two_repository()
235- results = self.git_api.checkRefPermissions(
236- repo.getInternalPath(),
237- paths,
238- {'uid': user_a.id})
239-
240- self.assertThat(results, MatchesDict({
241- 'refs/heads/master': Equals(['create', 'push', 'force_push']),
242- 'refs/heads/foo': Equals(['create', 'push', 'force_push']),
243- 'refs/tags/1.0': Equals(['create', 'push']),
244- 'refs/other': Equals(['create', 'push', 'force_push']),
245- }))
246+ self.assertHasRefPermissions(user_a, repo, paths, {
247+ b'refs/heads/master': ['create', 'push', 'force_push'],
248+ b'refs/heads/foo': ['create', 'push', 'force_push'],
249+ b'refs/tags/1.0': ['create', 'push'],
250+ b'refs/other': ['create', 'push', 'force_push'],
251+ })
252
253 def test_checkRefPermissions_scenario_two_user_b(self):
254 _, user_b, repo, paths = self._make_scenario_two_repository()
255- results = self.git_api.checkRefPermissions(
256- repo.getInternalPath(),
257- paths,
258- {'uid': user_b.id})
259-
260- self.assertThat(results, MatchesDict({
261- 'refs/heads/master': Equals(['push']),
262- 'refs/heads/foo': Equals([]),
263- 'refs/tags/1.0': Equals(['push']),
264- 'refs/other': Equals([]),
265- }))
266+ self.assertHasRefPermissions(user_b, repo, paths, {
267+ b'refs/heads/master': ['push'],
268+ b'refs/heads/foo': [],
269+ b'refs/tags/1.0': ['push'],
270+ b'refs/other': [],
271+ })
272
273 def test_checkRefPermissions_scenario_two_user_c(self):
274 _, _, repo, paths = self._make_scenario_two_repository()
275 user_c = self.factory.makePerson()
276- results = self.git_api.checkRefPermissions(
277- repo.getInternalPath(),
278- paths,
279- {'uid': user_c.id})
280-
281- self.assertThat(results, MatchesDict({
282- 'refs/heads/master': Equals([]),
283- 'refs/heads/foo': Equals([]),
284- 'refs/tags/1.0': Equals([]),
285- 'refs/other': Equals([]),
286- }))
287+ self.assertHasRefPermissions(user_c, repo, paths, {
288+ b'refs/heads/master': [],
289+ b'refs/heads/foo': [],
290+ b'refs/tags/1.0': [],
291+ b'refs/other': [],
292+ })
293
294 def test_checkRefPermissions_bytes(self):
295 owner = self.factory.makePerson()
296@@ -556,26 +509,6 @@
297 self.assertHasRefPermissions(
298 no_privileges, repository, paths, {path: [] for path in paths})
299
300- def test_checkRefPermissions_unicode(self):
301- # Actual Unicode ref paths work too.
302- # XXX cjwatson 2018-11-21: Remove this when the transition to the
303- # new protocol is complete.
304- owner = self.factory.makePerson()
305- grantee = self.factory.makePerson()
306- no_privileges = self.factory.makePerson()
307- repository = removeSecurityProxy(
308- self.factory.makeGitRepository(owner=owner))
309- self.factory.makeGitRuleGrant(
310- repository=repository, ref_pattern=u"refs/heads/next/*",
311- grantee=grantee, can_push=True)
312- path = u"refs/heads/next/\N{SNOWMAN}"
313-
314- self.assertHasRefPermissions(
315- grantee, repository, [path], {path: ["push"]})
316- login(ANONYMOUS)
317- self.assertHasRefPermissions(
318- no_privileges, repository, [path], {path: []})
319-
320 def test_checkRefPermissions_nonexistent_repository(self):
321 requester = self.factory.makePerson()
322 self.assertEqual(
323@@ -1176,7 +1109,7 @@
324 macaroons = [
325 removeSecurityProxy(issuer).issueMacaroon(job) for job in jobs]
326 repository = code_imports[0].git_repository
327- ref_path = "refs/heads/master"
328+ ref_path = b"refs/heads/master"
329 self.assertHasRefPermissions(
330 LAUNCHPAD_SERVICES, repository, [ref_path], {ref_path: []},
331 macaroon_raw=macaroons[0].serialize())
332@@ -1223,7 +1156,7 @@
333 macaroons = [
334 removeSecurityProxy(issuer).issueMacaroon(job) for job in jobs]
335 repository = code_imports[0].git_repository
336- ref_path = "refs/heads/master"
337+ ref_path = b"refs/heads/master"
338 self.assertHasRefPermissions(
339 LAUNCHPAD_SERVICES, repository, [ref_path], {ref_path: []},
340 macaroon_raw=macaroons[0].serialize())