sadpandajoe commented on code in PR #44992:
URL: https://github.com/apache/superset/pull/44992#discussion_r4214194303


##########
superset-frontend/src/features/alerts/AlertReportModal.tsx:
##########
@@ -985,10 +1072,64 @@ const AlertReportModal: 
FunctionComponent<AlertReportModalProps> = ({
       extra: contentType === ContentType.Dashboard ? currentAlert?.extra : {},
     };
 
+    if (!isReport && !attachmentControlsVisible && !isEditMode) {
+      data.report_format = 'NONE';
+    }
+    if (!attachmentControlsVisible && isEditMode) {
+      // Hidden settings stay stored; only the format controls attachment 
delivery.
+      delete data.chart;
+      delete data.dashboard;
+      delete data.extra;
+      delete data.custom_width;
+      delete data.force_screenshot;
+      delete data.include_cta;

Review Comment:
   The "Include a link back to Superset" checkbox lives inside the 
attachment-controls block, and saving without those controls deletes 
`include_cta` from the payload. So if an editor unchecks the link and then 
turns the attachment off (or attachments are globally off for alerts), the 
unchecked choice is silently dropped and the notifications keep the chart link. 
`include_cta` is stored independently of the format and is read in the executor 
regardless of attachments, so should this be left in the payload and the 
checkbox kept outside the attachment-only block?



##########
superset/commands/report/update.py:
##########
@@ -193,6 +489,18 @@ def validate(self) -> None:  # noqa: C901
             include_viewers=False,
         )
 
+        self.validate_report_format(
+            report_type,
+            self._properties.get("report_format", self._model.report_format),
+            exceptions,
+        )
+        if "recipients" in self._properties:
+            self.validate_recipients_policy(exceptions)

Review Comment:
   The PUT path's recipient-policy check has no test that would fail if this 
call were removed. `run_as_test.py` stubs `validate_recipients_policy` on 
`UpdateReportScheduleCommand`, and the API recipient-update tests run with no 
allowlist, while the only unstubbed policy test 
(`test_create_enforces_recipient_policy`) covers create. Could you add an 
update-command test with a stored allowlist and a recipient outside it, 
asserting the invalid-error contains `ReportScheduleRecipientNotAllowedError` 
and the stored recipients are unchanged?



##########
superset/reports/schemas.py:
##########
@@ -628,6 +743,106 @@ def validate_custom_width(
             )
 
 
+def validate_email_domain(value: str) -> None:
+    if not EMAIL_DOMAIN_REGEX.match(value.strip()):
+        raise ValidationError(_("Invalid e-mail domain: %(domain)s", 
domain=value))
+
+
+class ReportConfigurationSchema(Schema):
+    """
+    Global Alerts & Reports configuration (SIP-209).
+
+    Every field is optional on update: absent fields keep their stored value 
and
+    ``null`` clears a setting without restoring its legacy fallback.
+    """
+
+    alerts_attach_reports = fields.Boolean(
+        metadata={
+            "description": "Whether alerts deliver their attachment 
(screenshot, "
+            "PDF, CSV or XLSX). When disabled, alerts only send the message 
and "
+            "link. Falls back to the FF until a row has first been saved."
+        },
+        required=False,
+        allow_none=True,
+    )
+    date_format_in_email_subject = fields.Boolean(
+        metadata={
+            "description": "Render strftime date placeholders in email 
subjects. "
+            "Falls back to the DATE_FORMAT_IN_EMAIL_SUBJECT FF until first 
saved."
+        },
+        required=False,
+        allow_none=True,
+    )
+    alert_minimum_interval = fields.Integer(
+        metadata={
+            "description": "Minimum interval between alert executions, in 
seconds. "
+            "Values below 120 do not restrict schedules. Falls back to "
+            "ALERT_MINIMUM_INTERVAL only before this setting has been saved.",
+            "example": 3600,
+        },
+        required=False,
+        allow_none=True,
+        validate=[Range(min=0, error=lazy_gettext("Value must be 0 or 
greater"))],
+    )
+    report_minimum_interval = fields.Integer(
+        metadata={
+            "description": "Minimum interval between report executions, in 
seconds. "
+            "Values below 120 do not restrict schedules. Falls back to "
+            "REPORT_MINIMUM_INTERVAL only before this setting has been saved.",
+            "example": 3600,
+        },
+        required=False,
+        allow_none=True,
+        validate=[Range(min=0, error=lazy_gettext("Value must be 0 or 
greater"))],
+    )
+    limit_recipients_to_users = fields.Boolean(
+        metadata={
+            "description": "When enabled, only e-mail addresses of existing 
active "
+            "users are accepted as recipients."
+        },
+        required=False,
+        allow_none=True,
+    )
+    allowed_email_domains = fields.List(
+        fields.String(validate=validate_email_domain),
+        metadata={
+            "description": "E-mail domains accepted as recipients. An empty 
list "
+            "allows any domain.",
+            "example": ["example.com", "superset.com"],
+        },
+        required=False,
+        allow_none=True,
+    )
+
+    @pre_load
+    def normalize_domains(self, data: dict[str, Any], **kwargs: Any) -> 
dict[str, Any]:
+        domains = data.get("allowed_email_domains")

Review Comment:
   `normalize_domains` calls `data.get(...)` before Marshmallow checks that the 
body is an object, so an admin `PUT /configuration/` with a JSON body of `[]` 
or `null` raises `AttributeError`. The endpoint only catches `ValidationError`, 
so that surfaces as a 500 instead of the documented 400. Would a guard like `if 
not isinstance(data, dict): return data` here let the normal type validation 
produce the 400?



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to