From 46b21ea25134a1a71673969b4bd08cd75e3d64cd Mon Sep 17 00:00:00 2001 From: Paul Moeller Date: Tue, 3 Dec 2024 14:11:00 -0700 Subject: [PATCH] fix #7388 add security.txt (#7389) --- .../static/json/schema-common.json | 1 + sirepo/pkcli/static_files.py | 28 ++++-------- sirepo/server.py | 42 ++++++++++++------ .../1.out/{ => static/img}/favicon.ico | Bin .../1.out/{ => static/img}/favicon.png | Bin .../1.out/{ => static}/robots.txt | 0 6 files changed, 37 insertions(+), 34 deletions(-) rename tests/pkcli/static_files_data/1.out/{ => static/img}/favicon.ico (100%) rename tests/pkcli/static_files_data/1.out/{ => static/img}/favicon.png (100%) rename tests/pkcli/static_files_data/1.out/{ => static}/robots.txt (100%) diff --git a/sirepo/package_data/static/json/schema-common.json b/sirepo/package_data/static/json/schema-common.json index 27cec16054..2cf7362be2 100644 --- a/sirepo/package_data/static/json/schema-common.json +++ b/sirepo/package_data/static/json/schema-common.json @@ -172,6 +172,7 @@ "saveSimulationData": "/save-simulation", "sbatchLoginStatus": "/sbatch-login-status", "sbatchLogin": "/sbatch-login", + "securityTxt": "/security.txt", "serverStatus": "/server-status", "simOauthFlashAuthorized": "/sim-oauth-flash-authorized", "simulationData": "/simulation////?
", diff --git a/sirepo/pkcli/static_files.py b/sirepo/pkcli/static_files.py index 1c6eb30dd2..8559ab8b9e 100644 --- a/sirepo/pkcli/static_files.py +++ b/sirepo/pkcli/static_files.py @@ -12,8 +12,6 @@ import sirepo.resource import re -_ROOT_FILES = frozenset(("static/img/favicon.ico", "static/img/favicon.png")) - def gen(target_dir): """Generate static files into `target_dir` @@ -28,29 +26,19 @@ def gen(target_dir): class _Gen(PKDict): def __init__(self, target_dir): self.tgt = pykern.pkio.py_path(target_dir) - self.count = PKDict(root=0) for r, s in sirepo.resource.static_files(): self._copy(r, s) - self._maybe_root(r, s) - - self._verify() with sirepo.quest.start(in_pkcli=True) as qcall: - pykern.pkio.write_text( - self.tgt.join("robots.txt"), - qcall.call_api_sync("robotsTxt").content_as_str(), - ) + for k, v in PKDict( + robotsTxt="robots.txt", + securityTxt="security.txt", + ).items(): + pykern.pkio.write_text( + self.tgt.join("static").join(v), + qcall.call_api_sync(k).content_as_str(), + ) def _copy(self, rel, src): t = self.tgt.join(rel) pykern.pkio.mkdir_parent_only(t) src.copy(t, stat=True) - - def _maybe_root(self, rel, src): - if rel in _ROOT_FILES: - self._copy(src.basename, src) - self.count.root += 1 - - def _verify(self): - for k, v in self.count.items(): - if v < 2: - raise AssertionError(f"{k} file count={v} less than 2") diff --git a/sirepo/server.py b/sirepo/server.py index 411078da34..4ea4ddb975 100644 --- a/sirepo/server.py +++ b/sirepo/server.py @@ -19,6 +19,7 @@ import sirepo.sim_data import sirepo.sim_run import sirepo.srschema +import sirepo.srtime import sirepo.uri import sirepo.util import urllib @@ -32,7 +33,6 @@ ): import h5py -_ROBOTS_TXT = None #: Global app value (only here so instance not lost) _app = None @@ -393,20 +393,20 @@ async def api_pythonSource( @sirepo.quest.Spec("allow_visitor") async def api_robotsTxt(self): """Disallow the app (dev, prod) or / (alpha, beta)""" - global _ROBOTS_TXT - if not _ROBOTS_TXT: - # We include dev so we can test - if pkconfig.channel_in("prod", "dev"): - u = [ - self.uri_for_app_root(x) - for x in sorted(sirepo.feature_config.cfg().sim_types) - ] - else: - u = ["/"] - _ROBOTS_TXT = "".join( + # We include dev so we can test + if pkconfig.channel_in("prod", "dev"): + u = [ + self.uri_for_app_root(x) + for x in sorted(sirepo.feature_config.cfg().sim_types) + ] + else: + u = ["/"] + return self.reply( + content="".join( ["User-agent: *\n"] + ["Disallow: {}\n".format(x) for x in u], - ) - return self.reply(content=_ROBOTS_TXT, content_type="text/plain") + ), + content_type="text/plain", + ) @sirepo.quest.Spec("allow_visitor", path_info="PathInfo") async def api_root(self, path_info=None): @@ -432,6 +432,20 @@ async def api_saveSimulationData(self): ), ) + @sirepo.quest.Spec("allow_visitor") + async def api_securityTxt(self): + d = sirepo.srtime.utc_now() + d = d.replace(year=d.year + 1, hour=0, minute=0, second=0, microsecond=0) + return self.reply( + content="".join( + [ + "Contact: mailto:support@radiasoft.net\n", + f"Expires: {d.isoformat()}Z\n", + ] + ), + content_type="text/plain", + ) + @sirepo.quest.Spec( "require_user", simulation_id="SimId", pretty="Bool optional", section="Section" ) diff --git a/tests/pkcli/static_files_data/1.out/favicon.ico b/tests/pkcli/static_files_data/1.out/static/img/favicon.ico similarity index 100% rename from tests/pkcli/static_files_data/1.out/favicon.ico rename to tests/pkcli/static_files_data/1.out/static/img/favicon.ico diff --git a/tests/pkcli/static_files_data/1.out/favicon.png b/tests/pkcli/static_files_data/1.out/static/img/favicon.png similarity index 100% rename from tests/pkcli/static_files_data/1.out/favicon.png rename to tests/pkcli/static_files_data/1.out/static/img/favicon.png diff --git a/tests/pkcli/static_files_data/1.out/robots.txt b/tests/pkcli/static_files_data/1.out/static/robots.txt similarity index 100% rename from tests/pkcli/static_files_data/1.out/robots.txt rename to tests/pkcli/static_files_data/1.out/static/robots.txt