def testGoodTokenWithNoPriorTokenKey(self): # config seems to be shared across tests, so we have to specifically set # it to None. config.set(xsrf_token_key=None) tool = utils.XsrfTool() token = tool.generate_token(12345, 'test_action') self.assertTrue(tool.verify_token(token, 12345, 'test_action'))
def testRejectsInvalidToken(self): config.set(xsrf_token_key='abcdef') tool = utils.XsrfTool() timestamp = utils.get_timestamp(XsrfToolTests.TEST_NOW) self.assertFalse( tool.verify_token('NotTheRightDigest/%f' % timestamp, 12345, 'test_action'))
def render_form(self, authorization=None, message=''): """Display a form for create/update Authorization""" user = users.get_current_user() if authorization: operation_name = _('Update an existing key') nav_html = ('<a href="%s">%s</a> ' % (self.get_url('admin/api_keys'), escape(_('Create a new API key')))) else: authorization = Authorization.DEFAULT_SETTINGS operation_name = _('Create a new API key') nav_html = '' nav_html += ( '<a href="%s">%s</a>' % (self.get_url('admin/api_keys/list'), escape(_('List API keys')))) user_email_with_tags = ('<span class="email">%s</span>' % escape(user.email())) xsrf_tool = utils.XsrfTool() return self.render( 'admin_api_keys.html', user=user, target_key=authorization, user_email_with_tags=user_email_with_tags, login_url=users.create_login_url(self.request.url), logout_url=users.create_logout_url(self.request.url), operation_name=operation_name, message=message, nav_html=nav_html, xsrf_token=xsrf_tool.generate_token(user.user_id(), 'admin_api_keys'), )
def post(self): user = users.get_current_user() xsrf_tool = utils.XsrfTool() if not (self.params.xsrf_token and xsrf_tool.verify_token( self.params.xsrf_token, user.user_id(), 'admin_review')): self.error(403) return False if not self.is_current_user_authorized(): return self.redirect(users.create_login_url('/admin/review')) notes = [] for name, value in self.request.params.items(): if name.startswith('note.'): note = model.Note.get(self.repo, name[5:]) if note: if value in ['accept', 'flag']: note.reviewed = True if value == 'flag': note.hidden = True notes.append(note) db.put(notes) self.redirect('/admin/review', status=self.params.status, source=self.params.source, skip=str(self.params.skip))
def testRejectsExpiredToken(self): config.set(xsrf_token_key='abcdef') tool = utils.XsrfTool() token = tool.generate_token(12345, 'test_action') utils.set_utcnow_for_test(XsrfToolTests.TEST_NOW + datetime.timedelta(hours=4, minutes=1)) self.assertFalse(tool.verify_token(token, 12345, 'test_action'))
def testBadTokenWithNoPriorTokenKey(self): # config seems to be shared across tests, so we have to specifically set # it to None. config.set(xsrf_token_key=None) tool = utils.XsrfTool() timestamp = utils.get_timestamp(XsrfToolTests.TEST_NOW) self.assertFalse( tool.verify_token('NotTheRightDigest/%f' % timestamp, 12345, 'test_action'))
def test_rejects_invalid_tokens(self): """Tests that an invalid token is rejected.""" config.set(xsrf_token_key='abcdef') tool = utils.XsrfTool() self.assertFalse(tool.verify_token( 'ThisTokenDoesNotEvenHaveASlash', 12345, 'test_action')) timestamp = utils.get_timestamp(XsrfToolTests.TEST_NOW) self.assertFalse( tool.verify_token('NotTheRightDigest/%f' % timestamp, 12345, 'test_action'))
def test_good_with_no_prior_key(self): """Tests a good token when a token key has to be autogenerated. If the config doesn't already have an XSRF token key set, the XSRF tool will generate one automatically. """ # config seems to be shared across tests, so we have to specifically set # it to None. config.set(xsrf_token_key=None) tool = utils.XsrfTool() token = tool.generate_token(12345, 'test_action') self.assertTrue(tool.verify_token(token, 12345, 'test_action'))
def test_bad_with_no_prior_key(self): """Tests a bad token when a token key has to be autogenerated. If the config doesn't already have an XSRF token key set, the XSRF tool will generate one automatically. """ # config seems to be shared across tests, so we have to specifically set # it to None. config.set(xsrf_token_key=None) tool = utils.XsrfTool() timestamp = utils.get_timestamp(XsrfToolTests.TEST_NOW) self.assertFalse( tool.verify_token('NotTheRightDigest/%f' % timestamp, 12345, 'test_action'))
def setup(self, request, *args, **kwargs): """See docs on BaseView.setup.""" # pylint: disable=attribute-defined-outside-init super(AdminBaseView, self).setup(request, *args, **kwargs) self.env.show_logo = True self.env.enable_javascript = True self.env.user = users.get_current_user() self.env.user_admin_permission = self._get_user_admin_permission() self.env.logout_url = users.create_logout_url( self.build_absolute_uri()) self.env.all_repo_options = [ utils.Struct(repo=repo, url=self.build_absolute_path('/%s/admin' % repo)) for repo in sorted(model.Repo.list()) ] self.xsrf_tool = utils.XsrfTool()
def post(self): """Handle a post request from the create/update/edit form""" user = users.get_current_user() xsrf_tool = utils.XsrfTool() if not (self.params.xsrf_token and xsrf_tool.verify_token( self.params.xsrf_token, user.user_id(), 'admin_api_keys')): return self.error(403) # Handle a form submission from list page if self.request.get('edit_form'): authorization = db.get(self.request.get('authorization_key')) if not authorization: return self.error(404, _('No such Authorization entity.')) return self.render_form(authorization) # Handle authorization form submission if not (self.params.contact_name and self.params.contact_email and self.params.organization_name): return self.error(400, _('Please fill in all the required fields.')) original_key = self.request.get('key') if original_key: # just override the existing one existing_authorization = db.get(original_key) if not existing_authorization: return self.error(404, _('No such Authorization entity.')) key_str = existing_authorization.api_key action = ApiKeyManagementLog.UPDATE else: key_str = utils.generate_random_key(API_KEY_LENGTH) action = ApiKeyManagementLog.CREATE repo = self.repo or '*' authorization = Authorization.create( repo, key_str, **to_authorization_params(self.params)) authorization.put() management_log = ApiKeyManagementLog(repo=repo, api_key=authorization.api_key, action=action) management_log.put() self.redirect('/admin/api_keys?repo=%s&log_key=%s' % (self.repo, management_log.key()))
def setUp(self): super(ViewTestsBase, self).setUp() self._xsrf_tool = utils.XsrfTool() self.data_generator.admin_permission( repo_id='global', email_address='*****@*****.**', access_level= admin_acls_model.AdminPermission.AccessLevel.SUPERADMIN, expiration_date=datetime.datetime(2051, 1, 20)) self.data_generator.admin_permission( repo_id='global', email_address='*****@*****.**', access_level=admin_acls_model.AdminPermission.AccessLevel.MANAGER, expiration_date=datetime.datetime(2051, 1, 20)) self.data_generator.admin_permission( repo_id='global', email_address='*****@*****.**', access_level=admin_acls_model.AdminPermission.AccessLevel.MODERATOR, expiration_date=datetime.datetime(2051, 1, 20)) self._current_user_id = None
def get(self): user = users.get_current_user() q = Authorization.all().filter('repo =', self.repo or '*') authorizations = q.fetch(KEYS_PER_PAGE) nav_html = ('<a href="%s">%s</a> ' % (self.get_url('admin/api_keys'), escape(_('Create a new API key')))) user_email_with_tags = ('<span class="email">%s</span>' % escape(user.email())) xsrf_tool = utils.XsrfTool() return self.render('admin_api_keys_list.html', nav_html=nav_html, admin_api_keys_url=self.get_url('/admin/api_keys'), user=user, authorizations=authorizations, user_email_with_tags=user_email_with_tags, xsrf_token=xsrf_tool.generate_token( user.user_id(), 'admin_api_keys'))
def testGenerateAndVerifyGoodToken(self): config.set(xsrf_token_key='abcdef') tool = utils.XsrfTool() token = tool.generate_token(12345, 'test_action') self.assertTrue(tool.verify_token(token, 12345, 'test_action'))
def _get_xsrf_token(self): user = users.get_current_user() xsrf_tool = utils.XsrfTool() return xsrf_tool.generate_token(user.user_id(), 'admin_resources')
def test_gen_and_verify_good_token(self): """Tests generating and verifying a good token.""" config.set(xsrf_token_key='abcdef') tool = utils.XsrfTool() token = tool.generate_token(12345, 'test_action') self.assertTrue(tool.verify_token(token, 12345, 'test_action'))
def get(self): if not self.is_current_user_authorized(): return self.redirect(users.create_login_url('/admin/review')) # Make the navigation links. status = self.request.get('status') or 'all' source = self.request.get('source') or 'all' status_nav_html = '' for option in [ 'all', 'unspecified', 'information_sought', 'is_note_author', 'believed_alive', 'believed_missing', 'believed_dead' ]: if option == status: status_nav_html += '<b>%s</b> ' % option else: status_nav_html += '<a href="%s">%s</a> ' % ( self.get_url('/admin/review', status=option, source=source), option) source_nav_html = '' source_options = ['all', '%s.%s' % (self.repo, const.HOME_DOMAIN)] for auth_key in model.Authorization.all().filter('repo =', self.repo): if auth_key.domain_write_permission: source_options.append(auth_key.domain_write_permission) for option in source_options: if option == source: source_nav_html += '<b>%s</b> ' % option else: source_nav_html += '<a href="%s">%s</a> ' % ( self.get_url('/admin/review', status=status, source=option), option) # # Construct the query for notes. query = model.Note.all_in_repo(self.repo).filter('reviewed =', False).filter( 'hidden =', False) if status == 'unspecified': query.filter('status =', '') elif status != 'all': query.filter('status =', status) if source != 'all': query.filter('person_record_id >=', '%s/' % source) query.filter('person_record_id <', '%s0' % source) # TODO(ryok): we really want to order by entry_date, but GAE # restriction applies here, and we can not use two different # properties for comparison and ordering. The proper solution seems # to add a property source_domain to Note. query.order('-person_record_id') else: query.order('-entry_date') skip = self.params.skip or 0 notes = query.fetch(NOTES_PER_PAGE + 1, skip) for note in notes[:NOTES_PER_PAGE]: person = model.Person.get(self.repo, note.person_record_id) if person: # Copy in the fields of the associated Person. for name in person.properties(): setattr(note, 'person_' + name, getattr(person, name)) # Get the statuses of the other notes on this Person. status_codes = '' for other_note in person.get_notes(): code = STATUS_CODES[other_note.status] if other_note.note_record_id == note.note_record_id: code = code.upper() status_codes += code note.person_status_codes = status_codes note.source_date_string = self.format_datetime_localized( note.source_date) note.entry_date_string = self.format_datetime_localized( note.entry_date) if len(notes) > NOTES_PER_PAGE: notes = notes[:NOTES_PER_PAGE] next_skip = skip + NOTES_PER_PAGE next_url = self.get_url('/admin/review', skip=str(next_skip), status=status, source=source) else: next_url = None user = users.get_current_user() xsrf_tool = utils.XsrfTool() return self.render('admin_review.html', notes=notes, status_nav_html=status_nav_html, source_nav_html=source_nav_html, next_url=next_url, first=skip + 1, last=skip + len(notes[:NOTES_PER_PAGE]), xsrf_token=xsrf_tool.generate_token( user.user_id(), 'admin_review'))
def handle(self, operation): """Handles both GET and POST requests. POST requests include an 'operation' param describing what the user is trying to change.""" bundle_name = self.params.resource_bundle or '' name = self.params.resource_name or '' lang = self.params.resource_lang or '' key_name = name + (lang and ':' + lang) editable = (bundle_name != self.env.default_resource_bundle) if not ResourceBundle.get_by_key_name(self.env.default_resource_bundle): ResourceBundle(key_name=self.env.default_resource_bundle).put() if not operation: self.write(PREFACE + self.format_nav_html(bundle_name, name, lang)) if bundle_name and name: self.show_resource(bundle_name, key_name, name, lang, editable) elif bundle_name: self.list_resources(bundle_name, editable) else: self.list_bundles() return user = users.get_current_user() xsrf_tool = utils.XsrfTool() if not (self.params.xsrf_token and xsrf_tool.verify_token( self.params.xsrf_token, user.user_id(), 'admin_resources')): return self.error(403) if operation == 'set_preview': # Set the resource_bundle cookie. This causes all pages to render # using the selected bundle (see main.py). We use a cookie so that # it's possible to preview PF as embedded on external sites. self.response.headers['Set-Cookie'] = \ 'resource_bundle=%s; path=/' % bundle_name return self.redirect(self.get_admin_url()) if operation == 'set_default': # Set the default resource bundle. config.set(default_resource_bundle= self.params.resource_bundle_default) return self.redirect(self.get_admin_url()) if operation == 'add_bundle' and editable: # Add a new bundle, optionally copying from an existing bundle. put_bundle(bundle_name, self.params.resource_bundle_original) return self.redirect(self.get_admin_url(bundle_name)) if operation == 'add_resource' and editable: # Go to the edit page for a new resource (don't create until save). return self.redirect(self.get_admin_url(bundle_name, name, lang)) if operation == 'delete_resource' and editable: # Delete a resource. resource = Resource.get(key_name, bundle_name) if resource: resource.delete() return self.redirect(self.get_admin_url(bundle_name)) if operation == 'put_resource' and editable: # Store the content of a resource. if isinstance(self.request.POST.get('file'), cgi.FieldStorage): content = self.request.get('file') # uploaded file content elif 'content' in self.request.POST: # edited text content = self.request.get('content').encode('utf-8') else: # modify cache_seconds but leave content unchanged resource = Resource.get(key_name, bundle_name) content = resource and resource.content or '' put_resource(bundle_name, key_name, content=content, cache_seconds=self.params.cache_seconds) return self.redirect(self.get_admin_url(bundle_name))