|
| 1 | +# Part of OpenSPP. See LICENSE file for full copyright and licensing details. |
| 2 | + |
| 3 | +from odoo import api, fields, models |
| 4 | + |
| 5 | + |
| 6 | +class ResConfigSettings(models.TransientModel): |
| 7 | + _inherit = "res.config.settings" |
| 8 | + |
| 9 | + # The DCI auth middleware stores every boolean flag as the literal string |
| 10 | + # "true"/"false" (see middleware/signature.py:_read_security_flag) and falls |
| 11 | + # back to an in-code default when the parameter is missing. Odoo's |
| 12 | + # ``config_parameter`` boolean machinery is incompatible with that: it |
| 13 | + # *deletes* the parameter when the field is False (so a default-true flag can |
| 14 | + # never be turned off) and reads back ``bool("false")`` as True. We therefore |
| 15 | + # manage these flags explicitly in get_values/set_values instead. |
| 16 | + _DCI_FLAG_PARAMS = { |
| 17 | + "dci_api_tokens_required": ("dci.api_tokens_required", True), |
| 18 | + "dci_allow_unsigned_requests": ("dci.allow_unsigned_requests", False), |
| 19 | + "dci_bypass_bearer_auth": ("dci.bypass_bearer_auth", False), |
| 20 | + "dci_allow_http_callbacks": ("dci.allow_http_callbacks", False), |
| 21 | + "dci_allow_internal_callback_ips": ("dci.allow_internal_callback_ips", False), |
| 22 | + } |
| 23 | + |
| 24 | + # --- API authentication --- |
| 25 | + dci_api_tokens = fields.Char( |
| 26 | + string="DCI API Bearer Tokens", |
| 27 | + config_parameter="dci.api_tokens", |
| 28 | + help="Accepted bearer tokens for incoming DCI requests. " |
| 29 | + "Comma-separated for multiple clients. Each token must match the " |
| 30 | + "Bearer Token configured on the calling client's data source.", |
| 31 | + ) |
| 32 | + dci_sender_id = fields.Char( |
| 33 | + string="DCI Server Sender ID", |
| 34 | + config_parameter="dci.sender_id", |
| 35 | + default="openspp", |
| 36 | + help="This server's own DCI sender id, stamped on outgoing envelopes.", |
| 37 | + ) |
| 38 | + dci_api_tokens_required = fields.Boolean( |
| 39 | + string="Require DCI API Tokens", |
| 40 | + default=True, |
| 41 | + help="When enabled and no tokens are configured, every request is " |
| 42 | + "rejected (fail-closed). Disable only for development.", |
| 43 | + ) |
| 44 | + |
| 45 | + # --- Development / insecure options (never enable in production) --- |
| 46 | + dci_allow_unsigned_requests = fields.Boolean( |
| 47 | + string="Allow Unsigned Requests", |
| 48 | + default=False, |
| 49 | + help="Development only. Accept DCI envelopes that carry no signature, " |
| 50 | + "skipping signature verification. Never enable in production.", |
| 51 | + ) |
| 52 | + dci_bypass_bearer_auth = fields.Boolean( |
| 53 | + string="Bypass Bearer Authentication", |
| 54 | + default=False, |
| 55 | + help="Development only. Skip the bearer-token check entirely. Never enable in production.", |
| 56 | + ) |
| 57 | + dci_allow_http_callbacks = fields.Boolean( |
| 58 | + string="Allow HTTP Callbacks", |
| 59 | + default=False, |
| 60 | + help="Development only. Permit plain-http (non-TLS) callback URLs. Never enable in production.", |
| 61 | + ) |
| 62 | + dci_allow_internal_callback_ips = fields.Boolean( |
| 63 | + string="Allow Internal Callback IPs", |
| 64 | + default=False, |
| 65 | + help="Development only. Permit callbacks to internal/private IP addresses. Never enable in production.", |
| 66 | + ) |
| 67 | + |
| 68 | + @api.model |
| 69 | + def get_values(self): |
| 70 | + res = super().get_values() |
| 71 | + # System parameters require sudo; this view is gated to base.group_system. |
| 72 | + # nosemgrep: odoo-sudo-without-context |
| 73 | + icp = self.env["ir.config_parameter"].sudo() |
| 74 | + for field_name, (param, default) in self._DCI_FLAG_PARAMS.items(): |
| 75 | + default_str = "true" if default else "false" |
| 76 | + res[field_name] = icp.get_param(param, default_str).lower() == "true" |
| 77 | + return res |
| 78 | + |
| 79 | + def set_values(self): |
| 80 | + super().set_values() |
| 81 | + # System parameters require sudo; this view is gated to base.group_system. |
| 82 | + # nosemgrep: odoo-sudo-without-context |
| 83 | + icp = self.env["ir.config_parameter"].sudo() |
| 84 | + for field_name, (param, _default) in self._DCI_FLAG_PARAMS.items(): |
| 85 | + icp.set_param(param, "true" if self[field_name] else "false") |
0 commit comments