Merge lp:~cjwatson/launchpad/drop-old-git-permissions-protocol into lp:launchpad
- drop-old-git-permissions-protocol
- Merge into devel
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 |
Related bugs: |
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.
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()) |