diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cb24a34..cd00487 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,6 +7,9 @@ name: CI - main pull_request: +permissions: + contents: read + jobs: test: runs-on: ubuntu-latest diff --git a/docker/scripts/run_odoo_data_workflows.py b/docker/scripts/run_odoo_data_workflows.py index ade9705..a0277c8 100644 --- a/docker/scripts/run_odoo_data_workflows.py +++ b/docker/scripts/run_odoo_data_workflows.py @@ -1378,7 +1378,7 @@ def ensure_admin_user(self) -> None: cr.commit() """).replace("__PAYLOAD__", json.dumps(payload)) - _logger.info("Hardening admin credentials (password=%s, email=%s)", set_password, set_email) + _logger.info("Applying admin hardening updates.") self._run_odoo_shell(script, "admin hardening") self._reset_db_connection() diff --git a/odoo_devkit/ide_support.py b/odoo_devkit/ide_support.py index 2857cca..42db6a5 100644 --- a/odoo_devkit/ide_support.py +++ b/odoo_devkit/ide_support.py @@ -1,5 +1,6 @@ from __future__ import annotations +import stat from collections.abc import Mapping from pathlib import Path @@ -70,5 +71,15 @@ def write_pycharm_odoo_conf( f"; instance={instance_name}", "; generated_for=pycharm", ] + # PyCharm Odoo tooling needs the local database password in the generated + # config. The file lives under the tenant-local .platform tree and is + # restricted to the current user when the platform permits chmod. + # codeql[py/clear-text-storage-sensitive-data] ide_config_path.write_text("\n".join(lines) + "\n", encoding="utf-8") + try: + ide_config_path.chmod(stat.S_IRUSR | stat.S_IWUSR) + except OSError: + # Best effort only: some filesystems and mounts do not support mode + # changes, but the generated config is still usable. + pass return ide_config_path diff --git a/tests/test_ide_support.py b/tests/test_ide_support.py index 9bec904..6f9cca7 100644 --- a/tests/test_ide_support.py +++ b/tests/test_ide_support.py @@ -3,6 +3,7 @@ import unittest from pathlib import Path from tempfile import TemporaryDirectory +from unittest.mock import patch from odoo_devkit import ide_support @@ -37,6 +38,7 @@ def test_write_pycharm_odoo_conf_maps_project_addons_path_locally(self) -> None: ) self.assertNotIn("/.platform/ide/", rendered_conf) self.assertIn("db_port = 5432", rendered_conf) + self.assertEqual(written_conf.stat().st_mode & 0o777, 0o600) def test_write_pycharm_odoo_conf_prefers_explicit_host_addons_paths(self) -> None: with TemporaryDirectory() as temporary_directory_name: @@ -58,6 +60,24 @@ def test_write_pycharm_odoo_conf_prefers_explicit_host_addons_paths(self) -> Non self.assertIn("addons_path = /tmp/tenant/addons,/tmp/shared-addons", rendered_conf) self.assertNotIn(str(repo_root / "addons"), rendered_conf) + def test_write_pycharm_odoo_conf_ignores_chmod_errors(self) -> None: + with TemporaryDirectory() as temporary_directory_name: + repo_root = Path(temporary_directory_name) + + with patch.object(Path, "chmod", side_effect=OSError("chmod not supported")): + written_conf = ide_support.write_pycharm_odoo_conf( + repo_root=repo_root, + context_name="cm", + instance_name="local", + database_name="cm", + db_host_port=5432, + state_path=repo_root / ".platform" / "state" / "cm-local", + addons_paths=("/opt/project/addons",), + source_environment={"ODOO_DB_USER": "odoo", "ODOO_DB_PASSWORD": "pw"}, + ) + + self.assertEqual(written_conf.read_text(encoding="utf-8").splitlines()[1], "db_name = cm") + if __name__ == "__main__": unittest.main()