OLD | NEW |
1 # Copyright 2015 The Swarming Authors. All rights reserved. | 1 # Copyright 2015 The Swarming Authors. All rights reserved. |
2 # Use of this source code is governed by the Apache v2.0 license that can be | 2 # Use of this source code is governed by the Apache v2.0 license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 import logging | 5 import logging |
6 | 6 |
7 from protorpc import messages | 7 from protorpc import messages |
8 from protorpc import message_types | 8 from protorpc import message_types |
9 from protorpc import remote | 9 from protorpc import remote |
10 import endpoints | 10 import endpoints |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
48 content = messages.BytesField(4) | 48 content = messages.BytesField(4) |
49 configs = messages.MessageField(ConfigEntry, 1, repeated=True) | 49 configs = messages.MessageField(ConfigEntry, 1, repeated=True) |
50 | 50 |
51 | 51 |
52 @auth.endpoints_api(name='config', version='v1', title='Configuration Service') | 52 @auth.endpoints_api(name='config', version='v1', title='Configuration Service') |
53 class ConfigApi(remote.Service): | 53 class ConfigApi(remote.Service): |
54 """API to access configurations.""" | 54 """API to access configurations.""" |
55 | 55 |
56 def can_read_config_set(self, config_set): | 56 def can_read_config_set(self, config_set): |
57 try: | 57 try: |
58 return acl.can_read_config_set( | 58 return acl.can_read_config_set(config_set) |
59 config_set, headers=self.request_state.headers) | |
60 except ValueError: | 59 except ValueError: |
61 raise endpoints.BadRequestException('Invalid config set: %s' % config_set) | 60 raise endpoints.BadRequestException('Invalid config set: %s' % config_set) |
62 | 61 |
63 ############################################################################## | 62 ############################################################################## |
64 # endpoint: get_mapping | 63 # endpoint: get_mapping |
65 | 64 |
66 class GetMappingResponseMessage(messages.Message): | 65 class GetMappingResponseMessage(messages.Message): |
67 class Mapping(messages.Message): | 66 class Mapping(messages.Message): |
68 config_set = messages.StringField(1, required=True) | 67 config_set = messages.StringField(1, required=True) |
69 location = messages.StringField(2) | 68 location = messages.StringField(2) |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
178 @auth.endpoints_method( | 177 @auth.endpoints_method( |
179 message_types.VoidMessage, | 178 message_types.VoidMessage, |
180 GetProjectsResponseMessage, | 179 GetProjectsResponseMessage, |
181 http_method='GET', | 180 http_method='GET', |
182 path='projects') | 181 path='projects') |
183 def get_projects(self, request): # pylint: disable=W0613 | 182 def get_projects(self, request): # pylint: disable=W0613 |
184 """Gets list of registered projects. | 183 """Gets list of registered projects. |
185 | 184 |
186 The project list is stored in services/luci-config:projects.cfg. | 185 The project list is stored in services/luci-config:projects.cfg. |
187 """ | 186 """ |
188 if not acl.can_read_project_list(): | 187 return self.GetProjectsResponseMessage( |
189 raise endpoints.ForbiddenException() | 188 projects=[p for p in get_projects() if acl.has_project_access(p.id)], |
190 return self.GetProjectsResponseMessage(projects=get_projects()) | 189 ) |
191 | 190 |
192 ############################################################################## | 191 ############################################################################## |
193 # endpoint: get_refs | 192 # endpoint: get_refs |
194 | 193 |
195 class GetRefsResponseMessage(messages.Message): | 194 class GetRefsResponseMessage(messages.Message): |
196 class Ref(messages.Message): | 195 class Ref(messages.Message): |
197 name = messages.StringField(1) | 196 name = messages.StringField(1) |
198 refs = messages.MessageField(Ref, 1, repeated=True) | 197 refs = messages.MessageField(Ref, 1, repeated=True) |
199 | 198 |
200 @auth.endpoints_method( | 199 @auth.endpoints_method( |
201 endpoints.ResourceContainer( | 200 endpoints.ResourceContainer( |
202 message_types.VoidMessage, | 201 message_types.VoidMessage, |
203 project_id=messages.StringField(1, required=True), | 202 project_id=messages.StringField(1, required=True), |
204 ), | 203 ), |
205 GetRefsResponseMessage, | 204 GetRefsResponseMessage, |
206 http_method='GET', | 205 http_method='GET', |
207 path='projects/{project_id}/refs') | 206 path='projects/{project_id}/refs') |
208 def get_refs(self, request): | 207 def get_refs(self, request): |
209 """Gets list of refs of a project.""" | 208 """Gets list of refs of a project.""" |
210 if not acl.can_read_project_config(request.project_id): | 209 if not acl.has_project_access(request.project_id): |
211 raise endpoints.NotFoundException() | 210 raise endpoints.NotFoundException() |
212 ref_names = get_ref_names(request.project_id) | 211 ref_names = get_ref_names(request.project_id) |
213 if ref_names is None: | 212 if ref_names is None: |
214 # Project not found | 213 # Project not found |
215 raise endpoints.NotFoundException() | 214 raise endpoints.NotFoundException() |
216 res = self.GetRefsResponseMessage() | 215 res = self.GetRefsResponseMessage() |
217 res.refs = [res.Ref(name=ref) for ref in ref_names] | 216 res.refs = [res.Ref(name=ref) for ref in ref_names] |
218 return res | 217 return res |
219 | 218 |
220 ############################################################################## | 219 ############################################################################## |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
297 # Project does not exist | 296 # Project does not exist |
298 return None | 297 return None |
299 return [ref.name for ref in refs] | 298 return [ref.name for ref in refs] |
300 | 299 |
301 | 300 |
302 def get_config_multi(config_sets, path, hashes_only): | 301 def get_config_multi(config_sets, path, hashes_only): |
303 """Returns configs at |path| in all config sets. | 302 """Returns configs at |path| in all config sets. |
304 | 303 |
305 Returns empty config list if requester does not have project access. | 304 Returns empty config list if requester does not have project access. |
306 """ | 305 """ |
307 if not acl.has_project_access(): | |
308 raise endpoints.ForbiddenException() | |
309 | |
310 res = GetConfigMultiResponseMessage() | 306 res = GetConfigMultiResponseMessage() |
| 307 config_sets = filter(acl.can_read_config_set, config_sets) |
311 configs = storage.get_latest_multi_async( | 308 configs = storage.get_latest_multi_async( |
312 config_sets, path, hashes_only).get_result() | 309 config_sets, path, hashes_only).get_result() |
313 for config in configs: | 310 for config in configs: |
314 if not hashes_only and config.get('content') is None: | 311 if not hashes_only and config.get('content') is None: |
315 logging.error( | 312 logging.error( |
316 'Blob %s referenced from %s:%s:%s was not found', | 313 'Blob %s referenced from %s:%s:%s was not found', |
317 config['content_hash'], | 314 config['content_hash'], |
318 config['config_set'], | 315 config['config_set'], |
319 config['revision'], | 316 config['revision'], |
320 path) | 317 path) |
321 continue | 318 continue |
322 res.configs.append(res.ConfigEntry( | 319 res.configs.append(res.ConfigEntry( |
323 config_set=config['config_set'], | 320 config_set=config['config_set'], |
324 revision=config['revision'], | 321 revision=config['revision'], |
325 content_hash=config['content_hash'], | 322 content_hash=config['content_hash'], |
326 content=config.get('content'), | 323 content=config.get('content'), |
327 )) | 324 )) |
328 return res | 325 return res |
329 | 326 |
330 | 327 |
331 def raise_config_not_found(): | 328 def raise_config_not_found(): |
332 raise endpoints.NotFoundException('The requested config is not found') | 329 raise endpoints.NotFoundException('The requested config is not found') |
OLD | NEW |