blob: aa25d18a3edab46096299c98da31ca0ad88123de [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2018 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
6"""Tests for the users servicer."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import unittest
12
13import mox
14from components.prpc import codes
15from components.prpc import context
16from components.prpc import server
17
18from api import users_servicer
19from api.api_proto import common_pb2
20from api.api_proto import users_pb2
21from api.api_proto import user_objects_pb2
22from framework import authdata
23from framework import exceptions
24from framework import monorailcontext
25from framework import permissions
26from proto import project_pb2
27from proto import tracker_pb2
28from proto import user_pb2
29from testing import fake
30from services import service_manager
31
32
33class UsersServicerTest(unittest.TestCase):
34
35 def setUp(self):
36 self.mox = mox.Mox()
37 self.cnxn = fake.MonorailConnection()
38 self.services = service_manager.Services(
39 config=fake.ConfigService(),
40 issue=fake.IssueService(),
41 user=fake.UserService(),
42 user_star=fake.UserStarService(),
43 usergroup=fake.UserGroupService(),
44 project=fake.ProjectService(),
45 project_star=fake.ProjectStarService(),
46 features=fake.FeaturesService())
47 self.project = self.services.project.TestAddProject('proj', project_id=987)
48 self.user = self.services.user.TestAddUser('owner@example.com', 111)
49 self.user_2 = self.services.user.TestAddUser('test2@example.com', 222)
50 self.group1_id = self.services.usergroup.CreateGroup(
51 self.cnxn, self.services, 'group1@test.com', 'anyone')
52 self.group2_id = self.services.usergroup.CreateGroup(
53 self.cnxn, self.services, 'group2@test.com', 'anyone')
54 self.services.usergroup.UpdateMembers(
55 self.cnxn, self.group1_id, [111], 'member')
56 self.services.usergroup.UpdateMembers(
57 self.cnxn, self.group2_id, [222, 111], 'owner')
58 self.users_svcr = users_servicer.UsersServicer(
59 self.services, make_rate_limiter=False)
60 self.prpc_context = context.ServicerContext()
61 self.prpc_context.set_code(codes.StatusCode.OK)
62
63 def tearDown(self):
64 self.mox.UnsetStubs()
65 self.mox.ResetAll()
66
67 def CallWrapped(self, wrapped_handler, *args, **kwargs):
68 return wrapped_handler.wrapped(self.users_svcr, *args, **kwargs)
69
70 def testGetMemberships(self):
71 request = users_pb2.GetMembershipsRequest(
72 user_ref=common_pb2.UserRef(
73 display_name='owner@example.com', user_id=111))
74 mc = monorailcontext.MonorailContext(
75 self.services, cnxn=self.cnxn, requester='owner@example.com')
76
77 response = self.CallWrapped(self.users_svcr.GetMemberships, mc, request)
78 expected_group_refs = [
79 common_pb2.UserRef(
80 display_name='group1@test.com', user_id=self.group1_id),
81 common_pb2.UserRef(
82 display_name='group2@test.com', user_id=self.group2_id)
83 ]
84
85 self.assertItemsEqual(expected_group_refs, response.group_refs)
86
87 def testGetMemberships_NonExistentUser(self):
88 request = users_pb2.GetMembershipsRequest(
89 user_ref=common_pb2.UserRef(
90 display_name='ghost@example.com', user_id=888)
91 )
92
93 mc = monorailcontext.MonorailContext(
94 self.services, cnxn=self.cnxn, requester='')
95
96 with self.assertRaises(exceptions.NoSuchUserException):
97 self.CallWrapped(self.users_svcr.GetMemberships, mc, request)
98
99 def testGetUser(self):
100 """We can get a user by email address."""
101 user_ref = common_pb2.UserRef(display_name='test2@example.com')
102 request = users_pb2.GetUserRequest(user_ref=user_ref)
103 mc = monorailcontext.MonorailContext(
104 self.services, cnxn=self.cnxn, requester='owner@example.com')
105 response = self.CallWrapped(
106 self.users_svcr.GetUser, mc, request)
107 self.assertEqual(response.display_name, 'test2@example.com')
108 self.assertEqual(response.user_id, 222)
109 self.assertFalse(response.is_site_admin)
110
111 self.user_2.is_site_admin = True
112 response = self.CallWrapped(
113 self.users_svcr.GetUser, mc, request)
114 self.assertTrue(response.is_site_admin)
115
116 def testListReferencedUsers(self):
117 """We can get all valid users by email addresses."""
118 request = users_pb2.ListReferencedUsersRequest(
119 # we ignore emails that are empty or belong to non-existent users.
120 user_refs=[
121 common_pb2.UserRef(display_name='test2@example.com'),
122 common_pb2.UserRef(display_name='ghost@example.com'),
123 common_pb2.UserRef(display_name=''),
124 common_pb2.UserRef()])
125 mc = monorailcontext.MonorailContext(
126 self.services, cnxn=self.cnxn, requester='owner@example.com')
127 response = self.CallWrapped(
128 self.users_svcr.ListReferencedUsers, mc, request)
129 self.assertEqual(len(response.users), 1)
130 self.assertEqual(response.users[0].user_id, 222)
131
132 def testListReferencedUsers_Deprecated(self):
133 """We can get all valid users by email addresses."""
134 request = users_pb2.ListReferencedUsersRequest(
135 # we ignore emails that are empty or belong to non-existent users.
136 emails=[
137 'test2@example.com',
138 'ghost@example.com',
139 ''])
140 mc = monorailcontext.MonorailContext(
141 self.services, cnxn=self.cnxn, requester='owner@example.com')
142 response = self.CallWrapped(
143 self.users_svcr.ListReferencedUsers, mc, request)
144 self.assertEqual(len(response.users), 1)
145 self.assertEqual(response.users[0].user_id, 222)
146
147 def CallGetStarCount(self):
148 request = users_pb2.GetUserStarCountRequest(
149 user_ref=common_pb2.UserRef(user_id=222))
150 mc = monorailcontext.MonorailContext(
151 self.services, cnxn=self.cnxn, requester='owner@example.com')
152 response = self.CallWrapped(
153 self.users_svcr.GetUserStarCount, mc, request)
154 return response.star_count
155
156 def CallStar(self, requester='owner@example.com', starred=True):
157 request = users_pb2.StarUserRequest(
158 user_ref=common_pb2.UserRef(user_id=222), starred=starred)
159 mc = monorailcontext.MonorailContext(
160 self.services, cnxn=self.cnxn, requester=requester)
161 response = self.CallWrapped(
162 self.users_svcr.StarUser, mc, request)
163 return response.star_count
164
165 def testStarCount_Normal(self):
166 self.assertEqual(0, self.CallGetStarCount())
167 self.assertEqual(1, self.CallStar())
168 self.assertEqual(1, self.CallGetStarCount())
169
170 def testStarCount_StarTwiceSameUser(self):
171 self.assertEqual(1, self.CallStar())
172 self.assertEqual(1, self.CallStar())
173 self.assertEqual(1, self.CallGetStarCount())
174
175 def testStarCount_StarTwiceDifferentUser(self):
176 self.assertEqual(1, self.CallStar())
177 self.assertEqual(2, self.CallStar(requester='test2@example.com'))
178 self.assertEqual(2, self.CallGetStarCount())
179
180 def testStarCount_RemoveStarTwiceSameUser(self):
181 self.assertEqual(1, self.CallStar())
182 self.assertEqual(1, self.CallGetStarCount())
183
184 self.assertEqual(0, self.CallStar(starred=False))
185 self.assertEqual(0, self.CallStar(starred=False))
186 self.assertEqual(0, self.CallGetStarCount())
187
188 def testStarCount_RemoveStarTwiceDifferentUser(self):
189 self.assertEqual(1, self.CallStar())
190 self.assertEqual(2, self.CallStar(requester='test2@example.com'))
191 self.assertEqual(2, self.CallGetStarCount())
192
193 self.assertEqual(1, self.CallStar(starred=False))
194 self.assertEqual(
195 0, self.CallStar(requester='test2@example.com', starred=False))
196 self.assertEqual(0, self.CallGetStarCount())
197
198 def testSetExpandPermsPreference_KeepOpen(self):
199 request = users_pb2.SetExpandPermsPreferenceRequest(expand_perms=True)
200 mc = monorailcontext.MonorailContext(
201 self.services, cnxn=self.cnxn, requester='owner@example.com')
202 self.CallWrapped(self.users_svcr.SetExpandPermsPreference, mc, request)
203
204 user = self.services.user.GetUser(self.cnxn, self.user.user_id)
205 self.assertTrue(user.keep_people_perms_open)
206
207 def testSetExpandPermsPreference_DontKeepOpen(self):
208 request = users_pb2.SetExpandPermsPreferenceRequest(expand_perms=False)
209 mc = monorailcontext.MonorailContext(
210 self.services, cnxn=self.cnxn, requester='owner@example.com')
211 self.CallWrapped(self.users_svcr.SetExpandPermsPreference, mc, request)
212
213 user = self.services.user.GetUser(self.cnxn, self.user.user_id)
214 self.assertFalse(user.keep_people_perms_open)
215
216 def testGetUserSavedQueries_Anon(self):
217 """Anon has empty saved queries."""
218 request = users_pb2.GetSavedQueriesRequest()
219 mc = monorailcontext.MonorailContext(
220 self.services, cnxn=self.cnxn, requester=None)
221 response = self.CallWrapped(self.users_svcr.GetSavedQueries, mc, request)
222
223 self.assertEqual(0, len(response.saved_queries))
224
225 def testGetUserSavedQueries_Mine(self):
226 """See your own queries."""
227 self.services.features.UpdateUserSavedQueries(self.cnxn, 111, [
228 tracker_pb2.SavedQuery(query_id=101, name='test', query='owner:me'),
229 tracker_pb2.SavedQuery(query_id=202, name='hello', query='world',
230 executes_in_project_ids=[987])
231 ])
232 request = users_pb2.GetUserPrefsRequest()
233 mc = monorailcontext.MonorailContext(
234 self.services, cnxn=self.cnxn, requester='owner@example.com')
235 response = self.CallWrapped(self.users_svcr.GetSavedQueries, mc, request)
236
237 self.assertEqual(2, len(response.saved_queries))
238
239 self.assertEqual('test', response.saved_queries[0].name)
240 self.assertEqual('owner:me', response.saved_queries[0].query)
241 self.assertEqual('hello', response.saved_queries[1].name)
242 self.assertEqual('world', response.saved_queries[1].query)
243 self.assertEqual(['proj'], response.saved_queries[1].project_names)
244
245
246 def testGetUserSavedQueries_Other_Allowed(self):
247 """See other people's queries if you're an admin."""
248 self.services.features.UpdateUserSavedQueries(self.cnxn, 111, [
249 tracker_pb2.SavedQuery(query_id=101, name='test', query='owner:me'),
250 tracker_pb2.SavedQuery(query_id=202, name='hello', query='world',
251 executes_in_project_ids=[987])
252 ])
253 self.user_2.is_site_admin = True
254
255 request = users_pb2.GetSavedQueriesRequest()
256 request.user_ref.display_name = 'owner@example.com'
257
258 mc = monorailcontext.MonorailContext(
259 self.services, cnxn=self.cnxn, requester='test2@example.com')
260
261 response = self.CallWrapped(self.users_svcr.GetSavedQueries, mc, request)
262
263 self.assertEqual(2, len(response.saved_queries))
264
265 self.assertEqual('test', response.saved_queries[0].name)
266 self.assertEqual('owner:me', response.saved_queries[0].query)
267 self.assertEqual('hello', response.saved_queries[1].name)
268 self.assertEqual('world', response.saved_queries[1].query)
269 self.assertEqual(['proj'], response.saved_queries[1].project_names)
270
271 def testGetUserSavedQueries_Other_Denied(self):
272 """Can't see other people's queries unless you're an admin."""
273 self.services.features.UpdateUserSavedQueries(self.cnxn, 111, [
274 tracker_pb2.SavedQuery(query_id=101, name='test', query='owner:me'),
275 tracker_pb2.SavedQuery(query_id=202, name='hello', query='world',
276 executes_in_project_ids=[987])
277 ])
278
279 request = users_pb2.GetSavedQueriesRequest()
280 request.user_ref.display_name = 'owner@example.com'
281
282 mc = monorailcontext.MonorailContext(
283 self.services, cnxn=self.cnxn, requester='test2@example.com')
284
285 with self.assertRaises(permissions.PermissionException):
286 self.CallWrapped(self.users_svcr.GetSavedQueries, mc, request)
287
288 def testGetUserPrefs_Anon(self):
289 """Anon always has empty prefs."""
290 request = users_pb2.GetUserPrefsRequest()
291 mc = monorailcontext.MonorailContext(
292 self.services, cnxn=self.cnxn, requester=None)
293 response = self.CallWrapped(self.users_svcr.GetUserPrefs, mc, request)
294
295 self.assertEqual(0, len(response.prefs))
296
297 def testGetUserPrefs_Mine_Empty(self):
298 """User who never set any pref gets empty prefs."""
299 request = users_pb2.GetUserPrefsRequest()
300 mc = monorailcontext.MonorailContext(
301 self.services, cnxn=self.cnxn, requester='owner@example.com')
302 response = self.CallWrapped(self.users_svcr.GetUserPrefs, mc, request)
303
304 self.assertEqual(0, len(response.prefs))
305
306 def testGetUserPrefs_Mine_Some(self):
307 """User who set a pref gets it back."""
308 self.services.user.SetUserPrefs(
309 self.cnxn, 111,
310 [user_pb2.UserPrefValue(name='code_font', value='true')])
311 request = users_pb2.GetUserPrefsRequest()
312 mc = monorailcontext.MonorailContext(
313 self.services, cnxn=self.cnxn, requester='owner@example.com')
314 response = self.CallWrapped(self.users_svcr.GetUserPrefs, mc, request)
315
316 self.assertEqual(1, len(response.prefs))
317 self.assertEqual('code_font', response.prefs[0].name)
318 self.assertEqual('true', response.prefs[0].value)
319
320 def testGetUserPrefs_Other_Allowed(self):
321 """A site admin can read another user's prefs."""
322 self.services.user.SetUserPrefs(
323 self.cnxn, 111,
324 [user_pb2.UserPrefValue(name='code_font', value='true')])
325 self.user_2.is_site_admin = True
326
327 request = users_pb2.GetUserPrefsRequest()
328 request.user_ref.display_name = 'owner@example.com'
329 mc = monorailcontext.MonorailContext(
330 self.services, cnxn=self.cnxn, requester='test2@example.com')
331 mc.LookupLoggedInUserPerms(self.project)
332 response = self.CallWrapped(self.users_svcr.GetUserPrefs, mc, request)
333
334 self.assertEqual(1, len(response.prefs))
335 self.assertEqual('code_font', response.prefs[0].name)
336 self.assertEqual('true', response.prefs[0].value)
337
338 def testGetUserPrefs_Other_Denied(self):
339 """A non-admin cannot read another user's prefs."""
340 self.services.user.SetUserPrefs(
341 self.cnxn, 111,
342 [user_pb2.UserPrefValue(name='code_font', value='true')])
343 # user2 is not a site admin.
344
345 request = users_pb2.GetUserPrefsRequest()
346 request.user_ref.display_name = 'owner@example.com'
347 mc = monorailcontext.MonorailContext(
348 self.services, cnxn=self.cnxn, requester='test2@example.com')
349 mc.LookupLoggedInUserPerms(self.project)
350 with self.assertRaises(permissions.PermissionException):
351 self.CallWrapped(self.users_svcr.GetUserPrefs, mc, request)
352
353 def testSetUserPrefs_Anon(self):
354 """Anon cannot set prefs."""
355 request = users_pb2.SetUserPrefsRequest()
356 mc = monorailcontext.MonorailContext(
357 self.services, cnxn=self.cnxn, requester=None)
358 with self.assertRaises(exceptions.InputException):
359 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
360
361 def testSetUserPrefs_Mine_Empty(self):
362 """Setting zero prefs is a no-op.."""
363 request = users_pb2.SetUserPrefsRequest()
364 mc = monorailcontext.MonorailContext(
365 self.services, cnxn=self.cnxn, requester='owner@example.com')
366 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
367
368 prefs_after = self.services.user.GetUserPrefs(self.cnxn, 111)
369 self.assertEqual(0, len(prefs_after.prefs))
370
371 def testSetUserPrefs_Mine_Add(self):
372 """User can set a preference for the first time."""
373 request = users_pb2.SetUserPrefsRequest(
374 prefs=[user_objects_pb2.UserPrefValue(name='code_font', value='true')])
375 mc = monorailcontext.MonorailContext(
376 self.services, cnxn=self.cnxn, requester='owner@example.com')
377 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
378
379 prefs_after = self.services.user.GetUserPrefs(self.cnxn, 111)
380 self.assertEqual(1, len(prefs_after.prefs))
381 self.assertEqual('code_font', prefs_after.prefs[0].name)
382 self.assertEqual('true', prefs_after.prefs[0].value)
383
384 def testSetUserPrefs_Mine_Overwrite(self):
385 """User can change the value of a pref."""
386 self.services.user.SetUserPrefs(
387 self.cnxn, 111,
388 [user_pb2.UserPrefValue(name='code_font', value='true')])
389 request = users_pb2.SetUserPrefsRequest(
390 prefs=[user_objects_pb2.UserPrefValue(name='code_font', value='false')])
391 mc = monorailcontext.MonorailContext(
392 self.services, cnxn=self.cnxn, requester='owner@example.com')
393 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
394
395 prefs_after = self.services.user.GetUserPrefs(self.cnxn, 111)
396 self.assertEqual(1, len(prefs_after.prefs))
397 self.assertEqual('code_font', prefs_after.prefs[0].name)
398 self.assertEqual('false', prefs_after.prefs[0].value)
399
400 def testSetUserPrefs_Other_Allowed(self):
401 """A site admin can update another user's prefs."""
402 self.services.user.SetUserPrefs(
403 self.cnxn, 111,
404 [user_pb2.UserPrefValue(name='code_font', value='true')])
405 self.user_2.is_site_admin = True
406
407 request = users_pb2.SetUserPrefsRequest(
408 prefs=[user_objects_pb2.UserPrefValue(name='code_font', value='false')])
409 request.user_ref.display_name = 'owner@example.com'
410 mc = monorailcontext.MonorailContext(
411 self.services, cnxn=self.cnxn, requester='test2@example.com')
412 mc.LookupLoggedInUserPerms(self.project)
413 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
414
415 prefs_after = self.services.user.GetUserPrefs(self.cnxn, 111)
416 self.assertEqual(1, len(prefs_after.prefs))
417 self.assertEqual('code_font', prefs_after.prefs[0].name)
418 self.assertEqual('false', prefs_after.prefs[0].value)
419
420 def testSetUserPrefs_Other_Denied(self):
421 """A non-admin cannot set another user's prefs."""
422 self.services.user.SetUserPrefs(
423 self.cnxn, 111,
424 [user_pb2.UserPrefValue(name='code_font', value='true')])
425 # user2 is not a site admin.
426
427 request = users_pb2.SetUserPrefsRequest(
428 prefs=[user_objects_pb2.UserPrefValue(name='code_font', value='false')])
429 request.user_ref.display_name = 'owner@example.com'
430 mc = monorailcontext.MonorailContext(
431 self.services, cnxn=self.cnxn, requester='test2@example.com')
432 mc.LookupLoggedInUserPerms(self.project)
433 with self.assertRaises(permissions.PermissionException):
434 self.CallWrapped(self.users_svcr.SetUserPrefs, mc, request)
435
436 # Regardless of any exception, the preferences remain unchanged.
437 prefs_after = self.services.user.GetUserPrefs(self.cnxn, 111)
438 self.assertEqual(1, len(prefs_after.prefs))
439 self.assertEqual('code_font', prefs_after.prefs[0].name)
440 self.assertEqual('true', prefs_after.prefs[0].value)
441
442 def testInviteLinkedParent_NotFound(self):
443 """Reject attempt to invite a user that does not exist."""
444 self.services.user.TestAddUser('user@google.com', 333)
445 request = users_pb2.InviteLinkedParentRequest(
446 email='who@chromium.org') # Does not exist.
447 mc = monorailcontext.MonorailContext(
448 self.services, cnxn=self.cnxn, requester='who@google.com')
449 with self.assertRaises(exceptions.NoSuchUserException):
450 self.CallWrapped(self.users_svcr.InviteLinkedParent, mc, request)
451
452 def testInviteLinkedParent_Normal(self):
453 """We can invite accounts to link when all criteria are met."""
454 self.services.user.TestAddUser('user@google.com', 333)
455 self.services.user.TestAddUser('user@chromium.org', 444)
456 request = users_pb2.InviteLinkedParentRequest(
457 email='user@google.com')
458 mc = monorailcontext.MonorailContext(
459 self.services, cnxn=self.cnxn, requester='user@chromium.org')
460 self.CallWrapped(self.users_svcr.InviteLinkedParent, mc, request)
461
462 (invite_as_parent, invite_as_child
463 ) = self.services.user.GetPendingLinkedInvites(self.cnxn, 333)
464 self.assertEqual([444], invite_as_parent)
465 self.assertEqual([], invite_as_child)
466 (invite_as_parent, invite_as_child
467 ) = self.services.user.GetPendingLinkedInvites(self.cnxn, 444)
468 self.assertEqual([], invite_as_parent)
469 self.assertEqual([333], invite_as_child)
470
471 def testAcceptLinkedChild_NotFound(self):
472 """Reject attempt to link a user that does not exist."""
473 self.services.user.TestAddUser('user@google.com', 333)
474 request = users_pb2.AcceptLinkedChildRequest(
475 email='who@chromium.org') # Does not exist.
476 mc = monorailcontext.MonorailContext(
477 self.services, cnxn=self.cnxn, requester='who@google.com')
478 with self.assertRaises(exceptions.NoSuchUserException):
479 self.CallWrapped(self.users_svcr.AcceptLinkedChild, mc, request)
480
481 def testAcceptLinkedChild_NoInvite(self):
482 """Reject attempt to link accounts when there was no invite."""
483 self.services.user.TestAddUser('user@google.com', 333)
484 self.services.user.TestAddUser('user@chromium.org', 444)
485 request = users_pb2.AcceptLinkedChildRequest(
486 email='user@chromium.org')
487 mc = monorailcontext.MonorailContext(
488 self.services, cnxn=self.cnxn, requester='user@google.com')
489 with self.assertRaises(exceptions.InputException):
490 self.CallWrapped(self.users_svcr.AcceptLinkedChild, mc, request)
491
492 def testAcceptLinkedChild_Normal(self):
493 """We can linke accounts when all criteria are met."""
494 parent = self.services.user.TestAddUser('user@google.com', 333)
495 child = self.services.user.TestAddUser('user@chromium.org', 444)
496 self.services.user.InviteLinkedParent(
497 self.cnxn, parent.user_id, child.user_id)
498 request = users_pb2.AcceptLinkedChildRequest(
499 email='user@chromium.org')
500 mc = monorailcontext.MonorailContext(
501 self.services, cnxn=self.cnxn, requester='user@google.com')
502 self.CallWrapped(self.users_svcr.AcceptLinkedChild, mc, request)
503
504 self.assertEqual(parent.user_id, child.linked_parent_id)
505 self.assertIn(child.user_id, parent.linked_child_ids)
506
507 def testUnlinkAccounts_NotFound(self):
508 """Reject attempt to unlink a user that does not exist or unspecified."""
509 mc = monorailcontext.MonorailContext(
510 self.services, cnxn=self.cnxn, requester='owner@example.com')
511
512 request = users_pb2.UnlinkAccountsRequest(
513 parent=common_pb2.UserRef(display_name='who@chromium.org'),
514 child=common_pb2.UserRef(display_name='owner@example.com'))
515 with self.assertRaises(exceptions.NoSuchUserException):
516 self.CallWrapped(self.users_svcr.UnlinkAccounts, mc, request)
517
518 request = users_pb2.UnlinkAccountsRequest(
519 parent=common_pb2.UserRef(display_name='owner@example.com'),
520 child=common_pb2.UserRef(display_name='who@google.com'))
521 with self.assertRaises(exceptions.NoSuchUserException):
522 self.CallWrapped(self.users_svcr.UnlinkAccounts, mc, request)
523
524 request = users_pb2.UnlinkAccountsRequest(
525 parent=common_pb2.UserRef(display_name='owner@example.com'))
526 with self.assertRaises(exceptions.InputException):
527 self.CallWrapped(self.users_svcr.UnlinkAccounts, mc, request)
528
529 request = users_pb2.UnlinkAccountsRequest(
530 child=common_pb2.UserRef(display_name='owner@example.com'))
531 with self.assertRaises(exceptions.InputException):
532 self.CallWrapped(self.users_svcr.UnlinkAccounts, mc, request)
533
534 def testUnlinkAccounts_Normal(self):
535 """Users can unlink their accounts."""
536 self.services.user.linked_account_rows = [(111, 222)]
537 request = users_pb2.UnlinkAccountsRequest(
538 parent=common_pb2.UserRef(display_name='owner@example.com'),
539 child=common_pb2.UserRef(display_name='test2@example.com'))
540 mc = monorailcontext.MonorailContext(
541 self.services, cnxn=self.cnxn, requester='owner@example.com')
542
543 self.CallWrapped(self.users_svcr.UnlinkAccounts, mc, request)
544
545 self.assertEqual([], self.services.user.linked_account_rows)
546
547 def AddUserProjects(self, user_id):
548 project_states = {
549 'live': project_pb2.ProjectState.LIVE,
550 'archived': project_pb2.ProjectState.ARCHIVED,
551 'deletable': project_pb2.ProjectState.DELETABLE}
552
553 for name, state in project_states.items():
554 self.services.project.TestAddProject(
555 'owner-%s-%s' % (name, user_id), state=state, owner_ids=[user_id])
556 self.services.project.TestAddProject(
557 'committer-%s-%s' % (name, user_id), state=state,\
558 committer_ids=[user_id])
559 contributor = self.services.project.TestAddProject(
560 'contributor-%s-%s' % (name, user_id), state=state)
561 contributor.contributor_ids = [user_id]
562
563 members_only = self.services.project.TestAddProject(
564 'members-only-' + str(user_id), owner_ids=[user_id])
565 members_only.access = project_pb2.ProjectAccess.MEMBERS_ONLY
566
567 def testGetUsersProjects(self):
568 self.user = self.services.user.TestAddUser('test3@example.com', 333)
569 self.services.project_star.SetStar(
570 self.cnxn, self.project.project_id, 222, True)
571 self.project.committer_ids.extend([222])
572
573 self.AddUserProjects(222)
574 self.AddUserProjects(333)
575
576 request = users_pb2.GetUsersProjectsRequest(user_refs=[
577 common_pb2.UserRef(display_name='test2@example.com'),
578 common_pb2.UserRef(display_name='test3@example.com')])
579 mc = monorailcontext.MonorailContext(
580 self.services, cnxn=self.cnxn, requester='test2@example.com')
581 mc.LookupLoggedInUserPerms(self.project)
582 response = self.CallWrapped(
583 self.users_svcr.GetUsersProjects, mc, request)
584
585 self.assertEqual([
586 user_objects_pb2.UserProjects(
587 user_ref=common_pb2.UserRef(display_name='test2@example.com'),
588 owner_of=['members-only-222', 'owner-live-222'],
589 member_of=['committer-live-222', 'proj'],
590 contributor_to=['contributor-live-222'],
591 starred_projects=['proj']),
592 user_objects_pb2.UserProjects(
593 user_ref=common_pb2.UserRef(display_name='test3@example.com'),
594 owner_of=['owner-live-333'],
595 member_of=['committer-live-333'],
596 contributor_to=['contributor-live-333'])],
597 list(response.users_projects))
598
599 def testGetUsersProjects_NoUserRefs(self):
600 request = users_pb2.GetUsersProjectsRequest()
601 mc = monorailcontext.MonorailContext(
602 self.services, cnxn=self.cnxn, requester='test2@example.com')
603 mc.LookupLoggedInUserPerms(self.project)
604 response = self.CallWrapped(
605 self.users_svcr.GetUsersProjects, mc, request)
606 self.assertEqual([], list(response.users_projects))