blob: fcd30c3662a2765fd3ec8ad9fe92e126b922c3fb [file] [log] [blame]
Copybara854996b2021-09-07 19:36:02 +00001# Copyright 2016 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"""Unit tests for the monorailrequest module."""
7from __future__ import print_function
8from __future__ import division
9from __future__ import absolute_import
10
11import endpoints
12import mock
13import re
14import unittest
15
16import mox
17import six
18
19from google.appengine.api import oauth
20from google.appengine.api import users
21
22import webapp2
23
24from framework import exceptions
25from framework import monorailrequest
26from framework import permissions
27from proto import project_pb2
28from proto import tracker_pb2
29from services import service_manager
30from testing import fake
31from testing import testing_helpers
32from tracker import tracker_constants
33
34
35class HostportReTest(unittest.TestCase):
36
37 def testGood(self):
38 test_data = [
39 'localhost:8080',
40 'app.appspot.com',
41 'bugs-staging.chromium.org',
42 'vers10n-h3x-dot-app-id.appspot.com',
43 ]
44 for hostport in test_data:
45 self.assertTrue(monorailrequest._HOSTPORT_RE.match(hostport),
46 msg='Incorrectly rejected %r' % hostport)
47
48 def testBad(self):
49 test_data = [
50 '',
51 ' ',
52 '\t',
53 '\n',
54 '\'',
55 '"',
56 'version"cruft-dot-app-id.appspot.com',
57 '\nother header',
58 'version&cruft-dot-app-id.appspot.com',
59 ]
60 for hostport in test_data:
61 self.assertFalse(monorailrequest._HOSTPORT_RE.match(hostport),
62 msg='Incorrectly accepted %r' % hostport)
63
64
65class MonorailApiRequestUnitTest(unittest.TestCase):
66
67 def setUp(self):
68 self.cnxn = 'fake cnxn'
69 self.services = service_manager.Services(
70 config=fake.ConfigService(),
71 issue=fake.IssueService(),
72 project=fake.ProjectService(),
73 user=fake.UserService(),
74 usergroup=fake.UserGroupService())
75 self.project = self.services.project.TestAddProject(
76 'proj', project_id=789)
77 self.services.user.TestAddUser('requester@example.com', 111)
78 self.issue = fake.MakeTestIssue(
79 789, 1, 'sum', 'New', 111)
80 self.services.issue.TestAddIssue(self.issue)
81
82 self.patcher_1 = mock.patch('endpoints.get_current_user')
83 self.mock_endpoints_gcu = self.patcher_1.start()
84 self.mock_endpoints_gcu.return_value = None
85 self.patcher_2 = mock.patch('google.appengine.api.oauth.get_current_user')
86 self.mock_oauth_gcu = self.patcher_2.start()
87 self.mock_oauth_gcu.return_value = testing_helpers.Blank(
88 email=lambda: 'requester@example.com')
89
90 def tearDown(self):
91 mock.patch.stopall()
92
93 def testInit_NoProjectIssueOrViewedUser(self):
94 request = testing_helpers.Blank()
95 mar = monorailrequest.MonorailApiRequest(
96 request, self.services, cnxn=self.cnxn)
97 self.assertIsNone(mar.project)
98 self.assertIsNone(mar.issue)
99
100 def testInit_WithProject(self):
101 request = testing_helpers.Blank(projectId='proj')
102 mar = monorailrequest.MonorailApiRequest(
103 request, self.services, cnxn=self.cnxn)
104 self.assertEqual(self.project, mar.project)
105 self.assertIsNone(mar.issue)
106
107 def testInit_WithProjectAndIssue(self):
108 request = testing_helpers.Blank(
109 projectId='proj', issueId=1)
110 mar = monorailrequest.MonorailApiRequest(
111 request, self.services, cnxn=self.cnxn)
112 self.assertEqual(self.project, mar.project)
113 self.assertEqual(self.issue, mar.issue)
114
115 def testGetParam_Normal(self):
116 request = testing_helpers.Blank(q='owner:me')
117 mar = monorailrequest.MonorailApiRequest(
118 request, self.services, cnxn=self.cnxn)
119 self.assertEqual(None, mar.GetParam('unknown'))
120 self.assertEqual(100, mar.GetParam('num'))
121 self.assertEqual('owner:me', mar.GetParam('q'))
122
123 request = testing_helpers.Blank(q='owner:me', maxResults=200)
124 mar = monorailrequest.MonorailApiRequest(
125 request, self.services, cnxn=self.cnxn)
126 self.assertEqual(200, mar.GetParam('num'))
127
128
129class MonorailRequestUnitTest(unittest.TestCase):
130
131 def setUp(self):
132 self.services = service_manager.Services(
133 project=fake.ProjectService(),
134 user=fake.UserService(),
135 usergroup=fake.UserGroupService(),
136 features=fake.FeaturesService())
137 self.project = self.services.project.TestAddProject('proj')
138 self.hotlist = self.services.features.TestAddHotlist(
139 'TestHotlist', owner_ids=[111])
140 self.services.user.TestAddUser('jrobbins@example.com', 111)
141
142 self.mox = mox.Mox()
143 self.mox.StubOutWithMock(users, 'get_current_user')
144 users.get_current_user().AndReturn(None)
145 self.mox.ReplayAll()
146
147 def tearDown(self):
148 self.mox.UnsetStubs()
149
150 def testGetIntParam_ConvertsQueryParamToInt(self):
151 notice_id = 12345
152 mr = testing_helpers.MakeMonorailRequest(
153 path='/foo?notice=%s' % notice_id)
154
155 value = mr.GetIntParam('notice')
156 self.assertTrue(isinstance(value, int))
157 self.assertEqual(notice_id, value)
158
159 def testGetIntParam_ConvertsQueryParamToLong(self):
160 notice_id = 12345678901234567890
161 mr = testing_helpers.MakeMonorailRequest(
162 path='/foo?notice=%s' % notice_id)
163
164 value = mr.GetIntParam('notice')
165 self.assertTrue(isinstance(value, six.integer_types))
166 self.assertEqual(notice_id, value)
167
168 def testGetIntListParam_NoParam(self):
169 mr = monorailrequest.MonorailRequest(self.services)
170 mr.ParseRequest(webapp2.Request.blank('servlet'), self.services)
171 self.assertEqual(mr.GetIntListParam('ids'), None)
172 self.assertEqual(mr.GetIntListParam('ids', default_value=['test']),
173 ['test'])
174
175 def testGetIntListParam_OneValue(self):
176 mr = monorailrequest.MonorailRequest(self.services)
177 mr.ParseRequest(webapp2.Request.blank('servlet?ids=11'), self.services)
178 self.assertEqual(mr.GetIntListParam('ids'), [11])
179 self.assertEqual(mr.GetIntListParam('ids', default_value=['test']),
180 [11])
181
182 def testGetIntListParam_MultiValue(self):
183 mr = monorailrequest.MonorailRequest(self.services)
184 mr.ParseRequest(
185 webapp2.Request.blank('servlet?ids=21,22,23'), self.services)
186 self.assertEqual(mr.GetIntListParam('ids'), [21, 22, 23])
187 self.assertEqual(mr.GetIntListParam('ids', default_value=['test']),
188 [21, 22, 23])
189
190 def testGetIntListParam_BogusValue(self):
191 mr = monorailrequest.MonorailRequest(self.services)
192 with self.assertRaises(exceptions.InputException):
193 mr.ParseRequest(
194 webapp2.Request.blank('servlet?ids=not_an_int'), self.services)
195
196 def testGetIntListParam_Malformed(self):
197 mr = monorailrequest.MonorailRequest(self.services)
198 with self.assertRaises(exceptions.InputException):
199 mr.ParseRequest(
200 webapp2.Request.blank('servlet?ids=31,32,,'), self.services)
201
202 def testDefaultValuesNoUrl(self):
203 """If request has no param, default param values should be used."""
204 mr = monorailrequest.MonorailRequest(self.services)
205 mr.ParseRequest(webapp2.Request.blank('servlet'), self.services)
206 self.assertEqual(mr.GetParam('r', 3), 3)
207 self.assertEqual(mr.GetIntParam('r', 3), 3)
208 self.assertEqual(mr.GetPositiveIntParam('r', 3), 3)
209 self.assertEqual(mr.GetIntListParam('r', [3, 4]), [3, 4])
210
211 def _MRWithMockRequest(
212 self, path, headers=None, *mr_args, **mr_kwargs):
213 request = webapp2.Request.blank(path, headers=headers)
214 mr = monorailrequest.MonorailRequest(self.services, *mr_args, **mr_kwargs)
215 mr.ParseRequest(request, self.services)
216 return mr
217
218 def testParseQueryParameters(self):
219 mr = self._MRWithMockRequest(
220 '/p/proj/issues/list?q=foo+OR+bar&num=50')
221 self.assertEqual('foo OR bar', mr.query)
222 self.assertEqual(50, mr.num)
223
224 def testParseQueryParameters_ModeMissing(self):
225 mr = self._MRWithMockRequest(
226 '/p/proj/issues/list?q=foo+OR+bar&num=50')
227 self.assertEqual('list', mr.mode)
228
229 def testParseQueryParameters_ModeList(self):
230 mr = self._MRWithMockRequest(
231 '/p/proj/issues/list?q=foo+OR+bar&num=50&mode=')
232 self.assertEqual('list', mr.mode)
233
234 def testParseQueryParameters_ModeGrid(self):
235 mr = self._MRWithMockRequest(
236 '/p/proj/issues/list?q=foo+OR+bar&num=50&mode=grid')
237 self.assertEqual('grid', mr.mode)
238
239 def testParseQueryParameters_ModeChart(self):
240 mr = self._MRWithMockRequest(
241 '/p/proj/issues/list?q=foo+OR+bar&num=50&mode=chart')
242 self.assertEqual('chart', mr.mode)
243
244 def testParseRequest_Scheme(self):
245 mr = self._MRWithMockRequest('/p/proj/')
246 self.assertEqual('http', mr.request.scheme)
247
248 def testParseRequest_HostportAndCurrentPageURL(self):
249 mr = self._MRWithMockRequest('/p/proj/', headers={
250 'Host': 'example.com',
251 'Cookie': 'asdf',
252 })
253 self.assertEqual('http', mr.request.scheme)
254 self.assertEqual('example.com', mr.request.host)
255 self.assertEqual('http://example.com/p/proj/', mr.current_page_url)
256
257 def testParseRequest_ProjectFound(self):
258 mr = self._MRWithMockRequest('/p/proj/')
259 self.assertEqual(mr.project, self.project)
260
261 def testParseRequest_ProjectNotFound(self):
262 with self.assertRaises(exceptions.NoSuchProjectException):
263 self._MRWithMockRequest('/p/no-such-proj/')
264
265 def testViewedUser_WithEmail(self):
266 mr = self._MRWithMockRequest('/u/jrobbins@example.com/')
267 self.assertEqual('jrobbins@example.com', mr.viewed_username)
268 self.assertEqual(111, mr.viewed_user_auth.user_id)
269 self.assertEqual(
270 self.services.user.GetUser('fake cnxn', 111),
271 mr.viewed_user_auth.user_pb)
272
273 def testViewedUser_WithUserID(self):
274 mr = self._MRWithMockRequest('/u/111/')
275 self.assertEqual('jrobbins@example.com', mr.viewed_username)
276 self.assertEqual(111, mr.viewed_user_auth.user_id)
277 self.assertEqual(
278 self.services.user.GetUser('fake cnxn', 111),
279 mr.viewed_user_auth.user_pb)
280
281 def testViewedUser_NoSuchEmail(self):
282 with self.assertRaises(webapp2.HTTPException) as cm:
283 self._MRWithMockRequest('/u/unknownuser@example.com/')
284 self.assertEqual(404, cm.exception.code)
285
286 def testViewedUser_NoSuchUserID(self):
287 with self.assertRaises(exceptions.NoSuchUserException):
288 self._MRWithMockRequest('/u/234521111/')
289
290 def testGetParam(self):
291 mr = testing_helpers.MakeMonorailRequest(
292 path='/foo?syn=error!&a=a&empty=',
293 params=dict(over1='over_value1', over2='over_value2'))
294
295 # test tampering
296 self.assertRaises(exceptions.InputException, mr.GetParam, 'a',
297 antitamper_re=re.compile(r'^$'))
298 self.assertRaises(exceptions.InputException, mr.GetParam,
299 'undefined', default_value='default',
300 antitamper_re=re.compile(r'^$'))
301
302 # test empty value
303 self.assertEqual('', mr.GetParam(
304 'empty', default_value='default', antitamper_re=re.compile(r'^$')))
305
306 # test default
307 self.assertEqual('default', mr.GetParam(
308 'undefined', default_value='default'))
309
310 def testComputeColSpec(self):
311 # No config passed, and nothing in URL
312 mr = testing_helpers.MakeMonorailRequest(
313 path='/p/proj/issues/detail?id=123')
314 mr.ComputeColSpec(None)
315 self.assertEqual(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec)
316
317 # No config passed, but set in URL
318 mr = testing_helpers.MakeMonorailRequest(
319 path='/p/proj/issues/detail?id=123&colspec=a b C')
320 mr.ComputeColSpec(None)
321 self.assertEqual('a b C', mr.col_spec)
322
323 config = tracker_pb2.ProjectIssueConfig()
324
325 # No default in the config, and nothing in URL
326 mr = testing_helpers.MakeMonorailRequest(
327 path='/p/proj/issues/detail?id=123')
328 mr.ComputeColSpec(config)
329 self.assertEqual(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec)
330
331 # No default in the config, but set in URL
332 mr = testing_helpers.MakeMonorailRequest(
333 path='/p/proj/issues/detail?id=123&colspec=a b C')
334 mr.ComputeColSpec(config)
335 self.assertEqual('a b C', mr.col_spec)
336
337 config.default_col_spec = 'd e f'
338
339 # Default in the config, and nothing in URL
340 mr = testing_helpers.MakeMonorailRequest(
341 path='/p/proj/issues/detail?id=123')
342 mr.ComputeColSpec(config)
343 self.assertEqual('d e f', mr.col_spec)
344
345 # Default in the config, but overrided via URL
346 mr = testing_helpers.MakeMonorailRequest(
347 path='/p/proj/issues/detail?id=123&colspec=a b C')
348 mr.ComputeColSpec(config)
349 self.assertEqual('a b C', mr.col_spec)
350
351 # project colspec contains hotlist columns
352 mr = testing_helpers.MakeMonorailRequest(
353 path='p/proj/issues/detail?id=123&colspec=Rank Adder Adder Owner')
354 mr.ComputeColSpec(None)
355 self.assertEqual(tracker_constants.DEFAULT_COL_SPEC, mr.col_spec)
356
357 # hotlist columns are not deleted when page is a hotlist page
358 mr = testing_helpers.MakeMonorailRequest(
359 path='u/jrobbins@example.com/hotlists/TestHotlist?colspec=Rank Adder',
360 hotlist=self.hotlist)
361 mr.ComputeColSpec(None)
362 self.assertEqual('Rank Adder', mr.col_spec)
363
364 def testComputeColSpec_XSS(self):
365 config_1 = tracker_pb2.ProjectIssueConfig()
366 config_2 = tracker_pb2.ProjectIssueConfig()
367 config_2.default_col_spec = "id '+alert(1)+'"
368 mr_1 = testing_helpers.MakeMonorailRequest(
369 path='/p/proj/issues/detail?id=123')
370 mr_2 = testing_helpers.MakeMonorailRequest(
371 path="/p/proj/issues/detail?id=123&colspec=id '+alert(1)+'")
372
373 # Normal colspec in config but malicious request
374 self.assertRaises(
375 exceptions.InputException,
376 mr_2.ComputeColSpec, config_1)
377
378 # Malicious colspec in config but normal request
379 self.assertRaises(
380 exceptions.InputException,
381 mr_1.ComputeColSpec, config_2)
382
383 # Malicious colspec in config and malicious request
384 self.assertRaises(
385 exceptions.InputException,
386 mr_2.ComputeColSpec, config_2)
387
388
389class CalcDefaultQueryTest(unittest.TestCase):
390
391 def setUp(self):
392 self.project = project_pb2.Project()
393 self.project.project_name = 'proj'
394 self.project.owner_ids = [111]
395 self.config = tracker_pb2.ProjectIssueConfig()
396
397 def testIssueListURL_NotDefaultCan(self):
398 mr = monorailrequest.MonorailRequest(None)
399 mr.query = None
400 mr.can = 1
401 self.assertEqual('', mr._CalcDefaultQuery())
402
403 def testIssueListURL_NoProject(self):
404 mr = monorailrequest.MonorailRequest(None)
405 mr.query = None
406 mr.can = 2
407 self.assertEqual('', mr._CalcDefaultQuery())
408
409 def testIssueListURL_NoConfig(self):
410 mr = monorailrequest.MonorailRequest(None)
411 mr.query = None
412 mr.can = 2
413 mr.project = self.project
414 self.assertEqual('', mr._CalcDefaultQuery())
415
416 def testIssueListURL_NotCustomized(self):
417 mr = monorailrequest.MonorailRequest(None)
418 mr.query = None
419 mr.can = 2
420 mr.project = self.project
421 mr.config = self.config
422 self.assertEqual('', mr._CalcDefaultQuery())
423
424 def testIssueListURL_Customized_Nonmember(self):
425 mr = monorailrequest.MonorailRequest(None)
426 mr.query = None
427 mr.can = 2
428 mr.project = self.project
429 mr.config = self.config
430 mr.config.member_default_query = 'owner:me'
431 self.assertEqual('', mr._CalcDefaultQuery())
432
433 mr.auth = testing_helpers.Blank(effective_ids=set())
434 self.assertEqual('', mr._CalcDefaultQuery())
435
436 mr.auth = testing_helpers.Blank(effective_ids={999})
437 self.assertEqual('', mr._CalcDefaultQuery())
438
439 def testIssueListURL_Customized_Member(self):
440 mr = monorailrequest.MonorailRequest(None)
441 mr.query = None
442 mr.can = 2
443 mr.project = self.project
444 mr.config = self.config
445 mr.config.member_default_query = 'owner:me'
446 mr.auth = testing_helpers.Blank(effective_ids={111})
447 self.assertEqual('owner:me', mr._CalcDefaultQuery())
448
449
450class TestMonorailRequestFunctions(unittest.TestCase):
451
452 def testExtractPathIdentifiers_ProjectOnly(self):
453 (username, project_name, hotlist_id,
454 hotlist_name) = monorailrequest._ParsePathIdentifiers(
455 '/p/proj/issues/list?q=foo+OR+bar&ts=1234')
456 self.assertIsNone(username)
457 self.assertIsNone(hotlist_id)
458 self.assertIsNone(hotlist_name)
459 self.assertEqual('proj', project_name)
460
461 def testExtractPathIdentifiers_ViewedUserOnly(self):
462 (username, project_name, hotlist_id,
463 hotlist_name) = monorailrequest._ParsePathIdentifiers(
464 '/u/jrobbins@example.com/')
465 self.assertEqual('jrobbins@example.com', username)
466 self.assertIsNone(project_name)
467 self.assertIsNone(hotlist_id)
468 self.assertIsNone(hotlist_name)
469
470 def testExtractPathIdentifiers_ViewedUserURLSpace(self):
471 (username, project_name, hotlist_id,
472 hotlist_name) = monorailrequest._ParsePathIdentifiers(
473 '/u/jrobbins@example.com/updates')
474 self.assertEqual('jrobbins@example.com', username)
475 self.assertIsNone(project_name)
476 self.assertIsNone(hotlist_id)
477 self.assertIsNone(hotlist_name)
478
479 def testExtractPathIdentifiers_ViewedGroupURLSpace(self):
480 (username, project_name, hotlist_id,
481 hotlist_name) = monorailrequest._ParsePathIdentifiers(
482 '/g/user-group@example.com/updates')
483 self.assertEqual('user-group@example.com', username)
484 self.assertIsNone(project_name)
485 self.assertIsNone(hotlist_id)
486 self.assertIsNone(hotlist_name)
487
488 def testExtractPathIdentifiers_HotlistIssuesURLSpaceById(self):
489 (username, project_name, hotlist_id,
490 hotlist_name) = monorailrequest._ParsePathIdentifiers(
491 '/u/jrobbins@example.com/hotlists/13124?q=stuff&ts=more')
492 self.assertIsNone(hotlist_name)
493 self.assertIsNone(project_name)
494 self.assertEqual('jrobbins@example.com', username)
495 self.assertEqual(13124, hotlist_id)
496
497 def testExtractPathIdentifiers_HotlistIssuesURLSpaceByName(self):
498 (username, project_name, hotlist_id,
499 hotlist_name) = monorailrequest._ParsePathIdentifiers(
500 '/u/jrobbins@example.com/hotlists/testname?q=stuff&ts=more')
501 self.assertIsNone(project_name)
502 self.assertIsNone(hotlist_id)
503 self.assertEqual('jrobbins@example.com', username)
504 self.assertEqual('testname', hotlist_name)
505
506 def testParseColSpec(self):
507 parse = monorailrequest.ParseColSpec
508 self.assertEqual(['PageName', 'Summary', 'Changed', 'ChangedBy'],
509 parse(u'PageName Summary Changed ChangedBy'))
510 self.assertEqual(['Foo-Bar', 'Foo-Bar-Baz', 'Release-1.2', 'Hey', 'There'],
511 parse('Foo-Bar Foo-Bar-Baz Release-1.2 Hey!There'))
512 self.assertEqual(
513 ['\xe7\xaa\xbf\xe8\x8b\xa5\xe7\xb9\xb9'.decode('utf-8'),
514 '\xe5\x9f\xba\xe5\x9c\xb0\xe3\x81\xaf'.decode('utf-8')],
515 parse('\xe7\xaa\xbf\xe8\x8b\xa5\xe7\xb9\xb9 '
516 '\xe5\x9f\xba\xe5\x9c\xb0\xe3\x81\xaf'.decode('utf-8')))
517
518 def testParseColSpec_Dedup(self):
519 """An attacker cannot inflate response size by repeating a column."""
520 parse = monorailrequest.ParseColSpec
521 self.assertEqual([], parse(''))
522 self.assertEqual(
523 ['Aa', 'b', 'c/d'],
524 parse(u'Aa Aa AA AA AA b Aa aa c/d d c aA b aa B C/D D/aa/c'))
525 self.assertEqual(
526 ['A', 'b', 'c/d', 'e', 'f'],
527 parse(u'A b c/d e f g h i j a/k l m/c/a n/o'))
528
529 def testParseColSpec_Huge(self):
530 """An attacker cannot inflate response size with a huge column name."""
531 parse = monorailrequest.ParseColSpec
532 self.assertEqual(
533 ['Aa', 'b', 'c/d'],
534 parse(u'Aa Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa b c/d'))
535
536 def testParseColSpec_Ignore(self):
537 """We ignore groupby and grid axes that would be useless."""
538 parse = monorailrequest.ParseColSpec
539 self.assertEqual(
540 ['Aa', 'b', 'c/d'],
541 parse(u'Aa AllLabels alllabels Id b opened/summary c/d',
542 ignore=tracker_constants.NOT_USED_IN_GRID_AXES))
543
544
545class TestPermissionLookup(unittest.TestCase):
546 OWNER_ID = 1
547 OTHER_USER_ID = 2
548
549 def setUp(self):
550 self.services = service_manager.Services(
551 project=fake.ProjectService(),
552 user=fake.UserService(),
553 usergroup=fake.UserGroupService())
554 self.services.user.TestAddUser('owner@gmail.com', self.OWNER_ID)
555 self.services.user.TestAddUser('user@gmail.com', self.OTHER_USER_ID)
556 self.live_project = self.services.project.TestAddProject(
557 'live', owner_ids=[self.OWNER_ID])
558 self.archived_project = self.services.project.TestAddProject(
559 'archived', owner_ids=[self.OWNER_ID],
560 state=project_pb2.ProjectState.ARCHIVED)
561 self.members_only_project = self.services.project.TestAddProject(
562 'members-only', owner_ids=[self.OWNER_ID],
563 access=project_pb2.ProjectAccess.MEMBERS_ONLY)
564
565 self.mox = mox.Mox()
566
567 def tearDown(self):
568 self.mox.UnsetStubs()
569
570 def CheckPermissions(self, perms, expect_view, expect_commit, expect_edit):
571 may_view = perms.HasPerm(permissions.VIEW, None, None)
572 self.assertEqual(expect_view, may_view)
573 may_commit = perms.HasPerm(permissions.COMMIT, None, None)
574 self.assertEqual(expect_commit, may_commit)
575 may_edit = perms.HasPerm(permissions.EDIT_PROJECT, None, None)
576 self.assertEqual(expect_edit, may_edit)
577
578 def MakeRequestAsUser(self, project_name, email):
579 self.mox.StubOutWithMock(users, 'get_current_user')
580 users.get_current_user().AndReturn(testing_helpers.Blank(
581 email=lambda: email))
582 self.mox.ReplayAll()
583
584 request = webapp2.Request.blank('/p/' + project_name)
585 mr = monorailrequest.MonorailRequest(self.services)
586 with mr.profiler.Phase('parse user info'):
587 mr.ParseRequest(request, self.services)
588 print('mr.auth is %r' % mr.auth)
589 return mr
590
591 def testOwnerPermissions_Live(self):
592 mr = self.MakeRequestAsUser('live', 'owner@gmail.com')
593 self.CheckPermissions(mr.perms, True, True, True)
594
595 def testOwnerPermissions_Archived(self):
596 mr = self.MakeRequestAsUser('archived', 'owner@gmail.com')
597 self.CheckPermissions(mr.perms, True, False, True)
598
599 def testOwnerPermissions_MembersOnly(self):
600 mr = self.MakeRequestAsUser('members-only', 'owner@gmail.com')
601 self.CheckPermissions(mr.perms, True, True, True)
602
603 def testExternalUserPermissions_Live(self):
604 mr = self.MakeRequestAsUser('live', 'user@gmail.com')
605 self.CheckPermissions(mr.perms, True, False, False)
606
607 def testExternalUserPermissions_Archived(self):
608 mr = self.MakeRequestAsUser('archived', 'user@gmail.com')
609 self.CheckPermissions(mr.perms, False, False, False)
610
611 def testExternalUserPermissions_MembersOnly(self):
612 mr = self.MakeRequestAsUser('members-only', 'user@gmail.com')
613 self.CheckPermissions(mr.perms, False, False, False)