blob: 9267f1d13deb03bda7dc2ec0d989279d29206bea [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2020 The Chromium Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style
3# license that can be found in the LICENSE file or at
4# https://developers.google.com/open-source/licenses/bsd
5
6from __future__ import print_function
7from __future__ import division
8from __future__ import absolute_import
9
10from google.protobuf import empty_pb2
11
12from api import resource_name_converters as rnc
13from api.v3 import api_constants
14from api.v3 import monorail_servicer
15from api.v3 import paginator
16from api.v3.api_proto import projects_pb2
17from api.v3.api_proto import projects_prpc_pb2
18from businesslogic import work_env
19
20
21class ProjectsServicer(monorail_servicer.MonorailServicer):
22 """Handle API requests related to Project objects.
23 Each API request is implemented with a method as defined in the
24 .proto file. Each method does any request-specific validation, uses work_env
25 to safely operate on business objects, and returns a response proto.
26 """
27
28 DESCRIPTION = projects_prpc_pb2.ProjectsServiceDescription
29
30 @monorail_servicer.PRPCMethod
31 def ListIssueTemplates(self, mc, request):
32 # type: (MonorailContext, ListIssueTemplatesRequest) ->
33 # ListIssueTemplatesResponse
34 """pRPC API method that implements ListIssueTemplates.
35
36 Raises:
37 InputException if the request.parent is invalid.
38 NoSuchProjectException if no project exists with the given name.
39 """
40 project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)
41
42 with work_env.WorkEnv(mc, self.services) as we:
43 # TODO(crbug/monorail/7614): Eliminate the need to do this lookup.
44 project = we.GetProject(project_id)
45 mc.LookupLoggedInUserPerms(project)
46 templates = we.ListProjectTemplates(project_id)
47
48 return projects_pb2.ListIssueTemplatesResponse(
49 templates=self.converter.ConvertIssueTemplates(project_id, templates))
50
51 @monorail_servicer.PRPCMethod
Adrià Vilanova Martínezf5e10392021-12-07 22:55:40 +010052 def GetComponentDef(self, mc, request):
53 # type: (MonorailContext, GetComponentDefRequest) ->
54 # ComponentDef
55 """pRPC API method that implements GetComponentDef.
56
57 Raises:
58 InputException if the request.parent is invalid.
59 NoSuchProjectException if the parent project is not found.
60 """
61 project_id, component_id = rnc.IngestComponentDefNames(
62 mc.cnxn, [request.name], self.services)[0]
63
64 with work_env.WorkEnv(mc, self.services) as we:
65 # TODO(crbug/monorail/7614): Eliminate the need to do this lookup.
66 project = we.GetProject(project_id)
67 mc.LookupLoggedInUserPerms(project)
68
69 component_def = we.GetComponentDef(project_id, component_id)
70 api_component_def = self.converter.ConvertComponentDef(component_def)
71
72 return api_component_def
73
74 @monorail_servicer.PRPCMethod
Copybara854996b2021-09-07 19:36:02 +000075 def ListComponentDefs(self, mc, request):
76 # type: (MonorailContext, ListComponentDefsRequest) ->
77 # ListComponentDefsResponse
78 """pRPC API method that implements ListComponentDefs.
79
80 Raises:
81 InputException if the request.parent is invalid.
82 NoSuchProjectException if the parent project is not found.
83 """
84 project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)
85
86 with work_env.WorkEnv(mc, self.services) as we:
87 # TODO(crbug/monorail/7614): Eliminate the need to do this lookup.
88 project = we.GetProject(project_id)
89 mc.LookupLoggedInUserPerms(project)
90
91 page_size = paginator.CoercePageSize(
92 request.page_size, api_constants.MAX_COMPONENTS_PER_PAGE)
93 pager = paginator.Paginator(
94 parent=request.parent, page_size=page_size)
95 list_result = we.ListComponentDefs(
96 project_id, page_size, pager.GetStart(request.page_token))
97
98 api_component_defs = self.converter.ConvertComponentDefs(
99 list_result.items, project_id)
100
101 return projects_pb2.ListComponentDefsResponse(
102 component_defs=api_component_defs,
103 next_page_token=pager.GenerateNextPageToken(list_result.next_start))
104
105 @monorail_servicer.PRPCMethod
106 def CreateComponentDef(self, mc, request):
107 # type: (MonorailContext, CreateComponentDefRequest) ->
108 # ComponentDef
109 """pRPC API method that implements CreateComponentDef.
110
111 Raises:
112 InputException if the request is invalid.
113 NoSuchUserException if any given component admins or ccs do not exist.
114 NoSuchProjectException if the parent project does not exist.
115 PermissionException if the requester is not allowed to create
116 this component.
117 """
118 project_id = rnc.IngestProjectName(mc.cnxn, request.parent, self.services)
119 admin_ids = rnc.IngestUserNames(
120 mc.cnxn, request.component_def.admins, self.services)
121 cc_ids = rnc.IngestUserNames(
122 mc.cnxn, request.component_def.ccs, self.services)
123
124 with work_env.WorkEnv(mc, self.services) as we:
125 component_def = we.CreateComponentDef(
126 project_id, request.component_def.value,
127 request.component_def.docstring, admin_ids, cc_ids,
128 request.component_def.labels)
129
130 return self.converter.ConvertComponentDef(component_def)
131
132 @monorail_servicer.PRPCMethod
133 def DeleteComponentDef(self, mc, request):
134 # type: (MonorailContext, DeleteComponentDefRequest) -> Empty
135 """pRPC API method that implements DeleteComponentDef.
136
137 Raises:
138 InputException if the request in invalid.
139 NoSuchComponentException if the component does not exist.
140 PermissionException if the requester is not allowed to delete
141 this component.
142 NoSuchProjectException if the parent project does not exist.
143 """
144 project_id, component_id = rnc.IngestComponentDefNames(
145 mc.cnxn, [request.name], self.services)[0]
146
147 with work_env.WorkEnv(mc, self.services) as we:
148 we.DeleteComponentDef(project_id, component_id)
149
150 return empty_pb2.Empty()
151
152 @monorail_servicer.PRPCMethod
153 def ListProjects(self, mc, _):
154 # type: (MonorailContext, ListProjectsRequest) -> ListProjectsResponse
155 """pRPC API method that implements ListProjects.
156
157 Raises:
158 InputException if the request.page_token is invalid or the request does
159 not match the previous request that provided the given page_token.
160 """
161 with work_env.WorkEnv(mc, self.services) as we:
162 # NOTE(crbug/monorail/7614): Until the referenced cleanup is complete,
163 # all servicer methods that are scoped to a single Project need to call
164 # mc.LookupLoggedInUserPerms.
165 # This method does not because it may be scoped to multiple projects.
166 allowed_project_ids = we.ListProjects()
167 projects_dict = we.GetProjects(allowed_project_ids)
168 projects = [projects_dict[proj_id] for proj_id in allowed_project_ids]
169
170 # TODO(crbug.com/monorail/7505): Add pagination logic.
171 return projects_pb2.ListProjectsResponse(
172 projects=self.converter.ConvertProjects(projects))