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