blob: 31ec0868afc202cb654b2c3eb4c618b0a4eea8c5 [file] [log] [blame]
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +01001# Copyright 2018 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
9import logging
10
11from api import monorail_servicer
12from api import converters
13from api.api_proto import common_pb2
14from api.api_proto import features_pb2
15from api.api_proto import features_prpc_pb2
16from businesslogic import work_env
Copybara854996b2021-09-07 19:36:02 +000017from features import features_bizobj
18from framework import exceptions
19from framework import framework_bizobj
20from framework import framework_views
21from framework import paginate
22from framework import permissions
23from services import features_svc
24from tracker import tracker_bizobj
25
26
27class FeaturesServicer(monorail_servicer.MonorailServicer):
28 """Handle API requests related to Features objects.
29
30 Each API request is implemented with a method as defined in the .proto
31 file that does any request-specific validation, uses work_env to
32 safely operate on business objects, and returns a response proto.
33 """
34
35 DESCRIPTION = features_prpc_pb2.FeaturesServiceDescription
36
37 @monorail_servicer.PRPCMethod
38 def ListHotlistsByUser(self, mc, request):
39 """Return the hotlists for the given user."""
40 user_id = converters.IngestUserRef(
41 mc.cnxn, request.user, self.services.user)
42
43 with work_env.WorkEnv(mc, self.services) as we:
44 mc.LookupLoggedInUserPerms(None)
45 hotlists = we.ListHotlistsByUser(user_id)
46
47 with mc.profiler.Phase('making user views'):
48 users_involved = features_bizobj.UsersInvolvedInHotlists(hotlists)
49 users_by_id = framework_views.MakeAllUserViews(
50 mc.cnxn, self.services.user, users_involved)
51 framework_views.RevealAllEmailsToMembers(
52 mc.cnxn, self.services, mc.auth, users_by_id)
53
54 converted_hotlists = [
55 converters.ConvertHotlist(hotlist, users_by_id)
56 for hotlist in hotlists]
57
58 result = features_pb2.ListHotlistsByUserResponse(
59 hotlists=converted_hotlists)
60
61 return result
62
63 @monorail_servicer.PRPCMethod
64 def ListHotlistsByIssue(self, mc, request):
Adrià Vilanova Martínezf19ea432024-01-23 20:20:52 +010065 # type: (MonorailConnection, mrproto.features.ListHotlistsByIssueRequest) ->
66 # mrproto.features.ListHotlistsByIssueResponse
Copybara854996b2021-09-07 19:36:02 +000067 """Return the hotlists the given issue is part of."""
68 issue_id = converters.IngestIssueRefs(
69 mc.cnxn, [request.issue], self.services)[0]
70
71 with work_env.WorkEnv(mc, self.services) as we:
72 project = we.GetProjectByName(request.issue.project_name)
73 mc.LookupLoggedInUserPerms(project)
74 hotlists = we.ListHotlistsByIssue(issue_id)
75
76 # Reduce spam by only showing hotlists that belong to a project member.
77 project_hotlists = [
78 hotlist for hotlist in hotlists if framework_bizobj.UserIsInProject(
79 project, set(hotlist.owner_ids + hotlist.editor_ids)) or
80 features_bizobj.UserIsInHotlist(hotlist, mc.auth.effective_ids)
81 ]
82 if project_hotlists and len(hotlists) / len(project_hotlists) > 10:
83 logging.warning(
84 'Unusual hotlist activity in %s:%s' %
85 (request.issue.project_name, issue_id))
86
87 with mc.profiler.Phase('making user views'):
88 users_involved = features_bizobj.UsersInvolvedInHotlists(project_hotlists)
89 users_by_id = framework_views.MakeAllUserViews(
90 mc.cnxn, self.services.user, users_involved)
91 framework_views.RevealAllEmailsToMembers(
92 mc.cnxn, self.services, mc.auth, users_by_id)
93
94 converted_hotlists = [
95 converters.ConvertHotlist(hotlist, users_by_id)
96 for hotlist in project_hotlists
97 ]
98
99 result = features_pb2.ListHotlistsByIssueResponse(
100 hotlists=converted_hotlists)
101
102 return result
103
104 @monorail_servicer.PRPCMethod
105 def ListRecentlyVisitedHotlists(self, mc, _request):
106 """Return the recently visited hotlists for the logged in user."""
107 with work_env.WorkEnv(mc, self.services) as we:
108 mc.LookupLoggedInUserPerms(None)
109 hotlists = we.ListRecentlyVisitedHotlists()
110
111 with mc.profiler.Phase('making user views'):
112 users_involved = features_bizobj.UsersInvolvedInHotlists(hotlists)
113 users_by_id = framework_views.MakeAllUserViews(
114 mc.cnxn, self.services.user, users_involved)
115 framework_views.RevealAllEmailsToMembers(
116 mc.cnxn, self.services, mc.auth, users_by_id)
117
118 converted_hotlists = [
119 converters.ConvertHotlist(hotlist, users_by_id)
120 for hotlist in hotlists]
121
122 result = features_pb2.ListRecentlyVisitedHotlistsResponse(
123 hotlists=converted_hotlists)
124
125 return result
126
127 @monorail_servicer.PRPCMethod
128 def ListStarredHotlists(self, mc, _request):
129 """Return the starred hotlists for the logged in user."""
130 with work_env.WorkEnv(mc, self.services) as we:
131 mc.LookupLoggedInUserPerms(None)
132 hotlists = we.ListStarredHotlists()
133
134 with mc.profiler.Phase('maknig user views'):
135 users_involved = features_bizobj.UsersInvolvedInHotlists(hotlists)
136 users_by_id = framework_views.MakeAllUserViews(
137 mc.cnxn, self.services.user, users_involved)
138 framework_views.RevealAllEmailsToMembers(
139 mc.cnxn, self.services, mc.auth, users_by_id)
140
141 converted_hotlists = [
142 converters.ConvertHotlist(hotlist, users_by_id)
143 for hotlist in hotlists]
144
145 result = features_pb2.ListStarredHotlistsResponse(
146 hotlists=converted_hotlists)
147
148 return result
149
150 @monorail_servicer.PRPCMethod
151 def GetHotlistStarCount(self, mc, request):
152 """Get the star count for the specified hotlist."""
153 hotlist_id = converters.IngestHotlistRef(
154 mc.cnxn, self.services.user, self.services.features,
155 request.hotlist_ref)
156
157 with work_env.WorkEnv(mc, self.services) as we:
158 mc.LookupLoggedInUserPerms(None)
159 star_count = we.GetHotlistStarCount(hotlist_id)
160
161 result = features_pb2.GetHotlistStarCountResponse(star_count=star_count)
162 return result
163
164 @monorail_servicer.PRPCMethod
165 def StarHotlist(self, mc, request):
166 """Star the specified hotlist."""
167 hotlist_id = converters.IngestHotlistRef(
168 mc.cnxn, self.services.user, self.services.features,
169 request.hotlist_ref)
170
171 with work_env.WorkEnv(mc, self.services) as we:
172 mc.LookupLoggedInUserPerms(None)
173 we.StarHotlist(hotlist_id, request.starred)
174 star_count = we.GetHotlistStarCount(hotlist_id)
175
176 result = features_pb2.StarHotlistResponse(star_count=star_count)
177 return result
178
179 @monorail_servicer.PRPCMethod
180 def GetHotlist(self, mc, request):
181 """Get the Hotlist metadata for the specified hotlist."""
182 hotlist_id = converters.IngestHotlistRef(
183 mc.cnxn, self.services.user, self.services.features,
184 request.hotlist_ref)
185
186 with work_env.WorkEnv(mc, self.services) as we:
187 mc.LookupLoggedInUserPerms(None)
188 hotlist = we.GetHotlist(hotlist_id)
189
190 with mc.profiler.Phase('making user views'):
191 users_involved = features_bizobj.UsersInvolvedInHotlists([hotlist])
192 users_by_id = framework_views.MakeAllUserViews(
193 mc.cnxn, self.services.user, users_involved)
194 framework_views.RevealAllEmailsToMembers(
195 mc.cnxn, self.services, mc.auth, users_by_id)
196
197 converted_hotlist = converters.ConvertHotlist(hotlist, users_by_id)
198 return features_pb2.GetHotlistResponse(hotlist=converted_hotlist)
199
200 @monorail_servicer.PRPCMethod
201 def CreateHotlist(self, mc, request):
202 """Create a new hotlist."""
203 editor_ids = converters.IngestUserRefs(
204 mc.cnxn, request.editor_refs, self.services.user)
205 issue_ids = converters.IngestIssueRefs(
206 mc.cnxn, request.issue_refs, self.services)
207
208 with work_env.WorkEnv(mc, self.services) as we:
209 we.CreateHotlist(
210 request.name, request.summary, request.description, editor_ids,
211 issue_ids, request.is_private, '')
212
213 result = features_pb2.CreateHotlistResponse()
214 return result
215
216 @monorail_servicer.PRPCMethod
217 def CheckHotlistName(self, mc, request):
218 """Check that a hotlist name is valid and not already in use."""
219 with work_env.WorkEnv(mc, self.services) as we:
220 error = we.CheckHotlistName(request.name)
221 result = features_pb2.CheckHotlistNameResponse(error=error)
222 return result
223
224 @monorail_servicer.PRPCMethod
225 def RemoveIssuesFromHotlists(self, mc, request):
226 """Remove the given issues from the given hotlists."""
227 hotlist_ids = converters.IngestHotlistRefs(
228 mc.cnxn, self.services.user, self.services.features,
229 request.hotlist_refs)
230 issue_ids = converters.IngestIssueRefs(
231 mc.cnxn, request.issue_refs, self.services)
232
233 with work_env.WorkEnv(mc, self.services) as we:
234 mc.LookupLoggedInUserPerms(None)
235 we.RemoveIssuesFromHotlists(hotlist_ids, issue_ids)
236
237 result = features_pb2.RemoveIssuesFromHotlistsResponse()
238 return result
239
240 @monorail_servicer.PRPCMethod
241 def AddIssuesToHotlists(self, mc, request):
242 """Add the given issues to the given hotlists."""
243 hotlist_ids = converters.IngestHotlistRefs(
244 mc.cnxn, self.services.user, self.services.features,
245 request.hotlist_refs)
246 issue_ids = converters.IngestIssueRefs(
247 mc.cnxn, request.issue_refs, self.services)
248
249 with work_env.WorkEnv(mc, self.services) as we:
250 mc.LookupLoggedInUserPerms(None)
251 we.AddIssuesToHotlists(hotlist_ids, issue_ids, request.note)
252
253 result = features_pb2.AddIssuesToHotlistsResponse()
254 return result
255
256 @monorail_servicer.PRPCMethod
257 def RerankHotlistIssues(self, mc, request):
258 """Rerank issues in the given hotlist."""
259 hotlist_id = converters.IngestHotlistRef(
260 mc.cnxn, self.services.user, self.services.features,
261 request.hotlist_ref)
262 moved_issue_ids = converters.IngestIssueRefs(
263 mc.cnxn, request.moved_refs, self.services)
264 [target_issue_id] = converters.IngestIssueRefs(
265 mc.cnxn, [request.target_ref], self.services)
266
267 with work_env.WorkEnv(mc, self.services) as we:
268 we.RerankHotlistIssues(
269 hotlist_id, moved_issue_ids, target_issue_id, request.split_above)
270
271 # TODO(jojwang): return updated hotlist items.
272 with mc.profiler.Phase('converting to response objects'):
273 result = features_pb2.RerankHotlistIssuesResponse()
274
275 return result
276
277 @monorail_servicer.PRPCMethod
278 def UpdateHotlistIssueNote(self, mc, request):
279 """Update the note for the given issue in the given hotlist."""
280 hotlist_id = converters.IngestHotlistRef(
281 mc.cnxn, self.services.user, self.services.features,
282 request.hotlist_ref)
283 issue_id = converters.IngestIssueRefs(
284 mc.cnxn, [request.issue_ref], self.services)[0]
285
286 with work_env.WorkEnv(mc, self.services) as we:
287 project = we.GetProjectByName(request.issue_ref.project_name)
288 mc.LookupLoggedInUserPerms(project)
289 we.UpdateHotlistIssueNote(hotlist_id, issue_id, request.note)
290
291 result = features_pb2.UpdateHotlistIssueNoteResponse()
292 return result
293
294 @monorail_servicer.PRPCMethod
295 def DeleteHotlist(self, mc, request):
296 """Delete the given hotlist"""
297 hotlist_id = converters.IngestHotlistRef(
298 mc.cnxn, self.services.user, self.services.features,
299 request.hotlist_ref)
300
301 with work_env.WorkEnv(mc, self.services) as we:
302 we.DeleteHotlist(hotlist_id)
303
304 return features_pb2.DeleteHotlistResponse()