Merge lp:~cjwatson/launchpad/fix-git-authenticateWithPassword into lp:launchpad
- fix-git-authenticateWithPassword
- Merge into devel
Proposed by
Colin Watson
Status: | Merged |
---|---|
Merged at revision: | 19064 |
Proposed branch: | lp:~cjwatson/launchpad/fix-git-authenticateWithPassword |
Merge into: | lp:launchpad |
Diff against target: |
342 lines (+116/-62) 3 files modified
lib/lp/code/interfaces/gitapi.py (+7/-2) lib/lp/code/xmlrpc/git.py (+12/-3) lib/lp/code/xmlrpc/tests/test_git.py (+97/-57) |
To merge this branch: | bzr merge lp:~cjwatson/launchpad/fix-git-authenticateWithPassword |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Tony Simpson (community) | Approve | ||
Launchpad code reviewers | Pending | ||
Review via email: mp+373332@code.launchpad.net |
Commit message
Fix XML-RPC publication of IGitAPI.
Description of the change
Zope's XML-RPC publication machinery was confused by the return_fault decorator, and published a method taking zero arguments. Pushing this decorator down a layer avoids that problem.
To test this, I needed to refactor the tests to call the API under test via an XML-RPC ServerProxy (which I probably should have done from the start anyway). Since this has the effect of serialising and deserialising any fault that's raised, I also had to rearrange how they test for faults.
To post a comment you must log in.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'lib/lp/code/interfaces/gitapi.py' | |||
2 | --- lib/lp/code/interfaces/gitapi.py 2018-10-22 19:16:09 +0000 | |||
3 | +++ lib/lp/code/interfaces/gitapi.py 2019-09-27 15:51:36 +0000 | |||
4 | @@ -64,8 +64,13 @@ | |||
5 | 64 | def authenticateWithPassword(username, password): | 64 | def authenticateWithPassword(username, password): |
6 | 65 | """Authenticate a user by username and password. | 65 | """Authenticate a user by username and password. |
7 | 66 | 66 | ||
10 | 67 | :returns: An `Unauthorized` fault, as password authentication is | 67 | This currently only works when using macaroon authentication. |
11 | 68 | not yet supported. | 68 | |
12 | 69 | :returns: An `Unauthorized` fault if the username and password do | ||
13 | 70 | not match; otherwise, a dict containing a "uid" (for a real | ||
14 | 71 | user) or "user" (for internal services) key indicating the | ||
15 | 72 | authenticated principal, and possibly "macaroon" with a macaroon | ||
16 | 73 | that requires further authorisation by other methods. | ||
17 | 69 | """ | 74 | """ |
18 | 70 | 75 | ||
19 | 71 | def checkRefPermissions(translated_paths, ref_paths, auth_params): | 76 | def checkRefPermissions(translated_paths, ref_paths, auth_params): |
20 | 72 | 77 | ||
21 | === modified file 'lib/lp/code/xmlrpc/git.py' | |||
22 | --- lib/lp/code/xmlrpc/git.py 2019-09-10 09:58:52 +0000 | |||
23 | +++ lib/lp/code/xmlrpc/git.py 2019-09-27 15:51:36 +0000 | |||
24 | @@ -427,8 +427,13 @@ | |||
25 | 427 | removeSecurityProxy(repository)) | 427 | removeSecurityProxy(repository)) |
26 | 428 | 428 | ||
27 | 429 | @return_fault | 429 | @return_fault |
30 | 430 | def authenticateWithPassword(self, username, password): | 430 | def _authenticateWithPassword(self, username, password): |
31 | 431 | """See `IGitAPI`.""" | 431 | """Authenticate a user by username and password. |
32 | 432 | |||
33 | 433 | This is a separate method from `authenticateWithPassword` because | ||
34 | 434 | otherwise Zope's XML-RPC publication machinery gets confused by the | ||
35 | 435 | decorator and publishes a method that takes zero arguments. | ||
36 | 436 | """ | ||
37 | 432 | user = getUtility(IPersonSet).getByName(username) if username else None | 437 | user = getUtility(IPersonSet).getByName(username) if username else None |
38 | 433 | verified = self._verifyMacaroon(password, user=user) | 438 | verified = self._verifyMacaroon(password, user=user) |
39 | 434 | if verified: | 439 | if verified: |
40 | @@ -439,7 +444,11 @@ | |||
41 | 439 | auth_params["user"] = LAUNCHPAD_SERVICES | 444 | auth_params["user"] = LAUNCHPAD_SERVICES |
42 | 440 | return auth_params | 445 | return auth_params |
43 | 441 | # Only macaroons are supported for password authentication. | 446 | # Only macaroons are supported for password authentication. |
45 | 442 | return faults.Unauthorized() | 447 | raise faults.Unauthorized() |
46 | 448 | |||
47 | 449 | def authenticateWithPassword(self, username, password): | ||
48 | 450 | """See `IGitAPI`.""" | ||
49 | 451 | return self._authenticateWithPassword(username, password) | ||
50 | 443 | 452 | ||
51 | 444 | def _renderPermissions(self, set_of_permissions): | 453 | def _renderPermissions(self, set_of_permissions): |
52 | 445 | """Render a set of permission strings for XML-RPC output.""" | 454 | """Render a set of permission strings for XML-RPC output.""" |
53 | 446 | 455 | ||
54 | === modified file 'lib/lp/code/xmlrpc/tests/test_git.py' | |||
55 | --- lib/lp/code/xmlrpc/tests/test_git.py 2019-09-05 11:29:00 +0000 | |||
56 | +++ lib/lp/code/xmlrpc/tests/test_git.py 2019-09-27 15:51:36 +0000 | |||
57 | @@ -6,6 +6,7 @@ | |||
58 | 6 | __metaclass__ = type | 6 | __metaclass__ = type |
59 | 7 | 7 | ||
60 | 8 | from pymacaroons import Macaroon | 8 | from pymacaroons import Macaroon |
61 | 9 | import six | ||
62 | 9 | from six.moves import xmlrpc_client | 10 | from six.moves import xmlrpc_client |
63 | 10 | from testtools.matchers import ( | 11 | from testtools.matchers import ( |
64 | 11 | Equals, | 12 | Equals, |
65 | @@ -37,7 +38,6 @@ | |||
66 | 37 | IGitRepositorySet, | 38 | IGitRepositorySet, |
67 | 38 | ) | 39 | ) |
68 | 39 | from lp.code.tests.helpers import GitHostingFixture | 40 | from lp.code.tests.helpers import GitHostingFixture |
69 | 40 | from lp.code.xmlrpc.git import GitAPI | ||
70 | 41 | from lp.registry.enums import TeamMembershipPolicy | 41 | from lp.registry.enums import TeamMembershipPolicy |
71 | 42 | from lp.services.config import config | 42 | from lp.services.config import config |
72 | 43 | from lp.services.features.testing import FeatureFixture | 43 | from lp.services.features.testing import FeatureFixture |
73 | @@ -62,6 +62,7 @@ | |||
74 | 62 | AppServerLayer, | 62 | AppServerLayer, |
75 | 63 | LaunchpadFunctionalLayer, | 63 | LaunchpadFunctionalLayer, |
76 | 64 | ) | 64 | ) |
77 | 65 | from lp.testing.xmlrpc import XMLRPCTestTransport | ||
78 | 65 | from lp.xmlrpc import faults | 66 | from lp.xmlrpc import faults |
79 | 66 | 67 | ||
80 | 67 | 68 | ||
81 | @@ -108,24 +109,58 @@ | |||
82 | 108 | return ok | 109 | return ok |
83 | 109 | 110 | ||
84 | 110 | 111 | ||
85 | 112 | class MatchesFault(MatchesStructure): | ||
86 | 113 | """Match an XML-RPC fault. | ||
87 | 114 | |||
88 | 115 | This can be given either:: | ||
89 | 116 | |||
90 | 117 | - a subclass of LaunchpadFault (matches only the fault code) | ||
91 | 118 | - an instance of Fault (matches the fault code and the fault string | ||
92 | 119 | from this instance exactly) | ||
93 | 120 | """ | ||
94 | 121 | |||
95 | 122 | def __init__(self, expected_fault): | ||
96 | 123 | fault_matchers = {} | ||
97 | 124 | if (isinstance(expected_fault, six.class_types) and | ||
98 | 125 | issubclass(expected_fault, faults.LaunchpadFault)): | ||
99 | 126 | fault_matchers["faultCode"] = Equals(expected_fault.error_code) | ||
100 | 127 | else: | ||
101 | 128 | fault_matchers["faultCode"] = Equals(expected_fault.faultCode) | ||
102 | 129 | fault_string = expected_fault.faultString | ||
103 | 130 | # XXX cjwatson 2019-09-27: InvalidBranchName.faultString is | ||
104 | 131 | # bytes, so we need this to handle that case. Should it be? | ||
105 | 132 | if not isinstance(fault_string, six.text_type): | ||
106 | 133 | fault_string = fault_string.decode("UTF-8") | ||
107 | 134 | fault_matchers["faultString"] = Equals(fault_string) | ||
108 | 135 | super(MatchesFault, self).__init__(**fault_matchers) | ||
109 | 136 | |||
110 | 137 | |||
111 | 111 | class TestGitAPIMixin: | 138 | class TestGitAPIMixin: |
112 | 112 | """Helper methods for `IGitAPI` tests, and security-relevant tests.""" | 139 | """Helper methods for `IGitAPI` tests, and security-relevant tests.""" |
113 | 113 | 140 | ||
114 | 114 | def setUp(self): | 141 | def setUp(self): |
115 | 115 | super(TestGitAPIMixin, self).setUp() | 142 | super(TestGitAPIMixin, self).setUp() |
117 | 116 | self.git_api = GitAPI(None, None) | 143 | self.git_api = xmlrpc_client.ServerProxy( |
118 | 144 | "http://xmlrpc-private.launchpad.test:8087/git", | ||
119 | 145 | transport=XMLRPCTestTransport()) | ||
120 | 117 | self.hosting_fixture = self.useFixture(GitHostingFixture()) | 146 | self.hosting_fixture = self.useFixture(GitHostingFixture()) |
121 | 118 | self.repository_set = getUtility(IGitRepositorySet) | 147 | self.repository_set = getUtility(IGitRepositorySet) |
122 | 119 | 148 | ||
123 | 149 | def assertFault(self, expected_fault, func, *args, **kwargs): | ||
124 | 150 | """Assert that a call raises the expected fault.""" | ||
125 | 151 | fault = self.assertRaises(xmlrpc_client.Fault, func, *args, **kwargs) | ||
126 | 152 | self.assertThat(fault, MatchesFault(expected_fault)) | ||
127 | 153 | return fault | ||
128 | 154 | |||
129 | 120 | def assertGitRepositoryNotFound(self, requester, path, permission="read", | 155 | def assertGitRepositoryNotFound(self, requester, path, permission="read", |
130 | 121 | can_authenticate=False, macaroon_raw=None): | 156 | can_authenticate=False, macaroon_raw=None): |
131 | 122 | """Assert that the given path cannot be translated.""" | 157 | """Assert that the given path cannot be translated.""" |
132 | 123 | auth_params = _make_auth_params( | 158 | auth_params = _make_auth_params( |
133 | 124 | requester, can_authenticate=can_authenticate, | 159 | requester, can_authenticate=can_authenticate, |
134 | 125 | macaroon_raw=macaroon_raw) | 160 | macaroon_raw=macaroon_raw) |
138 | 126 | fault = self.git_api.translatePath(path, permission, auth_params) | 161 | self.assertFault( |
139 | 127 | self.assertEqual( | 162 | faults.GitRepositoryNotFound(path.strip("/")), |
140 | 128 | faults.GitRepositoryNotFound(path.strip("/")), fault) | 163 | self.git_api.translatePath, path, permission, auth_params) |
141 | 129 | 164 | ||
142 | 130 | def assertPermissionDenied(self, requester, path, | 165 | def assertPermissionDenied(self, requester, path, |
143 | 131 | message="Permission denied.", | 166 | message="Permission denied.", |
144 | @@ -135,8 +170,9 @@ | |||
145 | 135 | auth_params = _make_auth_params( | 170 | auth_params = _make_auth_params( |
146 | 136 | requester, can_authenticate=can_authenticate, | 171 | requester, can_authenticate=can_authenticate, |
147 | 137 | macaroon_raw=macaroon_raw) | 172 | macaroon_raw=macaroon_raw) |
150 | 138 | fault = self.git_api.translatePath(path, permission, auth_params) | 173 | self.assertFault( |
151 | 139 | self.assertEqual(faults.PermissionDenied(message), fault) | 174 | faults.PermissionDenied(message), |
152 | 175 | self.git_api.translatePath, path, permission, auth_params) | ||
153 | 140 | 176 | ||
154 | 141 | def assertUnauthorized(self, requester, path, | 177 | def assertUnauthorized(self, requester, path, |
155 | 142 | message="Authorisation required.", | 178 | message="Authorisation required.", |
156 | @@ -146,16 +182,18 @@ | |||
157 | 146 | auth_params = _make_auth_params( | 182 | auth_params = _make_auth_params( |
158 | 147 | requester, can_authenticate=can_authenticate, | 183 | requester, can_authenticate=can_authenticate, |
159 | 148 | macaroon_raw=macaroon_raw) | 184 | macaroon_raw=macaroon_raw) |
162 | 149 | fault = self.git_api.translatePath(path, permission, auth_params) | 185 | self.assertFault( |
163 | 150 | self.assertEqual(faults.Unauthorized(message), fault) | 186 | faults.Unauthorized(message), |
164 | 187 | self.git_api.translatePath, path, permission, auth_params) | ||
165 | 151 | 188 | ||
166 | 152 | def assertNotFound(self, requester, path, message, permission="read", | 189 | def assertNotFound(self, requester, path, message, permission="read", |
167 | 153 | can_authenticate=False): | 190 | can_authenticate=False): |
168 | 154 | """Assert that looking at the given path returns NotFound.""" | 191 | """Assert that looking at the given path returns NotFound.""" |
169 | 155 | auth_params = _make_auth_params( | 192 | auth_params = _make_auth_params( |
170 | 156 | requester, can_authenticate=can_authenticate) | 193 | requester, can_authenticate=can_authenticate) |
173 | 157 | fault = self.git_api.translatePath(path, permission, auth_params) | 194 | self.assertFault( |
174 | 158 | self.assertEqual(faults.NotFound(message), fault) | 195 | faults.NotFound(message), |
175 | 196 | self.git_api.translatePath, path, permission, auth_params) | ||
176 | 159 | 197 | ||
177 | 160 | def assertInvalidSourcePackageName(self, requester, path, name, | 198 | def assertInvalidSourcePackageName(self, requester, path, name, |
178 | 161 | permission="read", | 199 | permission="read", |
179 | @@ -164,24 +202,27 @@ | |||
180 | 164 | InvalidSourcePackageName.""" | 202 | InvalidSourcePackageName.""" |
181 | 165 | auth_params = _make_auth_params( | 203 | auth_params = _make_auth_params( |
182 | 166 | requester, can_authenticate=can_authenticate) | 204 | requester, can_authenticate=can_authenticate) |
185 | 167 | fault = self.git_api.translatePath(path, permission, auth_params) | 205 | self.assertFault( |
186 | 168 | self.assertEqual(faults.InvalidSourcePackageName(name), fault) | 206 | faults.InvalidSourcePackageName(name), |
187 | 207 | self.git_api.translatePath, path, permission, auth_params) | ||
188 | 169 | 208 | ||
189 | 170 | def assertInvalidBranchName(self, requester, path, message, | 209 | def assertInvalidBranchName(self, requester, path, message, |
190 | 171 | permission="read", can_authenticate=False): | 210 | permission="read", can_authenticate=False): |
191 | 172 | """Assert that looking at the given path returns InvalidBranchName.""" | 211 | """Assert that looking at the given path returns InvalidBranchName.""" |
192 | 173 | auth_params = _make_auth_params( | 212 | auth_params = _make_auth_params( |
193 | 174 | requester, can_authenticate=can_authenticate) | 213 | requester, can_authenticate=can_authenticate) |
196 | 175 | fault = self.git_api.translatePath(path, permission, auth_params) | 214 | self.assertFault( |
197 | 176 | self.assertEqual(faults.InvalidBranchName(Exception(message)), fault) | 215 | faults.InvalidBranchName(Exception(message)), |
198 | 216 | self.git_api.translatePath, path, permission, auth_params) | ||
199 | 177 | 217 | ||
200 | 178 | def assertOopsOccurred(self, requester, path, | 218 | def assertOopsOccurred(self, requester, path, |
201 | 179 | permission="read", can_authenticate=False): | 219 | permission="read", can_authenticate=False): |
202 | 180 | """Assert that looking at the given path OOPSes.""" | 220 | """Assert that looking at the given path OOPSes.""" |
203 | 181 | auth_params = _make_auth_params( | 221 | auth_params = _make_auth_params( |
204 | 182 | requester, can_authenticate=can_authenticate) | 222 | requester, can_authenticate=can_authenticate) |
207 | 183 | fault = self.git_api.translatePath(path, permission, auth_params) | 223 | fault = self.assertFault( |
208 | 184 | self.assertIsInstance(fault, faults.OopsOccurred) | 224 | faults.OopsOccurred, |
209 | 225 | self.git_api.translatePath, path, permission, auth_params) | ||
210 | 185 | prefix = ( | 226 | prefix = ( |
211 | 186 | "An unexpected error has occurred while creating a Git " | 227 | "An unexpected error has occurred while creating a Git " |
212 | 187 | "repository. Please report a Launchpad bug and quote: ") | 228 | "repository. Please report a Launchpad bug and quote: ") |
213 | @@ -551,10 +592,10 @@ | |||
214 | 551 | 592 | ||
215 | 552 | def test_checkRefPermissions_nonexistent_repository(self): | 593 | def test_checkRefPermissions_nonexistent_repository(self): |
216 | 553 | requester = self.factory.makePerson() | 594 | requester = self.factory.makePerson() |
218 | 554 | self.assertEqual( | 595 | self.assertFault( |
219 | 555 | faults.GitRepositoryNotFound("nonexistent"), | 596 | faults.GitRepositoryNotFound("nonexistent"), |
222 | 556 | self.git_api.checkRefPermissions( | 597 | self.git_api.checkRefPermissions, |
223 | 557 | "nonexistent", [], {"uid": requester.id})) | 598 | "nonexistent", [], {"uid": requester.id}) |
224 | 558 | 599 | ||
225 | 559 | 600 | ||
226 | 560 | class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory): | 601 | class TestGitAPI(TestGitAPIMixin, TestCaseWithFactory): |
227 | @@ -1136,8 +1177,7 @@ | |||
228 | 1136 | def test_notify_missing_repository(self): | 1177 | def test_notify_missing_repository(self): |
229 | 1137 | # A notify call on a non-existent repository returns a fault and | 1178 | # A notify call on a non-existent repository returns a fault and |
230 | 1138 | # does not create a job. | 1179 | # does not create a job. |
233 | 1139 | fault = self.git_api.notify("10000") | 1180 | self.assertFault(faults.NotFound, self.git_api.notify, "10000") |
232 | 1140 | self.assertIsInstance(fault, faults.NotFound) | ||
234 | 1141 | job_source = getUtility(IGitRefScanJobSource) | 1181 | job_source = getUtility(IGitRefScanJobSource) |
235 | 1142 | self.assertEqual([], list(job_source.iterReady())) | 1182 | self.assertEqual([], list(job_source.iterReady())) |
236 | 1143 | 1183 | ||
237 | @@ -1153,9 +1193,9 @@ | |||
238 | 1153 | self.assertEqual(repository, job.repository) | 1193 | self.assertEqual(repository, job.repository) |
239 | 1154 | 1194 | ||
240 | 1155 | def test_authenticateWithPassword(self): | 1195 | def test_authenticateWithPassword(self): |
244 | 1156 | self.assertIsInstance( | 1196 | self.assertFault( |
245 | 1157 | self.git_api.authenticateWithPassword('foo', 'bar'), | 1197 | faults.Unauthorized, |
246 | 1158 | faults.Unauthorized) | 1198 | self.git_api.authenticateWithPassword, "foo", "bar") |
247 | 1159 | 1199 | ||
248 | 1160 | def test_authenticateWithPassword_code_import(self): | 1200 | def test_authenticateWithPassword_code_import(self): |
249 | 1161 | self.pushConfig( | 1201 | self.pushConfig( |
250 | @@ -1170,13 +1210,13 @@ | |||
251 | 1170 | {"macaroon": macaroon.serialize(), "user": "+launchpad-services"}, | 1210 | {"macaroon": macaroon.serialize(), "user": "+launchpad-services"}, |
252 | 1171 | self.git_api.authenticateWithPassword("", macaroon.serialize())) | 1211 | self.git_api.authenticateWithPassword("", macaroon.serialize())) |
253 | 1172 | other_macaroon = Macaroon(identifier="another", key="another-secret") | 1212 | other_macaroon = Macaroon(identifier="another", key="another-secret") |
261 | 1173 | self.assertIsInstance( | 1213 | self.assertFault( |
262 | 1174 | self.git_api.authenticateWithPassword( | 1214 | faults.Unauthorized, |
263 | 1175 | "", other_macaroon.serialize()), | 1215 | self.git_api.authenticateWithPassword, |
264 | 1176 | faults.Unauthorized) | 1216 | "", other_macaroon.serialize()) |
265 | 1177 | self.assertIsInstance( | 1217 | self.assertFault( |
266 | 1178 | self.git_api.authenticateWithPassword("", "nonsense"), | 1218 | faults.Unauthorized, |
267 | 1179 | faults.Unauthorized) | 1219 | self.git_api.authenticateWithPassword, "", "nonsense") |
268 | 1180 | 1220 | ||
269 | 1181 | def test_authenticateWithPassword_private_snap_build(self): | 1221 | def test_authenticateWithPassword_private_snap_build(self): |
270 | 1182 | self.useFixture(FeatureFixture(SNAP_TESTING_FLAGS)) | 1222 | self.useFixture(FeatureFixture(SNAP_TESTING_FLAGS)) |
271 | @@ -1193,13 +1233,13 @@ | |||
272 | 1193 | {"macaroon": macaroon.serialize(), "user": "+launchpad-services"}, | 1233 | {"macaroon": macaroon.serialize(), "user": "+launchpad-services"}, |
273 | 1194 | self.git_api.authenticateWithPassword("", macaroon.serialize())) | 1234 | self.git_api.authenticateWithPassword("", macaroon.serialize())) |
274 | 1195 | other_macaroon = Macaroon(identifier="another", key="another-secret") | 1235 | other_macaroon = Macaroon(identifier="another", key="another-secret") |
282 | 1196 | self.assertIsInstance( | 1236 | self.assertFault( |
283 | 1197 | self.git_api.authenticateWithPassword( | 1237 | faults.Unauthorized, |
284 | 1198 | "", other_macaroon.serialize()), | 1238 | self.git_api.authenticateWithPassword, |
285 | 1199 | faults.Unauthorized) | 1239 | "", other_macaroon.serialize()) |
286 | 1200 | self.assertIsInstance( | 1240 | self.assertFault( |
287 | 1201 | self.git_api.authenticateWithPassword("", "nonsense"), | 1241 | faults.Unauthorized, |
288 | 1202 | faults.Unauthorized) | 1242 | self.git_api.authenticateWithPassword, "", "nonsense") |
289 | 1203 | 1243 | ||
290 | 1204 | def test_authenticateWithPassword_user_macaroon(self): | 1244 | def test_authenticateWithPassword_user_macaroon(self): |
291 | 1205 | # A user with a suitable macaroon can authenticate using it, in | 1245 | # A user with a suitable macaroon can authenticate using it, in |
292 | @@ -1214,21 +1254,21 @@ | |||
293 | 1214 | {"macaroon": macaroon.serialize(), "uid": requester.id}, | 1254 | {"macaroon": macaroon.serialize(), "uid": requester.id}, |
294 | 1215 | self.git_api.authenticateWithPassword( | 1255 | self.git_api.authenticateWithPassword( |
295 | 1216 | requester.name, macaroon.serialize())) | 1256 | requester.name, macaroon.serialize())) |
303 | 1217 | self.assertIsInstance( | 1257 | self.assertFault( |
304 | 1218 | self.git_api.authenticateWithPassword("", macaroon.serialize()), | 1258 | faults.Unauthorized, |
305 | 1219 | faults.Unauthorized) | 1259 | self.git_api.authenticateWithPassword, "", macaroon.serialize()) |
306 | 1220 | self.assertIsInstance( | 1260 | self.assertFault( |
307 | 1221 | self.git_api.authenticateWithPassword( | 1261 | faults.Unauthorized, |
308 | 1222 | "nonexistent", macaroon.serialize()), | 1262 | self.git_api.authenticateWithPassword, |
309 | 1223 | faults.Unauthorized) | 1263 | "nonexistent", macaroon.serialize()) |
310 | 1224 | other_macaroon = Macaroon(identifier="another", key="another-secret") | 1264 | other_macaroon = Macaroon(identifier="another", key="another-secret") |
318 | 1225 | self.assertIsInstance( | 1265 | self.assertFault( |
319 | 1226 | self.git_api.authenticateWithPassword( | 1266 | faults.Unauthorized, |
320 | 1227 | requester.name, other_macaroon.serialize()), | 1267 | self.git_api.authenticateWithPassword, |
321 | 1228 | faults.Unauthorized) | 1268 | requester.name, other_macaroon.serialize()) |
322 | 1229 | self.assertIsInstance( | 1269 | self.assertFault( |
323 | 1230 | self.git_api.authenticateWithPassword(requester.name, "nonsense"), | 1270 | faults.Unauthorized, |
324 | 1231 | faults.Unauthorized) | 1271 | self.git_api.authenticateWithPassword, requester.name, "nonsense") |
325 | 1232 | 1272 | ||
326 | 1233 | def test_authenticateWithPassword_user_mismatch(self): | 1273 | def test_authenticateWithPassword_user_mismatch(self): |
327 | 1234 | # authenticateWithPassword refuses macaroons in the case where the | 1274 | # authenticateWithPassword refuses macaroons in the case where the |
328 | @@ -1267,10 +1307,10 @@ | |||
329 | 1267 | name = ( | 1307 | name = ( |
330 | 1268 | requester if requester == LAUNCHPAD_SERVICES | 1308 | requester if requester == LAUNCHPAD_SERVICES |
331 | 1269 | else requester.name) | 1309 | else requester.name) |
336 | 1270 | self.assertIsInstance( | 1310 | self.assertFault( |
337 | 1271 | self.git_api.authenticateWithPassword( | 1311 | faults.Unauthorized, |
338 | 1272 | name, macaroon.serialize()), | 1312 | self.git_api.authenticateWithPassword, |
339 | 1273 | faults.Unauthorized) | 1313 | name, macaroon.serialize()) |
340 | 1274 | 1314 | ||
341 | 1275 | def test_checkRefPermissions_code_import(self): | 1315 | def test_checkRefPermissions_code_import(self): |
342 | 1276 | # A code import worker with a suitable macaroon has repository owner | 1316 | # A code import worker with a suitable macaroon has repository owner |
Looks good to me!