def test_list_pagination(tmpdir, setup, browser): # type: (LocalPath, SetupTest, Chrome) -> None """Test pagination. This forces the pagination to specific values, rather than using the page controls, since we don't create more than 100 permissions for testing. """ permissions = create_test_data(setup) settings = FrontendSettings() settings.update_from_config(src_path("config", "dev.yaml")) expected_permissions = [ (p.name, p.description, format_date(settings, p.created_on)) for p in permissions ] with frontend_server(tmpdir, "*****@*****.**") as frontend_url: browser.get(url(frontend_url, "/permissions?limit=1&offset=1")) page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions)[1:2] assert page.limit_label == "Limit: 1" # Retrieve the last permission but with a larger limit to test that the limit isn't capped # to the number of returned items. browser.get(url(frontend_url, "/permissions?limit=10&offset=2")) page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions)[2:] assert page.limit_label == "Limit: 10"
def test_list_pagination(tmpdir, setup, browser): # type: (LocalPath, SetupTest, Chrome) -> None """Test pagination. This forces the pagination to specific values, rather than using the page controls, since we don't create more than 100 permissions for testing. """ permissions = create_test_data(setup) settings = FrontendSettings() settings.update_from_config(src_path("config", "dev.yaml")) expected_permissions = [ (p.name, p.description, format_date(settings, p.created_on)) for p in permissions ] with frontend_server(tmpdir, "*****@*****.**") as frontend_url: browser.get(url(frontend_url, "/permissions?limit=1&offset=1")) page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions)[1:2] assert page.limit_label == "Limit: 1" # Retrieve the last permission but with a larger limit to test that the limit isn't capped # to the number of returned items. browser.get(url(frontend_url, "/permissions?limit=10&offset=2")) page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions)[2:] assert page.limit_label == "Limit: 10"
def main(sys_argv=sys.argv): # type: (List[str]) -> None setup_signal_handlers() # get arguments parser = build_arg_parser("Grouper Web Server.") args = parser.parse_args(sys_argv[1:]) try: # load settings settings = FrontendSettings.global_settings_from_config(args.config) # setup logging setup_logging(args, settings.log_format) # setup sentry sentry_client = get_sentry_client(settings.sentry_dsn) except Exception: logging.exception("uncaught exception in startup") sys.exit(1) try: start_server(args, settings, sentry_client) except Exception: sentry_client.captureException() finally: logging.info("end")
def test_template_consistency() -> None: """Check that template dataclasses define all variables needed by their templates. For each frontend template that has been wrapped in a dataclass, ask Jinja2 what variables need to be defined for that template and then check that the dataclass defines all of those variables and no others. This unfortunately can't check types, but at least it ensures that the dataclass is complete. """ static_path = os.path.join(os.path.dirname(grouper.fe.__file__), "static") engine = FrontendTemplateEngine(FrontendSettings(), "tests", static_path) for template_class in BaseTemplate.__subclasses__(): assert is_dataclass(template_class) template_fields = fields(template_class) expected: Set[str] = set() for template_field in template_fields: if template_field.name == "template": template = template_field.default else: expected.add(template_field.name) assert template wanted = (get_template_variables(engine, template) - DEFAULT_FIELDS) - MACROS assert expected == wanted, f"fields for {template}"
def main(sys_argv=sys.argv): # type: (List[str]) -> None setup_signal_handlers() # get arguments parser = build_arg_parser("Grouper Web Server.") args = parser.parse_args(sys_argv[1:]) try: # load settings settings = FrontendSettings.global_settings_from_config(args.config) # setup logging setup_logging(args, settings.log_format) # setup sentry sentry_client = get_sentry_client(settings.sentry_dsn) except Exception: logging.exception("uncaught exception in startup") sys.exit(1) try: start_server(args, settings, sentry_client) except Exception: sentry_client.captureException() finally: logging.info("end")
def main(sys_argv=sys.argv): # type: (List[str]) -> None setup_signal_handlers() # The curl HTTP client is required to support proxies. AsyncHTTPClient.configure(CurlAsyncHTTPClient) # get arguments parser = build_arg_parser("Grouper Web Server.") args = parser.parse_args(sys_argv[1:]) try: settings = FrontendSettings.global_settings_from_config(args.config) setup_logging(args, settings.log_format) plugins = PluginProxy.load_plugins(settings, "grouper-fe") set_global_plugin_proxy(plugins) except PluginsDirectoryDoesNotExist as e: logging.fatal("Plugin directory does not exist: {}".format(e)) sys.exit(1) except Exception: logging.exception("Uncaught exception in startup") sys.exit(1) try: start_server(args, settings, plugins) except Exception: plugins.log_exception(None, None, *sys.exc_info()) logging.exception("Uncaught exception") finally: logging.info("end")
def test_included_resources(): # type: () -> None settings = FrontendSettings() static_path = os.path.join(os.path.dirname(grouper.fe.__file__), "static") engine = FrontendTemplateEngine(settings, "", static_path, package="tests.fe") template = engine.get_template("base.json.tmpl") content = json.loads(template.render()) # Check that all external JavaScript and CSS have integrity attributes. for resource in itertools.chain(content["external_js"], content["external_css"]): assert resource["integrity"], "{} has integrity".format( resource["url"]) # Check that all internal JavaScript and CSS both exist and have matching hashes. for resource in itertools.chain(content["internal_js"], content["internal_css"]): resource_hash = sha256() with open(os.path.join(static_path, resource["url"]), "rb") as f: resource_hash.update(f.read()) assert resource["integrity"] == "sha256-" + b64encode( resource_hash.digest()).decode()
def test_csp(tmpdir, setup): # type: (LocalPath, SetupTest) -> None with setup.transaction(): setup.create_user("*****@*****.**") with frontend_server(tmpdir, "*****@*****.**") as frontend_url: r = urlopen(url(frontend_url, "/")) assert r.getcode() == 200 headers = r.info() # Some basic sanity checks on the Content-Security-Policy. assert "Content-Security-Policy" in headers csp_header = str(headers["Content-Security-Policy"]) csp_directive = {} for parameter in csp_header.split(";"): directive, value = parameter.strip().split(None, 1) csp_directive[directive] = value assert csp_directive["default-src"] == "'none'" assert "unsafe-inline" not in csp_directive["script-src"] assert "unsafe-inline" not in csp_directive["style-src"] assert "script" in csp_directive["require-sri-for"] assert "style" in csp_directive["require-sri-for"] # Make sure the cdnjs_prefix setting was honored. settings = FrontendSettings() assert settings.cdnjs_prefix in csp_directive["script-src"]
def fe_app(session, standard_graph, tmpdir): # type: (Session, GroupGraph, LocalPath) -> GrouperApplication settings = FrontendSettings() set_global_settings(settings) return create_fe_application(settings, "", xsrf_cookies=False, session=lambda: session)
def test_list(tmpdir, setup, browser): # type: (LocalPath, SetupTest, Chrome) -> None permissions = create_test_data(setup) settings = FrontendSettings() settings.update_from_config(src_path("config", "dev.yaml")) expected_permissions = [ (p.name, p.description, format_date(settings, p.created_on)) for p in permissions ] with frontend_server(tmpdir, "*****@*****.**") as frontend_url: browser.get(url(frontend_url, "/permissions")) # Check the basic permission list. page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions) assert page.heading == "Permissions" assert page.subheading == "{} permission(s)".format(len(expected_permissions)) assert page.limit_label == "Limit: 100" # Switch to only audited permissions. page.click_show_audited_button() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] audited = [p for p in expected_permissions if p[0] == "audited-permission"] assert seen_permissions == sorted(audited) assert page.heading == "Audited Permissions" assert page.subheading == "{} permission(s)".format(len(audited)) # Switch back to all permissions and sort by date. page.click_show_all_button() page.click_sort_by_date() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] expected_permissions_sorted_by_time = [ (p.name, p.description, format_date(settings, p.created_on)) for p in sorted(permissions, key=lambda p: p.created_on, reverse=True) ] assert seen_permissions == expected_permissions_sorted_by_time # Reverse the sort order. page.click_sort_by_date() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == list(reversed(expected_permissions_sorted_by_time))
def test_list(tmpdir, setup, browser): # type: (LocalPath, SetupTest, Chrome) -> None permissions = create_test_data(setup) settings = FrontendSettings() settings.update_from_config(src_path("config", "dev.yaml")) expected_permissions = [ (p.name, p.description, format_date(settings, p.created_on)) for p in permissions ] with frontend_server(tmpdir, "*****@*****.**") as frontend_url: browser.get(url(frontend_url, "/permissions")) # Check the basic permission list. page = PermissionsPage(browser) seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == sorted(expected_permissions) assert page.heading == "Permissions" assert page.subheading == "{} permission(s)".format(len(expected_permissions)) assert page.limit_label == "Limit: 100" # Switch to only audited permissions. page.click_show_audited_button() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] audited = [p for p in expected_permissions if p[0] == "audited-permission"] assert seen_permissions == sorted(audited) assert page.heading == "Audited Permissions" assert page.subheading == "{} permission(s)".format(len(audited)) # Switch back to all permissions and sort by date. page.click_show_all_button() page.click_sort_by_date() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] expected_permissions_sorted_by_time = [ (p.name, p.description, format_date(settings, p.created_on)) for p in sorted(permissions, key=lambda p: p.created_on, reverse=True) ] assert seen_permissions == expected_permissions_sorted_by_time # Reverse the sort order. page.click_sort_by_date() seen_permissions = [(r.name, r.description, r.created_on) for r in page.permission_rows] assert seen_permissions == list(reversed(expected_permissions_sorted_by_time))