def test_interpolate_cache_slug(self): with self.swap(feconf, 'DEV_MODE', True): utils.ASSET_DIR_PREFIX = None cache_slug = utils.get_asset_dir_prefix() parsed_str = jinja_utils.interpolate_cache_slug('{{cache_slug}}') self.assertEqual(parsed_str, '%s' % cache_slug) with self.swap(feconf, 'DEV_MODE', False): utils.ASSET_DIR_PREFIX = None cache_slug = utils.get_asset_dir_prefix() parsed_str = jinja_utils.interpolate_cache_slug('{{cache_slug}}') self.assertEqual(parsed_str, '%s' % cache_slug) with self.swap(feconf, 'IS_MINIFIED', True): utils.ASSET_DIR_PREFIX = None cache_slug = utils.get_asset_dir_prefix() parsed_str = jinja_utils.interpolate_cache_slug('{{cache_slug}}') self.assertEqual(parsed_str, '%s' % cache_slug) cache_slug = utils.get_asset_dir_prefix() parsed_str = jinja_utils.interpolate_cache_slug( '{{cache_slug}}/test/test.css') self.assertEqual(parsed_str, '%s/test/test.css' % cache_slug) # cache slug parameter is missing. parsed_str = jinja_utils.interpolate_cache_slug( '{{invalid_test}}/test/test.css') self.assertEqual(parsed_str, '/test/test.css')
def test_get_asset_dir_prefix_returns_correct_slug(self): with self.swap(feconf, 'DEV_MODE', True): utils.ASSET_DIR_PREFIX = None asset_dir_prefix = utils.get_asset_dir_prefix() self.assertEqual('', asset_dir_prefix) with self.swap(feconf, 'DEV_MODE', False): utils.ASSET_DIR_PREFIX = None asset_dir_prefix = utils.get_asset_dir_prefix() self.assertTrue(asset_dir_prefix.startswith('/build'))
def test_get_thumbnail_icon_url_for_category(self): self.assertEqual( utils.get_thumbnail_icon_url_for_category('Architecture'), '%s/assets/images/subjects/Architecture.svg' % utils.get_asset_dir_prefix()) self.assertEqual( utils.get_thumbnail_icon_url_for_category('Graph Theory'), '%s/assets/images/subjects/GraphTheory.svg' % utils.get_asset_dir_prefix()) self.assertEqual( utils.get_thumbnail_icon_url_for_category('Nonexistent'), '%s/assets/images/subjects/Lightbulb.svg' % utils.get_asset_dir_prefix())
def get_complete_static_resource_url(domain_url, resource_suffix): """Returns the relative path for the resource, appending it to the corresponding cache slug. resource_suffix should have a leading slash. """ return '%s%s%s' % ( domain_url, utils.get_asset_dir_prefix(), resource_suffix)
def test_get_asset_dir_prefix_returns_correct_slug(self): with self.swap(feconf, 'DEV_MODE', True): utils.ASSET_DIR_PREFIX = None asset_dir_prefix = utils.get_asset_dir_prefix() self.assertEqual('', asset_dir_prefix) with self.swap(feconf, 'DEV_MODE', False): utils.ASSET_DIR_PREFIX = None asset_dir_prefix = utils.get_asset_dir_prefix() self.assertTrue(asset_dir_prefix.startswith('/build')) with self.swap(feconf, 'IS_MINIFIED', True): utils.ASSET_DIR_PREFIX = None asset_dir_prefix = utils.get_asset_dir_prefix() self.assertTrue(asset_dir_prefix.startswith('/build'))
def get_complete_static_resource_url(domain_url, resource_suffix): """Returns the relative path for the resource, appending it to the corresponding cache slug. resource_suffix should have a leading slash. """ return '%s%s%s' % (domain_url, utils.get_asset_dir_prefix(), resource_suffix)
def interpolate_cache_slug(string): """Parses the cache slug in the input string. Returns: the parsed string, or None if the string could not be parsed. """ cache_slug = utils.get_asset_dir_prefix() return parse_string(string, {'cache_slug': cache_slug})
def get_complete_static_resource_url(domain_url, resource_suffix): """Returns the relative path for the resource, appending it to the corresponding cache slug. Args: domain_url: str. The url of the domain. resource_suffix: str. The resource suffix to get the relative path for the resource. It should have a leading slash. Returns: str. The relative path for the resource. """ return '%s%s%s' % ( domain_url, utils.get_asset_dir_prefix(), resource_suffix)
def test_get_asset_dir_prefix_with_prod_mode(self): with self.swap(constants, 'DEV_MODE', False): self.assertEqual(utils.get_asset_dir_prefix(), '/build')
def render_template(self, filepath, iframe_restriction='DENY', redirect_url_on_logout=None): """Prepares an HTML response to be sent to the client. Args: filepath: str. The template filepath. iframe_restriction: str or None. Possible values are 'DENY' and 'SAMEORIGIN': DENY: Strictly prevents the template to load in an iframe. SAMEORIGIN: The template can only be displayed in a frame on the same origin as the page itself. redirect_url_on_logout: str or None. URL to redirect to on logout. """ values = self.values scheme, netloc, path, _, _ = urlparse.urlsplit(self.request.uri) values.update({ 'ASSET_DIR_PREFIX': utils.get_asset_dir_prefix(), 'BEFORE_END_HEAD_TAG_HOOK': jinja2.utils.Markup(BEFORE_END_HEAD_TAG_HOOK.value), 'DEV_MODE': feconf.DEV_MODE, 'MINIFICATION': feconf.IS_MINIFIED, 'DOMAIN_URL': '%s://%s' % (scheme, netloc), 'ACTIVITY_STATUS_PRIVATE': (rights_manager.ACTIVITY_STATUS_PRIVATE), 'ACTIVITY_STATUS_PUBLIC': (rights_manager.ACTIVITY_STATUS_PUBLIC), 'GCS_RESOURCE_BUCKET_NAME': (app_identity_services.get_gcs_resource_bucket_name()), # The 'path' variable starts with a forward slash. 'FULL_URL': '%s://%s%s' % (scheme, netloc, path), 'INVALID_NAME_CHARS': feconf.INVALID_NAME_CHARS, 'RTE_COMPONENT_SPECS': (rte_component_registry.Registry.get_all_specs()), 'SITE_FEEDBACK_FORM_URL': feconf.SITE_FEEDBACK_FORM_URL, 'SITE_NAME': feconf.SITE_NAME, 'SYSTEM_USERNAMES': feconf.SYSTEM_USERNAMES, 'TEMPLATE_DIR_PREFIX': utils.get_template_dir_prefix(), 'can_create_collections': bool(self.role == feconf.ROLE_ID_COLLECTION_EDITOR), 'username': self.username, 'user_is_logged_in': user_services.has_fully_registered(self.user_id), 'preferred_site_language_code': self.preferred_site_language_code, 'allow_yaml_file_upload': feconf.ALLOW_YAML_FILE_UPLOAD }) if feconf.ENABLE_PROMO_BAR: promo_bar_enabled = config_domain.PROMO_BAR_ENABLED.value promo_bar_message = config_domain.PROMO_BAR_MESSAGE.value else: promo_bar_enabled = False promo_bar_message = '' values.update({ 'promo_bar_enabled': promo_bar_enabled, 'promo_bar_message': promo_bar_message, }) if 'meta_name' not in values: values['meta_name'] = 'Personalized Online Learning from Oppia' if 'meta_description' not in values: values['meta_description'] = ( 'Oppia is a free, open-source learning platform. Join the ' 'community to create or try an exploration today!') # nav_mode is used as part of the GLOBALS object in the frontend, but # not every backend handler declares a nav_mode. Thus, the following # code is a failsafe to ensure that the nav_mode key is added to all # page requests. if 'nav_mode' not in values: values['nav_mode'] = '' if redirect_url_on_logout is None: redirect_url_on_logout = self.request.uri if self.user_id: values['login_url'] = None values['logout_url'] = (current_user_services.create_logout_url( redirect_url_on_logout)) else: target_url = ('/' if self.request.uri.endswith(feconf.SPLASH_URL) else self.request.uri) values['login_url'] = ( current_user_services.create_login_url(target_url)) values['logout_url'] = None # Create a new csrf token for inclusion in HTML responses. This assumes # that tokens generated in one handler will be sent back to a handler # with the same page name. values['csrf_token'] = '' if self.REQUIRE_PAYLOAD_CSRF_CHECK: values['csrf_token'] = CsrfTokenManager.create_csrf_token( self.user_id) self.response.cache_control.no_cache = True self.response.cache_control.must_revalidate = True self.response.headers['Strict-Transport-Security'] = ( 'max-age=31536000; includeSubDomains') self.response.headers['X-Content-Type-Options'] = 'nosniff' if iframe_restriction is not None: if iframe_restriction in ['SAMEORIGIN', 'DENY']: self.response.headers['X-Frame-Options'] = iframe_restriction else: raise Exception('Invalid X-Frame-Options: %s' % iframe_restriction) self.response.expires = 'Mon, 01 Jan 1990 00:00:00 GMT' self.response.pragma = 'no-cache' self.response.write( self.jinja2_env.get_template(filepath).render(**values))
def render_template(self, filename, iframe_restriction='DENY', redirect_url_on_logout=None): values = self.values scheme, netloc, path, _, _ = urlparse.urlsplit(self.request.uri) values.update({ 'ALL_CATEGORIES': feconf.ALL_CATEGORIES, 'ALL_LANGUAGE_CODES': feconf.ALL_LANGUAGE_CODES, 'ASSET_DIR_PREFIX': utils.get_asset_dir_prefix(), 'BEFORE_END_HEAD_TAG_HOOK': jinja2.utils.Markup(BEFORE_END_HEAD_TAG_HOOK.value), 'CAN_SEND_ANALYTICS_EVENTS': feconf.CAN_SEND_ANALYTICS_EVENTS, 'DEFAULT_LANGUAGE_CODE': feconf.ALL_LANGUAGE_CODES[0]['code'], 'DEV_MODE': feconf.DEV_MODE, 'MINIFICATION': feconf.IS_MINIFIED, 'DOMAIN_URL': '%s://%s' % (scheme, netloc), 'ACTIVITY_STATUS_PRIVATE': (rights_manager.ACTIVITY_STATUS_PRIVATE), 'ACTIVITY_STATUS_PUBLIC': (rights_manager.ACTIVITY_STATUS_PUBLIC), 'ACTIVITY_STATUS_PUBLICIZED': (rights_manager.ACTIVITY_STATUS_PUBLICIZED), # The 'path' variable starts with a forward slash. 'FULL_URL': '%s://%s%s' % (scheme, netloc, path), 'INVALID_NAME_CHARS': feconf.INVALID_NAME_CHARS, 'RTE_COMPONENT_SPECS': (rte_component_registry.Registry.get_all_specs()), 'SITE_FEEDBACK_FORM_URL': SITE_FEEDBACK_FORM_URL.value, 'SITE_NAME': SITE_NAME.value, 'SUPPORTED_SITE_LANGUAGES': feconf.SUPPORTED_SITE_LANGUAGES, 'SYSTEM_USERNAMES': feconf.SYSTEM_USERNAMES, 'TEMPLATE_DIR_PREFIX': utils.get_template_dir_prefix(), 'can_create_collections': (self.username and self.username in config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value), 'user_is_logged_in': user_services.has_fully_registered(self.user_id), 'preferred_site_language_code': self.preferred_site_language_code }) if 'meta_name' not in values: values['meta_name'] = 'Personalized Online Learning from Oppia' if 'meta_description' not in values: values['meta_description'] = ( 'Oppia is a free, open-source learning platform. Join the ' 'community to create or try an exploration today!') # nav_mode is used as part of the GLOBALS object in the frontend, but # not every backend handler declares a nav_mode. Thus, the following # code is a failsafe to ensure that the nav_mode key is added to all # page requests. if 'nav_mode' not in values: values['nav_mode'] = '' if redirect_url_on_logout is None: redirect_url_on_logout = self.request.uri if self.user_id: values['logout_url'] = (current_user_services.create_logout_url( redirect_url_on_logout)) else: target_url = ('/' if self.request.uri.endswith(feconf.SPLASH_URL) else self.request.uri) values['login_url'] = ( current_user_services.create_login_url(target_url)) # Create a new csrf token for inclusion in HTML responses. This assumes # that tokens generated in one handler will be sent back to a handler # with the same page name. values['csrf_token'] = '' if self.REQUIRE_PAYLOAD_CSRF_CHECK: values['csrf_token'] = CsrfTokenManager.create_csrf_token( self.user_id) self.response.cache_control.no_cache = True self.response.cache_control.must_revalidate = True self.response.headers['Strict-Transport-Security'] = ( 'max-age=31536000; includeSubDomains') self.response.headers['X-Content-Type-Options'] = 'nosniff' if iframe_restriction is not None: if iframe_restriction in ['SAMEORIGIN', 'DENY']: self.response.headers['X-Frame-Options'] = iframe_restriction else: raise Exception('Invalid X-Frame-Options: %s' % iframe_restriction) self.response.expires = 'Mon, 01 Jan 1990 00:00:00 GMT' self.response.pragma = 'no-cache' self.response.write( self.jinja2_env.get_template(filename).render(**values))
def render_template( self, filename, iframe_restriction='DENY', redirect_url_on_logout=None): values = self.values scheme, netloc, path, _, _ = urlparse.urlsplit(self.request.uri) values.update({ 'ALL_CATEGORIES': feconf.ALL_CATEGORIES, 'ALL_LANGUAGE_CODES': feconf.ALL_LANGUAGE_CODES, 'ASSET_DIR_PREFIX': utils.get_asset_dir_prefix(), 'BEFORE_END_HEAD_TAG_HOOK': jinja2.utils.Markup( BEFORE_END_HEAD_TAG_HOOK.value), 'CAN_SEND_ANALYTICS_EVENTS': feconf.CAN_SEND_ANALYTICS_EVENTS, 'CATEGORIES_TO_COLORS': feconf.CATEGORIES_TO_COLORS, 'DEFAULT_LANGUAGE_CODE': feconf.ALL_LANGUAGE_CODES[0]['code'], 'DEFAULT_CATEGORY_ICON': feconf.DEFAULT_THUMBNAIL_ICON, 'DEFAULT_COLOR': feconf.DEFAULT_COLOR, 'DEV_MODE': feconf.DEV_MODE, 'MINIFICATION': feconf.IS_MINIFIED, 'DOMAIN_URL': '%s://%s' % (scheme, netloc), 'ACTIVITY_STATUS_PRIVATE': ( rights_manager.ACTIVITY_STATUS_PRIVATE), 'ACTIVITY_STATUS_PUBLIC': ( rights_manager.ACTIVITY_STATUS_PUBLIC), 'ACTIVITY_STATUS_PUBLICIZED': ( rights_manager.ACTIVITY_STATUS_PUBLICIZED), # The 'path' variable starts with a forward slash. 'FULL_URL': '%s://%s%s' % (scheme, netloc, path), 'INVALID_NAME_CHARS': feconf.INVALID_NAME_CHARS, 'RTE_COMPONENT_SPECS': ( rte_component_registry.Registry.get_all_specs()), 'SITE_FEEDBACK_FORM_URL': feconf.SITE_FEEDBACK_FORM_URL, 'SITE_NAME': feconf.SITE_NAME, 'SUPPORTED_SITE_LANGUAGES': feconf.SUPPORTED_SITE_LANGUAGES, 'SYSTEM_USERNAMES': feconf.SYSTEM_USERNAMES, 'TEMPLATE_DIR_PREFIX': utils.get_template_dir_prefix(), 'can_create_collections': ( self.username and self.username in config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value ), 'username': self.username, 'user_is_logged_in': user_services.has_fully_registered( self.user_id), 'preferred_site_language_code': self.preferred_site_language_code }) if feconf.ENABLE_PROMO_BAR: promo_bar_enabled = config_domain.PROMO_BAR_ENABLED.value promo_bar_message = config_domain.PROMO_BAR_MESSAGE.value else: promo_bar_enabled = False promo_bar_message = '' values.update({ 'promo_bar_enabled': promo_bar_enabled, 'promo_bar_message': promo_bar_message, }) if 'meta_name' not in values: values['meta_name'] = 'Personalized Online Learning from Oppia' if 'meta_description' not in values: values['meta_description'] = ( 'Oppia is a free, open-source learning platform. Join the ' 'community to create or try an exploration today!') # nav_mode is used as part of the GLOBALS object in the frontend, but # not every backend handler declares a nav_mode. Thus, the following # code is a failsafe to ensure that the nav_mode key is added to all # page requests. if 'nav_mode' not in values: values['nav_mode'] = '' if redirect_url_on_logout is None: redirect_url_on_logout = self.request.uri if self.user_id: values['login_url'] = None values['logout_url'] = ( current_user_services.create_logout_url( redirect_url_on_logout)) else: target_url = ( '/' if self.request.uri.endswith(feconf.SPLASH_URL) else self.request.uri) values['login_url'] = ( current_user_services.create_login_url(target_url)) values['logout_url'] = None # Create a new csrf token for inclusion in HTML responses. This assumes # that tokens generated in one handler will be sent back to a handler # with the same page name. values['csrf_token'] = '' if self.REQUIRE_PAYLOAD_CSRF_CHECK: values['csrf_token'] = CsrfTokenManager.create_csrf_token( self.user_id) self.response.cache_control.no_cache = True self.response.cache_control.must_revalidate = True self.response.headers['Strict-Transport-Security'] = ( 'max-age=31536000; includeSubDomains') self.response.headers['X-Content-Type-Options'] = 'nosniff' if iframe_restriction is not None: if iframe_restriction in ['SAMEORIGIN', 'DENY']: self.response.headers['X-Frame-Options'] = iframe_restriction else: raise Exception( 'Invalid X-Frame-Options: %s' % iframe_restriction) self.response.expires = 'Mon, 01 Jan 1990 00:00:00 GMT' self.response.pragma = 'no-cache' self.response.write( self.jinja2_env.get_template(filename).render(**values))
def render_template( self, filename, values=None, iframe_restriction='DENY', redirect_url_on_logout=None): if values is None: values = self.values scheme, netloc, path, _, _ = urlparse.urlsplit(self.request.uri) values.update({ 'ALL_CATEGORIES': feconf.ALL_CATEGORIES, 'ALL_LANGUAGE_CODES': feconf.ALL_LANGUAGE_CODES, 'ASSET_DIR_PREFIX': utils.get_asset_dir_prefix(), 'BEFORE_END_HEAD_TAG_HOOK': jinja2.utils.Markup( BEFORE_END_HEAD_TAG_HOOK.value), 'CAN_SEND_ANALYTICS_EVENTS': feconf.CAN_SEND_ANALYTICS_EVENTS, 'DEFAULT_LANGUAGE_CODE': feconf.ALL_LANGUAGE_CODES[0]['code'], 'DEV_MODE': feconf.DEV_MODE, 'MINIFICATION': feconf.IS_MINIFIED, 'DOMAIN_URL': '%s://%s' % (scheme, netloc), 'ACTIVITY_STATUS_PRIVATE': ( rights_manager.ACTIVITY_STATUS_PRIVATE), 'ACTIVITY_STATUS_PUBLIC': ( rights_manager.ACTIVITY_STATUS_PUBLIC), 'ACTIVITY_STATUS_PUBLICIZED': ( rights_manager.ACTIVITY_STATUS_PUBLICIZED), # The 'path' variable starts with a forward slash. 'FULL_URL': '%s://%s%s' % (scheme, netloc, path), 'INVALID_NAME_CHARS': feconf.INVALID_NAME_CHARS, 'RTE_COMPONENT_SPECS': ( rte_component_registry.Registry.get_all_specs()), 'SITE_FEEDBACK_FORM_URL': SITE_FEEDBACK_FORM_URL.value, 'SITE_NAME': SITE_NAME.value, 'SUPPORTED_SITE_LANGUAGES': feconf.SUPPORTED_SITE_LANGUAGES, 'SYSTEM_USERNAMES': feconf.SYSTEM_USERNAMES, 'TEMPLATE_DIR_PREFIX': utils.get_template_dir_prefix(), 'can_create_collections': ( self.username and self.username in config_domain.WHITELISTED_COLLECTION_EDITOR_USERNAMES.value ), 'user_is_logged_in': user_services.has_fully_registered( self.user_id), 'preferred_site_language_code': self.preferred_site_language_code }) if 'meta_name' not in values: values['meta_name'] = 'Personalized Online Learning from Oppia' if 'meta_description' not in values: values['meta_description'] = ( 'Oppia is a free, open-source learning platform. Join the ' 'community to create or try an exploration today!') if redirect_url_on_logout is None: redirect_url_on_logout = self.request.uri if self.user_id: values['logout_url'] = ( current_user_services.create_logout_url( redirect_url_on_logout)) else: target_url = ( '/' if self.request.uri.endswith(feconf.SPLASH_URL) else self.request.uri) values['login_url'] = ( current_user_services.create_login_url(target_url)) # Create a new csrf token for inclusion in HTML responses. This assumes # that tokens generated in one handler will be sent back to a handler # with the same page name. values['csrf_token'] = '' if self.REQUIRE_PAYLOAD_CSRF_CHECK: values['csrf_token'] = CsrfTokenManager.create_csrf_token( self.user_id) self.response.cache_control.no_cache = True self.response.cache_control.must_revalidate = True self.response.headers['Strict-Transport-Security'] = ( 'max-age=31536000; includeSubDomains') self.response.headers['X-Content-Type-Options'] = 'nosniff' if iframe_restriction is not None: if iframe_restriction in ['SAMEORIGIN', 'DENY']: self.response.headers['X-Frame-Options'] = iframe_restriction else: raise Exception( 'Invalid X-Frame-Options: %s' % iframe_restriction) self.response.expires = 'Mon, 01 Jan 1990 00:00:00 GMT' self.response.pragma = 'no-cache' self.response.write(self.jinja2_env.get_template( filename).render(**values)) # Calculate the processing time of this request. duration = datetime.datetime.utcnow() - self.start_time processing_time = duration.seconds + duration.microseconds / 1E6 counters.HTML_RESPONSE_TIME_SECS.inc(increment=processing_time) counters.HTML_RESPONSE_COUNT.inc()
def get_static_asset_url(self, asset_suffix): """Returns the relative path for the asset, appending it to the corresponding cache slug. asset_suffix should have a leading slash. """ return '/assets%s%s' % (utils.get_asset_dir_prefix(), asset_suffix)
def get_static_resource_url(resource_suffix): """Returns the relative path for the resource, appending it to the corresponding cache slug. resource_suffix should have a leading slash. """ return "%s%s" % (utils.get_asset_dir_prefix(), resource_suffix)