def testGenerateToken_DifferentUsersGetDifferentTokens(self): self.assertNotEqual( xsrf.GenerateToken(111, '/path'), xsrf.GenerateToken(222, '/path')) self.assertNotEqual( xsrf.GenerateToken(111, '/path'), xsrf.GenerateToken(0, '/path'))
def ComputeIssueEntryURL(mr, config): """Compute the URL to use for the "New issue" subtab. Args: mr: commonly used info parsed from the request. config: ProjectIssueConfig for the current project. Returns: A URL string to use. It will be simply "entry" in the non-customized case. Otherewise it will be a fully qualified URL that includes some query string parameters. """ if not config.custom_issue_entry_url: return '/p/%s/issues/entry' % (mr.project_name) base_url = config.custom_issue_entry_url sep = '&' if '?' in base_url else '?' token = xsrf.GenerateToken( mr.auth.user_id, '/p/%s%s%s' % (mr.project_name, urls.ISSUE_ENTRY, '.do')) role_name = framework_helpers.GetRoleName(mr.auth.effective_ids, mr.project) continue_url = urllib.quote(framework_helpers.FormatAbsoluteURL( mr, urls.ISSUE_ENTRY + '.do')) return '%s%stoken=%s&role=%s&continue=%s' % ( base_url, sep, urllib.quote(token), urllib.quote(role_name or ''), continue_url)
def setUp(self): self.mox = mox.Mox() self.testbed = testbed.Testbed() self.testbed.activate() self.testbed.init_memcache_stub() self.testbed.init_datastore_v3_stub() self.testbed.init_user_stub() self.cnxn = fake.MonorailConnection() self.services = service_manager.Services( user=fake.UserService(), usergroup=fake.UserGroupService(), project=fake.ProjectService(), cache_manager=fake.CacheManager()) self.project = self.services.project.TestAddProject( 'proj', project_id=789, owner_ids=[111]) self.user = self.services.user.TestAddUser('*****@*****.**', 222) self.svcr = TestableServicer(self.services) self.token = xsrf.GenerateToken(222, xsrf.XHR_SERVLET_PATH) self.request = UpdateSomethingRequest(exc_class=None) self.prpc_context = context.ServicerContext() self.prpc_context.set_code(codes.StatusCode.OK) self.auth = authdata.AuthData(user_id=222, email='*****@*****.**') self.oauth_patcher = mock.patch( 'google.appengine.api.oauth.get_current_user') self.mock_oauth_gcu = self.oauth_patcher.start() self.mock_oauth_gcu.return_value = None
def testAssertBaseChecks_Anon(self): """We allow anonymous access, with a XSRF token generated by our app.""" self.auth.user_id = 0 metadata = {monorail_servicer.XSRF_TOKEN_HEADER: xsrf.GenerateToken(0, xsrf.XHR_SERVLET_PATH)} mc = monorailcontext.MonorailContext(self.services, auth=self.auth) self.svcr.AssertBaseChecks(mc, self.request, metadata)
def testGetTableViewData(self): now = time.time() self.mox.StubOutWithMock(time, 'time') time.time().MultipleTimes().AndReturn(now) self.mox.ReplayAll() self.mr.auth.user_id = 222 self.mr.col_spec = 'Stars Projects Rank' table_view_data = self.servlet.GetTableViewData(self.mr) self.assertEqual(table_view_data['edit_hotlist_token'], xsrf.GenerateToken( self.mr.auth.user_id, '/u/222/hotlists/hotlist.do')) self.assertEqual(table_view_data['add_issues_selected'], ezt.boolean(False)) self.user2.obscure_email = False table_view_data = self.servlet.GetTableViewData(self.mr) self.assertEqual(table_view_data['edit_hotlist_token'], xsrf.GenerateToken( self.mr.auth.user_id, '/u/222/hotlists/hotlist.do')) self.mox.VerifyAll()
def testGenerateToken_CloseTimesGetSameTokens(self, mockTime): test_time = 1526671379 mockTime.return_value = test_time token1 = xsrf.GenerateToken(111, '/path') mockTime.return_value = test_time + 1 token2 = xsrf.GenerateToken(111, '/path') self.assertEqual(token1, token2) mockTime.return_value = test_time \ + xsrf.TOKEN_GRANULARITY_SECONDS \ - xsrf.TOKEN_TIMEOUT_MARGIN_SEC token3 = xsrf.GenerateToken(111, '/path') self.assertEqual(token1, token3) mockTime.return_value = test_time + xsrf.TOKEN_GRANULARITY_SECONDS token4 = xsrf.GenerateToken(111, '/path') self.assertNotEqual(token1, token4)
def testGatherPageData_Normal(self): """Users can get the hotlist issue list.""" for path in ('/u/222/hotlists/MyHotlist', '/u/[email protected]/hotlists/MyHotlist'): form_token_path = self.servlet._FormHandlerURL(path) token = xsrf.GenerateToken(self.user1.user_id, form_token_path) self._MakeMR(path + '?token=%s' % token) self.mr.auth.email = self.user1.email self.mr.auth.user_id = self.user1.user_id self.servlet.GatherPageData(self.mr)
def GetTableViewData(self, mr): """EZT template values to render a Table View of issues. Args: mr: commonly used info parsed from the request. Returns: Dictionary of page data for rendering of the Table View. """ table_data, table_related_dict = hotlist_helpers.CreateHotlistTableData( mr, mr.hotlist.items, self.services) columns = mr.col_spec.split() ordered_columns = [ template_helpers.EZTItem(col_index=i, name=col) for i, col in enumerate(columns) ] table_view_data = { 'table_data': table_data, 'panels': [template_helpers.EZTItem(ordered_columns=ordered_columns)], 'cursor': mr.cursor or mr.preview, 'preview': mr.preview, 'default_colspec': features_constants.DEFAULT_COL_SPEC, 'default_results_per_page': 10, 'preview_on_hover': (settings.enable_quick_edit and mr.auth.user_pb.preview_on_hover), # token must be generated using url with userid to accommodate # multiple urls for one hotlist 'edit_hotlist_token': xsrf.GenerateToken( mr.auth.user_id, hotlist_helpers.GetURLOfHotlist(mr.cnxn, mr.hotlist, self.services.user, url_for_token=True) + '.do'), 'add_local_ids': '', 'placeholder': _INITIAL_ADD_ISSUES_MESSAGE, 'add_issues_selected': ezt.boolean(False), 'col_spec': '' } table_view_data.update(table_related_dict) return table_view_data
def RefreshToken(self, mc, request): """Return a new token.""" # Validate that the token we're asked to refresh would still be valid with a # longer timeout. xsrf.ValidateToken(request.token, mc.auth.user_id, request.token_path, timeout=xsrf.REFRESH_TOKEN_TIMEOUT_SEC) result = sitewide_pb2.RefreshTokenResponse( token=xsrf.GenerateToken(mc.auth.user_id, request.token_path), token_expires_sec=xsrf.TokenExpiresSec()) return result
def testRefreshToken_TokenTooOld(self, mockGetRoundedTime, mockGetXSRFKey): """We reject attempts to refresh a token that's too old.""" mockGetXSRFKey.side_effect = lambda: 'fakeXSRFKey' mockGetRoundedTime.side_effect = lambda: 2 + xsrf.REFRESH_TOKEN_TIMEOUT_SEC token_path = 'token_path' token = xsrf.GenerateToken(111, token_path, 1) request = sitewide_pb2.RefreshTokenRequest( token=token, token_path=token_path) mc = monorailcontext.MonorailContext( self.services, cnxn=self.cnxn, requester='*****@*****.**') with self.assertRaises(xsrf.TokenIncorrect): self.CallWrapped(self.sitewide_svcr.RefreshToken, mc, request)
def testValidateToken_Expiration(self, mockTime): test_time = 1526671379 mockTime.return_value = test_time token = xsrf.GenerateToken(111, '/path') xsrf.ValidateToken(token, 111, '/path') mockTime.return_value = test_time + 1 xsrf.ValidateToken(token, 111, '/path') mockTime.return_value = test_time + xsrf.TOKEN_TIMEOUT_SEC xsrf.ValidateToken(token, 111, '/path') mockTime.return_value = test_time + xsrf.TOKEN_TIMEOUT_SEC + 1 self.assertRaises( xsrf.TokenIncorrect, xsrf.ValidateToken, token, 11, '/path')
def testProcessForm_RawResponse(self): user_id = 111 token = xsrf.GenerateToken(user_id, '/we/we/we') request, mr = testing_helpers.GetRequestObjects( path='/we/we/we?so=excited', params={ 'yesterday': 'thursday', 'today': 'friday', 'token': token }, user_info={'user_id': user_id}, method='POST', ) self.page_class.do_post_redirect = False self.page_class._DoFormProcessing(request, mr) self.assertEqual('sending raw data to browser', self.page_class.response.body)
def testRefreshToken(self, mockGetRoundedTime, mockGetXSRFKey): """We can refresh an expired token.""" mockGetXSRFKey.side_effect = lambda: 'fakeXSRFKey' # The token is at the brink of being too old mockGetRoundedTime.side_effect = lambda: 1 + xsrf.REFRESH_TOKEN_TIMEOUT_SEC token_path = 'token_path' token = xsrf.GenerateToken(111, token_path, 1) request = sitewide_pb2.RefreshTokenRequest( token=token, token_path=token_path) mc = monorailcontext.MonorailContext( self.services, cnxn=self.cnxn, requester='*****@*****.**') response = self.CallWrapped(self.sitewide_svcr.RefreshToken, mc, request) self.assertEqual( sitewide_pb2.RefreshTokenResponse( token='QSaKMyXhY752g7n8a34HyTo4NjQwMDE=', token_expires_sec=870901), response)
def GatherPageData(self, mr): if not self.CheckPerm(mr, permissions.MODERATE_SPAM): raise permissions.PermissionException() page_perms = self.MakePagePerms(mr, None, permissions.MODERATE_SPAM, permissions.EDIT_ISSUE, permissions.CREATE_ISSUE, permissions.SET_STAR) # TODO(seanmccullough): Figure out how to get the IssueFlagQueue either # integrated into this page data, or on its own subtab of spam moderation. # Also figure out the same for Comments. issue_items, total_count = self.services.spam.GetIssueClassifierQueue( mr.cnxn, self.services.issue, mr.project.project_id, mr.start, mr.num) issue_queue = spam_helpers.DecorateIssueClassifierQueue( mr.cnxn, self.services.issue, self.services.spam, self.services.user, issue_items) p = paginate.ArtifactPagination(mr, [], mr.num, urls.SPAM_MODERATION_QUEUE, total_count) return { 'issue_queue': issue_queue, 'projectname': mr.project.project_name, 'pagination': p, 'page_perms': page_perms, 'moderate_spam_token': xsrf.GenerateToken( mr.auth.user_id, '/p/%s%s.do' % (mr.project_name, urls.SPAM_MODERATION_QUEUE)), }
def testAssertWhitelistedOrXSRF_CustomTimeout( self, mockGetRoundedTime, mock_get_client_id): """Our API is limited to our client by checking an XSRF token.""" # Disable special whitelisting of the default client_id while testing. mock_get_client_id.return_value = None # pylint: disable=attribute-defined-outside-init self.request.project_name = 'proj' self.project.committer_ids.append(222) mc = monorailcontext.MonorailContext(self.services, auth=self.auth) # Set the token to an token created at time 1 metadata = {monorail_servicer.XSRF_TOKEN_HEADER: xsrf.GenerateToken(222, xsrf.XHR_SERVLET_PATH, 1)} # The token is too old and we fail to authenticate. mockGetRoundedTime.side_effect = lambda: 2 + xsrf.TOKEN_TIMEOUT_SEC with self.assertRaises(xsrf.TokenIncorrect): self.svcr.AssertWhitelistedOrXSRF(mc, metadata) # We can specify a custom xsrf timeout. self.svcr.xsrf_timeout = 1 + xsrf.TOKEN_TIMEOUT_SEC self.svcr.AssertWhitelistedOrXSRF(mc, metadata)
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page.""" group_views = [ sitewide_views.GroupView(*groupinfo) for groupinfo in self.services.usergroup.GetAllUserGroupsInfo(mr.cnxn) ] group_views.sort(key=lambda gv: gv.name) offer_group_deletion = mr.perms.CanUsePerm(permissions.DELETE_GROUP, mr.auth.effective_ids, None, []) offer_group_creation = mr.perms.CanUsePerm(permissions.CREATE_GROUP, mr.auth.effective_ids, None, []) return { 'form_token': xsrf.GenerateToken(mr.auth.user_id, '%s.do' % urls.GROUP_DELETE), 'groups': group_views, 'offer_group_deletion': ezt.boolean(offer_group_deletion), 'offer_group_creation': ezt.boolean(offer_group_creation), }
def HandleRequest(self, mr): """Build up a dictionary of data values to use when rendering the page. Args: mr: commonly used info parsed from the request. Returns: Dict of values used by EZT for rendering the page. """ if not mr.auth.user_id: return {} post_data = mr.request.POST form_token_path = post_data.get('form_token_path') xsrf.ValidateToken( post_data.get('form_token'), mr.auth.user_id, form_token_path, timeout=xsrf.REFRESH_TOKEN_TIMEOUT_SEC) return { 'form_token': xsrf.GenerateToken(mr.auth.user_id, form_token_path), 'token_expires_sec': xsrf.TokenExpiresSec(), }
def testProcessForm_Normal(self): user_id = 111 token = xsrf.GenerateToken(user_id, '/we/we/we') request, mr = testing_helpers.GetRequestObjects( path='/we/we/we?so=excited', params={ 'yesterday': 'thursday', 'today': 'friday', 'token': token }, user_info={'user_id': user_id}, method='POST', ) with self.assertRaises(webapp2.HTTPException) as cm: self.page_class._DoFormProcessing(request, mr) self.assertEqual(302, cm.exception.code) # forms redirect on succcess self.assertDictEqual( { 'yesterday': 'thursday', 'today': 'friday', 'token': token }, dict(self.page_class.seen_post_data))
def testWrongPath(self): token = xsrf.GenerateToken(111, '/path/one') self.assertRaises( xsrf.TokenIncorrect, xsrf.ValidateToken, token, 111, '/path/two')
def testGenerateToken_AnonUserGetsAToken(self): self.assertNotEqual('', xsrf.GenerateToken(0, '/path'))
def testGenerateToken_DifferentPathsGetDifferentTokens(self): self.assertNotEqual( xsrf.GenerateToken(111, '/path/one'), xsrf.GenerateToken(111, '/path/two'))
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page. Args: mr: commonly used info parsed from the request. Returns: Dict of values used by EZT for rendering the page. """ if mr.local_id is None: self.abort(404, 'no issue specified') with self.profiler.Phase('finishing getting issue'): issue = self._GetIssue(mr) if issue is None: self.abort(404, 'issue not found') # We give no explanation of missing issues on the peek page. if issue is None or issue.deleted: self.abort(404, 'issue not found') star_cnxn = sql.MonorailConnection() star_promise = framework_helpers.Promise( self.services.issue_star.IsItemStarredBy, star_cnxn, issue.issue_id, mr.auth.user_id) with self.profiler.Phase('getting project issue config'): config = self.services.config.GetProjectConfig(mr.cnxn, mr.project_id) with self.profiler.Phase('finishing getting comments'): comments = self.services.issue.GetCommentsForIssue( mr.cnxn, issue.issue_id) descriptions, visible_comments, cmnt_pagination = PaginateComments( mr, issue, comments, config) with self.profiler.Phase('making user proxies'): involved_user_ids = tracker_bizobj.UsersInvolvedInIssues([issue]) group_ids = self.services.usergroup.DetermineWhichUserIDsAreGroups( mr.cnxn, involved_user_ids) comment_user_ids = tracker_bizobj.UsersInvolvedInCommentList( descriptions + visible_comments) users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, involved_user_ids, comment_user_ids, group_ids=group_ids) framework_views.RevealAllEmailsToMembers(mr, users_by_id) (issue_view, description_views, comment_views) = self._MakeIssueAndCommentViews( mr, issue, users_by_id, descriptions, visible_comments, config) with self.profiler.Phase('getting starring info'): starred = star_promise.WaitAndGetValue() star_cnxn.Close() permit_edit = permissions.CanEditIssue( mr.auth.effective_ids, mr.perms, mr.project, issue) mr.ComputeColSpec(config) restrict_to_known = config.restrict_to_known page_perms = self.MakePagePerms( mr, issue, permissions.CREATE_ISSUE, permissions.SET_STAR, permissions.EDIT_ISSUE, permissions.EDIT_ISSUE_SUMMARY, permissions.EDIT_ISSUE_STATUS, permissions.EDIT_ISSUE_OWNER, permissions.EDIT_ISSUE_CC, permissions.DELETE_ISSUE, permissions.ADD_ISSUE_COMMENT, permissions.DELETE_OWN, permissions.DELETE_ANY, permissions.VIEW_INBOUND_MESSAGES) page_perms.EditIssue = ezt.boolean(permit_edit) prevent_restriction_removal = ( mr.project.only_owners_remove_restrictions and not framework_bizobj.UserOwnsProject( mr.project, mr.auth.effective_ids)) cmd_slots, default_slot_num = self.services.features.GetRecentCommands( mr.cnxn, mr.auth.user_id, mr.project_id) cmd_slot_views = [ template_helpers.EZTItem( slot_num=slot_num, command=command, comment=comment) for slot_num, command, comment in cmd_slots] previous_locations = self.GetPreviousLocations(mr, issue) return { 'issue_tab_mode': 'issueDetail', 'issue': issue_view, 'description': description_views, 'comments': comment_views, 'labels': issue.labels, 'num_detail_rows': len(comment_views) + 4, 'noisy': ezt.boolean(tracker_helpers.IsNoisy( len(comment_views), issue.star_count)), 'cmnt_pagination': cmnt_pagination, 'colspec': mr.col_spec, 'searchtip': 'You can jump to any issue by number', 'starred': ezt.boolean(starred), 'pagegen': str(long(time.time() * 1000000)), 'set_star_token': xsrf.GenerateToken( mr.auth.user_id, '/p/%s%s' % ( # Note: no .do suffix. mr.project_name, urls.ISSUE_SETSTAR_JSON)), 'restrict_to_known': ezt.boolean(restrict_to_known), 'prevent_restriction_removal': ezt.boolean( prevent_restriction_removal), 'statuses_offer_merge': config.statuses_offer_merge, 'page_perms': page_perms, 'cmd_slots': cmd_slot_views, 'default_slot_num': default_slot_num, 'quick_edit_submit_url': tracker_helpers.FormatRelativeIssueURL( issue.project_name, urls.ISSUE_PEEK + '.do', id=issue.local_id), 'previous_locations': previous_locations, # for template issue-meta-part shared by issuedetail servlet 'user_hotlists': [], 'user_issue_hotlists': [], 'involved_users_issue_hotlists': [], 'remaining_issue_hotlists': [], }
def GatherBaseData(self, mr, nonce): """Return a dict of info used on almost all pages.""" project = mr.project project_summary = '' project_alert = None project_read_only = False project_home_page = '' project_thumbnail_url = '' if project: project_summary = project.summary project_alert = _CalcProjectAlert(project) project_read_only = project.read_only_reason project_home_page = project.home_page project_thumbnail_url = tracker_views.LogoView( project).thumbnail_url with work_env.WorkEnv(mr, self.services) as we: is_project_starred = False project_view = None if mr.project: if permissions.UserCanViewProject(mr.auth.user_pb, mr.auth.effective_ids, mr.project): is_project_starred = we.IsProjectStarred(mr.project_id) # TODO(jrobbins): should this be a ProjectView? project_view = template_helpers.PBProxy(mr.project) grid_x_attr = None grid_y_attr = None hotlist_view = None if mr.hotlist: users_by_id = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, features_bizobj.UsersInvolvedInHotlists([mr.hotlist])) hotlist_view = hotlist_views.HotlistView( mr.hotlist, mr.perms, mr.auth, mr.viewed_user_auth.user_id, users_by_id, self.services.hotlist_star.IsItemStarredBy( mr.cnxn, mr.hotlist.hotlist_id, mr.auth.user_id)) grid_x_attr = mr.x.lower() grid_y_attr = mr.y.lower() app_version = os.environ.get('CURRENT_VERSION_ID') viewed_username = None if mr.viewed_user_auth.user_view: viewed_username = mr.viewed_user_auth.user_view.username issue_entry_url = 'entry' config = None if mr.project_id and self.services.config: with mr.profiler.Phase('getting config'): config = self.services.config.GetProjectConfig( mr.cnxn, mr.project_id) grid_x_attr = (mr.x or config.default_x_attr).lower() grid_y_attr = (mr.y or config.default_y_attr).lower() issue_entry_url = _LoginOrIssueEntryURL(mr, config) viewing_self = mr.auth.user_id == mr.viewed_user_auth.user_id offer_saved_queries_subtab = (viewing_self or mr.auth.user_pb and mr.auth.user_pb.is_site_admin) login_url = _SafeCreateLoginURL(mr) logout_url = _SafeCreateLogoutURL(mr) logout_url_goto_home = users.create_logout_url('/') version_base = _VersionBaseURL(mr.request) base_data = { # EZT does not have constants for True and False, so we pass them in. 'True': ezt.boolean(True), 'False': ezt.boolean(False), 'local_mode': ezt.boolean(settings.local_mode), 'site_name': settings.site_name, 'show_search_metadata': ezt.boolean(False), 'page_template': self._PAGE_TEMPLATE, 'main_tab_mode': self._MAIN_TAB_MODE, 'project_summary': project_summary, 'project_home_page': project_home_page, 'project_thumbnail_url': project_thumbnail_url, 'hotlist_id': mr.hotlist_id, 'hotlist': hotlist_view, 'hostport': mr.request.host, 'absolute_base_url': '%s://%s' % (mr.request.scheme, mr.request.host), 'project_home_url': None, 'link_rel_canonical': None, # For specifying <link rel="canonical"> 'projectname': mr.project_name, 'project': project_view, 'project_is_restricted': ezt.boolean(_ProjectIsRestricted(mr)), 'offer_contributor_list': ezt.boolean(permissions.CanViewContributorList(mr, mr.project)), 'logged_in_user': mr.auth.user_view, 'form_token': None, # Set to a value below iff the user is logged in. 'form_token_path': None, 'token_expires_sec': None, 'xhr_token': None, # Set to a value below iff the user is logged in. 'flag_spam_token': None, 'nonce': nonce, 'perms': mr.perms, 'warnings': mr.warnings, 'errors': mr.errors, 'viewed_username': viewed_username, 'viewed_user': mr.viewed_user_auth.user_view, 'viewed_user_pb': template_helpers.PBProxy(mr.viewed_user_auth.user_pb), 'viewing_self': ezt.boolean(viewing_self), 'viewed_user_id': mr.viewed_user_auth.user_id, 'offer_saved_queries_subtab': ezt.boolean(offer_saved_queries_subtab), 'currentPageURL': mr.current_page_url, 'currentPageURLEncoded': mr.current_page_url_encoded, 'login_url': login_url, 'logout_url': logout_url, 'logout_url_goto_home': logout_url_goto_home, 'continue_issue_id': mr.continue_issue_id, 'feedback_email': settings.feedback_email, 'category_css': None, # Used to specify a category of stylesheet 'category2_css': None, # specify a 2nd category of stylesheet if needed. 'page_css': None, # Used to add a stylesheet to a specific page. 'can': mr.can, 'query': mr.query, 'colspec': None, 'sortspec': mr.sort_spec, # Options for issuelist display 'grid_x_attr': grid_x_attr, 'grid_y_attr': grid_y_attr, 'grid_cell_mode': mr.cells, 'grid_mode': None, 'list_mode': None, 'chart_mode': None, 'issue_entry_url': issue_entry_url, 'is_cross_project': ezt.boolean(False), # for project search (some also used in issue search) 'start': mr.start, 'num': mr.num, 'groupby': mr.group_by_spec, 'q_field_size': (min( framework_constants.MAX_ARTIFACT_SEARCH_FIELD_SIZE, max(framework_constants.MIN_ARTIFACT_SEARCH_FIELD_SIZE, len(mr.query) + framework_constants.AUTOSIZE_STEP))), 'mode': None, # Display mode, e.g., grid mode. 'ajah': mr.ajah, 'table_title': mr.table_title, 'alerts': alerts.AlertsView(mr), # For alert.ezt 'project_alert': project_alert, 'title': None, # First part of page title 'title_summary': None, # Appended to title on artifact detail pages # TODO(jrobbins): make sure that the templates use # project_read_only for project-mutative actions and if any # uses of read_only remain. 'project_read_only': ezt.boolean(project_read_only), 'site_read_only': ezt.boolean(settings.read_only), 'banner_time': servlet_helpers.GetBannerTime(settings.banner_time), 'read_only': ezt.boolean(settings.read_only or project_read_only), 'site_banner_message': settings.banner_message, 'robots_no_index': None, 'analytics_id': settings.analytics_id, 'is_project_starred': ezt.boolean(is_project_starred), 'version_base': version_base, 'app_version': app_version, 'gapi_client_id': settings.gapi_client_id, 'viewing_user_page': ezt.boolean(False), 'old_ui_url': None, 'is_member': ezt.boolean(False), } if mr.project: base_data['project_home_url'] = '/p/%s' % mr.project_name # Always add xhr-xsrf token because even anon users need some # pRPC methods, e.g., autocomplete, flipper, and charts. base_data['token_expires_sec'] = xsrf.TokenExpiresSec() base_data['xhr_token'] = xsrf.GenerateToken(mr.auth.user_id, xsrf.XHR_SERVLET_PATH) # Always add other anti-xsrf tokens when the user is logged in. if mr.auth.user_id: form_token_path = self._FormHandlerURL(mr.request.path) base_data['form_token'] = xsrf.GenerateToken( mr.auth.user_id, form_token_path) base_data['form_token_path'] = form_token_path return base_data
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page.""" viewed_user = mr.viewed_user_auth.user_pb if self.services.usergroup.GetGroupSettings( mr.cnxn, mr.viewed_user_auth.user_id): url = framework_helpers.FormatAbsoluteURL(mr, '/g/%s/' % viewed_user.email, include_project=False) self.redirect(url, abort=True) # Show group page instead. with self.profiler.Phase('GetUserProjects'): project_lists = sitewide_helpers.GetUserProjects( mr.cnxn, self.services, mr.auth.user_pb, mr.auth.effective_ids, mr.viewed_user_auth.effective_ids) (visible_ownership, visible_archived, visible_membership, visible_contrib) = project_lists viewed_user_display_name = framework_views.GetViewedUserDisplayName(mr) with self.profiler.Phase('GetStarredProjects'): starred_projects = sitewide_helpers.GetViewableStarredProjects( mr.cnxn, self.services, mr.viewed_user_auth.user_id, mr.auth.effective_ids, mr.auth.user_pb) logged_in_starred_pids = [] if mr.auth.user_id: logged_in_starred_pids = self.services.project_star.LookupStarredItemIDs( mr.cnxn, mr.auth.user_id) starred_user_ids = self.services.user_star.LookupStarredItemIDs( mr.cnxn, mr.viewed_user_auth.user_id) starred_user_dict = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, starred_user_ids) starred_users = starred_user_dict.values() is_user_starred = self._IsUserStarred(mr.cnxn, mr.auth.user_id, mr.viewed_user_auth.user_id) if viewed_user.last_visit_timestamp: last_visit_str = timestr.FormatRelativeDate( viewed_user.last_visit_timestamp, days_only=True) last_visit_str = last_visit_str or 'Less than 2 days ago' else: last_visit_str = 'Never' if viewed_user.email_bounce_timestamp: last_bounce_str = timestr.FormatRelativeDate( viewed_user.email_bounce_timestamp, days_only=True) last_bounce_str = last_bounce_str or 'Less than 2 days ago' else: last_bounce_str = None can_ban = permissions.CanBan(mr, self.services) viewed_user_is_spammer = viewed_user.banned.lower() == 'spam' viewed_user_may_be_spammer = not viewed_user_is_spammer all_projects = self.services.project.GetAllProjects(mr.cnxn) for project_id in all_projects: project = all_projects[project_id] viewed_user_perms = permissions.GetPermissions( viewed_user, mr.viewed_user_auth.effective_ids, project) if (viewed_user_perms != permissions.EMPTY_PERMISSIONSET and viewed_user_perms != permissions.USER_PERMISSIONSET): viewed_user_may_be_spammer = False ban_token = None ban_spammer_token = None if mr.auth.user_id and can_ban: form_token_path = mr.request.path + 'ban.do' ban_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path) form_token_path = mr.request.path + 'banSpammer.do' ban_spammer_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path) page_data = { 'user_tab_mode': 'st2', 'viewed_user_display_name': viewed_user_display_name, 'viewed_user_may_be_spammer': ezt.boolean(viewed_user_may_be_spammer), 'viewed_user_is_spammer': ezt.boolean(viewed_user_is_spammer), 'viewed_user_is_banned': ezt.boolean(viewed_user.banned), 'viewed_user_ignore_action_limits': (ezt.boolean(viewed_user.ignore_action_limits)), 'owner_of_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_ownership ], 'committer_of_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_membership ], 'contributor_to_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_contrib ], 'owner_of_archived_projects': [project_views.ProjectView(p) for p in visible_archived], 'starred_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in starred_projects ], 'starred_users': starred_users, 'is_user_starred': ezt.boolean(is_user_starred), 'viewing_user_page': ezt.boolean(True), 'last_visit_str': last_visit_str, 'last_bounce_str': last_bounce_str, 'vacation_message': viewed_user.vacation_message, 'can_ban': ezt.boolean(can_ban), 'ban_token': ban_token, 'ban_spammer_token': ban_spammer_token } settings = framework_helpers.UserSettings.GatherUnifiedSettingsPageData( mr.auth.user_id, mr.viewed_user_auth.user_view, viewed_user) page_data.update(settings) return page_data
def testWrongUser(self): token = xsrf.GenerateToken(111, '/path') self.assertRaises( xsrf.TokenIncorrect, xsrf.ValidateToken, token, 222, '/path')
def GatherPageData(self, mr): """Build up a dictionary of data values to use when rendering the page.""" viewed_user = mr.viewed_user_auth.user_pb if self.services.usergroup.GetGroupSettings( mr.cnxn, mr.viewed_user_auth.user_id): url = framework_helpers.FormatAbsoluteURL(mr, '/g/%s/' % viewed_user.email, include_project=False) self.redirect(url, abort=True) # Show group page instead. with work_env.WorkEnv(mr, self.services) as we: project_lists = we.GetUserProjects( mr.viewed_user_auth.effective_ids) (visible_ownership, visible_archived, visible_membership, visible_contrib) = project_lists with mr.profiler.Phase('Getting user groups'): group_settings = self.services.usergroup.GetAllGroupSettings( mr.cnxn, mr.viewed_user_auth.effective_ids) member_ids, owner_ids = self.services.usergroup.LookupAllMembers( mr.cnxn, list(group_settings.keys())) friend_project_ids = [] # TODO(issue 4202): implement this. visible_group_ids = [] for group_id in group_settings: if permissions.CanViewGroupMembers(mr.perms, mr.auth.effective_ids, group_settings[group_id], member_ids[group_id], owner_ids[group_id], friend_project_ids): visible_group_ids.append(group_id) user_group_views = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, visible_group_ids) user_group_views = sorted(list(user_group_views.values()), key=lambda ugv: ugv.email) with mr.profiler.Phase('Getting linked accounts'): linked_parent = None linked_children = [] linked_views = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, [viewed_user.linked_parent_id], viewed_user.linked_child_ids) if viewed_user.linked_parent_id: linked_parent = linked_views[viewed_user.linked_parent_id] if viewed_user.linked_child_ids: linked_children = [ linked_views[child_id] for child_id in viewed_user.linked_child_ids ] offer_unlink = (mr.auth.user_id == viewed_user.user_id or mr.auth.user_id in linked_views) incoming_invite_users = [] outgoing_invite_users = [] possible_parent_accounts = [] can_edit_invites = mr.auth.user_id == mr.viewed_user_auth.user_id display_link_invites = can_edit_invites or mr.auth.user_pb.is_site_admin # TODO(jrobbins): allow site admin to edit invites for other users. if display_link_invites: with work_env.WorkEnv(mr, self.services, phase='Getting link invites'): incoming_invite_ids, outgoing_invite_ids = we.GetPendingLinkedInvites( user_id=viewed_user.user_id) invite_views = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, incoming_invite_ids, outgoing_invite_ids) incoming_invite_users = [ invite_views[uid] for uid in incoming_invite_ids ] outgoing_invite_users = [ invite_views[uid] for uid in outgoing_invite_ids ] possible_parent_accounts = _ComputePossibleParentAccounts( we, mr.viewed_user_auth.user_view, linked_parent, linked_children) viewed_user_display_name = framework_views.GetViewedUserDisplayName(mr) with work_env.WorkEnv(mr, self.services) as we: starred_projects = we.ListStarredProjects( viewed_user_id=mr.viewed_user_auth.user_id) logged_in_starred = we.ListStarredProjects() logged_in_starred_pids = {p.project_id for p in logged_in_starred} starred_user_ids = self.services.user_star.LookupStarredItemIDs( mr.cnxn, mr.viewed_user_auth.user_id) starred_user_dict = framework_views.MakeAllUserViews( mr.cnxn, self.services.user, starred_user_ids) starred_users = list(starred_user_dict.values()) starred_users_json = json.dumps( [uv.display_name for uv in starred_users]) is_user_starred = self._IsUserStarred(mr.cnxn, mr.auth.user_id, mr.viewed_user_auth.user_id) if viewed_user.last_visit_timestamp: last_visit_str = timestr.FormatRelativeDate( viewed_user.last_visit_timestamp, days_only=True) last_visit_str = last_visit_str or 'Less than 2 days ago' else: last_visit_str = 'Never' if viewed_user.email_bounce_timestamp: last_bounce_str = timestr.FormatRelativeDate( viewed_user.email_bounce_timestamp, days_only=True) last_bounce_str = last_bounce_str or 'Less than 2 days ago' else: last_bounce_str = None can_ban = permissions.CanBan(mr, self.services) viewed_user_is_spammer = viewed_user.banned.lower() == 'spam' viewed_user_may_be_spammer = not viewed_user_is_spammer all_projects = self.services.project.GetAllProjects(mr.cnxn) for project_id in all_projects: project = all_projects[project_id] viewed_user_perms = permissions.GetPermissions( viewed_user, mr.viewed_user_auth.effective_ids, project) if (viewed_user_perms != permissions.EMPTY_PERMISSIONSET and viewed_user_perms != permissions.USER_PERMISSIONSET): viewed_user_may_be_spammer = False ban_token = None ban_spammer_token = None if mr.auth.user_id and can_ban: form_token_path = mr.request.path + 'ban.do' ban_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path) form_token_path = mr.request.path + 'banSpammer.do' ban_spammer_token = xsrf.GenerateToken(mr.auth.user_id, form_token_path) page_data = { 'user_tab_mode': 'st2', 'viewed_user_display_name': viewed_user_display_name, 'viewed_user_may_be_spammer': ezt.boolean(viewed_user_may_be_spammer), 'viewed_user_is_spammer': ezt.boolean(viewed_user_is_spammer), 'viewed_user_is_banned': ezt.boolean(viewed_user.banned), 'owner_of_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_ownership ], 'committer_of_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_membership ], 'contributor_to_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in visible_contrib ], 'owner_of_archived_projects': [project_views.ProjectView(p) for p in visible_archived], 'starred_projects': [ project_views.ProjectView(p, starred=p.project_id in logged_in_starred_pids) for p in starred_projects ], 'starred_users': starred_users, 'starred_users_json': starred_users_json, 'is_user_starred': ezt.boolean(is_user_starred), 'viewing_user_page': ezt.boolean(True), 'last_visit_str': last_visit_str, 'last_bounce_str': last_bounce_str, 'vacation_message': viewed_user.vacation_message, 'can_ban': ezt.boolean(can_ban), 'ban_token': ban_token, 'ban_spammer_token': ban_spammer_token, 'user_groups': user_group_views, 'linked_parent': linked_parent, 'linked_children': linked_children, 'incoming_invite_users': incoming_invite_users, 'outgoing_invite_users': outgoing_invite_users, 'possible_parent_accounts': possible_parent_accounts, 'can_edit_invites': ezt.boolean(can_edit_invites), 'offer_unlink': ezt.boolean(offer_unlink), } viewed_user_prefs = None if mr.perms.HasPerm(permissions.EDIT_OTHER_USERS, None, None): with work_env.WorkEnv(mr, self.services) as we: viewed_user_prefs = we.GetUserPrefs( mr.viewed_user_auth.user_id) user_settings = ( framework_helpers.UserSettings.GatherUnifiedSettingsPageData( mr.auth.user_id, mr.viewed_user_auth.user_view, viewed_user, viewed_user_prefs)) page_data.update(user_settings) return page_data
def testValidToken(self): token = xsrf.GenerateToken(111, '/path') xsrf.ValidateToken(token, 111, '/path') # no exception raised