rusackas commented on code in PR #44362:
URL: https://github.com/apache/superset/pull/44362#discussion_r4086793981


##########
superset/commands/theme/import_themes.py:
##########
@@ -46,6 +46,52 @@ def _set_importer_as_theme_editor(theme: "Theme", user: Any 
| None) -> None:
         theme.editors.append(subject)
 
 
+def _authorize_theme_overwrite(existing: "Theme", user: Any | None) -> None:
+    """Raise unless the current user may overwrite an existing theme."""
+    from superset import security_manager
+
+    if existing.is_system:
+        raise ThemeImportError("Cannot overwrite a system theme via import")
+    # The active system-default/dark theme slot may be overwritten by
+    # admins only; a non-admin overwriting it would change the theme
+    # rendered for every user, including the login page and other admins.
+    if (
+        existing.is_system_default or existing.is_system_dark
+    ) and not security_manager.is_admin():
+        raise ThemeImportError(
+            "Cannot overwrite the active system-default/dark theme via import"
+        )
+    # Overwriting an existing theme requires editorship (admins bypass).
+    # The one-time migration that introduced per-theme editors backfilled
+    # `editors` from each theme's creator, but any theme created by a path
+    # that bypasses `CreateThemeCommand` (or predates that backfill running)
+    # can still have a creator who isn't in `editors`. Fall back to
+    # `created_by_fk` so that creator isn't locked out of their own theme --
+    # but only when `editors` is still empty. Once it's populated (whether
+    # by the backfill or an admin's own edit), an empty result from
+    # `is_editor()` is a deliberate revocation, not an unbackfilled gap, and
+    # this fallback must not un-revoke it.
+    is_original_creator = (
+        user is not None and existing.created_by_fk == user.id and not 
existing.editors

Review Comment:
   Good catch, @sadpandajoe. Can't tell those apart from the row itself, but I 
don't think there's an unbackfilled case left to protect: the subjects 
migration seeded a Subject for every user before the editors backfill ran, and 
every theme-creating path since seeds its creator. So an empty `editors` list 
can only mean an explicit revocation. Dropped the fallback and added a test 
that a creator with empty `editors` is denied.



##########
superset/commands/theme/import_themes.py:
##########
@@ -46,6 +46,52 @@ def _set_importer_as_theme_editor(theme: "Theme", user: Any 
| None) -> None:
         theme.editors.append(subject)
 
 
+def _authorize_theme_overwrite(existing: "Theme", user: Any | None) -> None:
+    """Raise unless the current user may overwrite an existing theme."""
+    from superset import security_manager
+
+    if existing.is_system:
+        raise ThemeImportError("Cannot overwrite a system theme via import")
+    # The active system-default/dark theme slot may be overwritten by
+    # admins only; a non-admin overwriting it would change the theme
+    # rendered for every user, including the login page and other admins.
+    if (
+        existing.is_system_default or existing.is_system_dark
+    ) and not security_manager.is_admin():
+        raise ThemeImportError(
+            "Cannot overwrite the active system-default/dark theme via import"
+        )
+    # Overwriting an existing theme requires editorship (admins bypass).
+    # The one-time migration that introduced per-theme editors backfilled
+    # `editors` from each theme's creator, but any theme created by a path
+    # that bypasses `CreateThemeCommand` (or predates that backfill running)
+    # can still have a creator who isn't in `editors`. Fall back to
+    # `created_by_fk` so that creator isn't locked out of their own theme --
+    # but only when `editors` is still empty. Once it's populated (whether
+    # by the backfill or an admin's own edit), an empty result from
+    # `is_editor()` is a deliberate revocation, not an unbackfilled gap, and
+    # this fallback must not un-revoke it.
+    is_original_creator = (
+        user is not None and existing.created_by_fk == user.id and not 
existing.editors
+    )

Review Comment:
   Fixed, dropped the `created_by_fk` fallback entirely.



-- 
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