+ {{plugin-outlet name="admin-customize-themes-show-top" args=(hash theme=model)}}
{{#if editingName}}
{{text-field value=model.name autofocus="true"}}
@@ -191,45 +192,47 @@
{{/d-section}}
{{/if}}
-
-
{{i18n "admin.customize.theme.css_html"}}
- {{#if model.hasEditedFields}}
-
{{i18n "admin.customize.theme.custom_sections"}}
-
- {{#each editedFieldsFormatted as |field|}}
- - {{field}}
- {{/each}}
-
- {{else}}
-
- {{i18n "admin.customize.theme.edit_css_html_help"}}
-
- {{/if}}
+ {{#unless model.remote_theme}}
+
+
{{i18n "admin.customize.theme.css_html"}}
+ {{#if model.hasEditedFields}}
+
{{i18n "admin.customize.theme.custom_sections"}}
+
+ {{#each editedFieldsFormatted as |field|}}
+ - {{field}}
+ {{/each}}
+
+ {{else}}
+
+ {{i18n "admin.customize.theme.edit_css_html_help"}}
+
+ {{/if}}
- {{d-button
- class="btn-default edit"
- action=(action "editTheme")
- label="admin.customize.theme.edit_css_html"}}
-
+ {{d-button
+ class="btn-default edit"
+ action=(action "editTheme")
+ label="admin.customize.theme.edit_css_html"}}
+
-
-
{{i18n "admin.customize.theme.uploads"}}
- {{#if model.uploads}}
-
- {{#each model.uploads as |upload|}}
- -
- ${{upload.name}}: {{upload.filename}}
-
- {{d-button action=(action "removeUpload") actionParam=upload class="second btn-default btn-default cancel-edit" icon="times"}}
-
-
- {{/each}}
-
- {{else}}
-
{{i18n "admin.customize.theme.no_uploads"}}
- {{/if}}
- {{d-button action=(action "addUploadModal") class="btn-default" icon="plus" label="admin.customize.theme.add"}}
-
+
+
{{i18n "admin.customize.theme.uploads"}}
+ {{#if model.uploads}}
+
+ {{#each model.uploads as |upload|}}
+ -
+ ${{upload.name}}: {{upload.filename}}
+
+ {{d-button action=(action "removeUpload") actionParam=upload class="second btn-default btn-default cancel-edit" icon="times"}}
+
+
+ {{/each}}
+
+ {{else}}
+
{{i18n "admin.customize.theme.no_uploads"}}
+ {{/if}}
+ {{d-button action=(action "addUploadModal") class="btn-default" icon="plus" label="admin.customize.theme.add"}}
+
+ {{/unless}}
{{#if extraFiles.length}}
diff --git a/app/controllers/admin/themes_controller.rb b/app/controllers/admin/themes_controller.rb
index b4c222dd0f0..7ddb3e49a0a 100644
--- a/app/controllers/admin/themes_controller.rb
+++ b/app/controllers/admin/themes_controller.rb
@@ -299,6 +299,10 @@ class Admin::ThemesController < Admin::AdminController
raise Discourse::InvalidAccess if !GlobalSetting.allowed_theme_ids.nil?
end
+ def ban_for_remote_theme!
+ raise Discourse::InvalidAccess if @theme.remote_theme
+ end
+
def add_relative_themes!(kind, ids)
expected = ids.map(&:to_i)
@@ -357,6 +361,7 @@ class Admin::ThemesController < Admin::AdminController
return unless fields = theme_params[:theme_fields]
ban_in_allowlist_mode!
+ ban_for_remote_theme!
fields.each do |field|
@theme.set_field(
diff --git a/spec/requests/admin/themes_controller_spec.rb b/spec/requests/admin/themes_controller_spec.rb
index f75c1c7ae20..43b5c9b12b6 100644
--- a/spec/requests/admin/themes_controller_spec.rb
+++ b/spec/requests/admin/themes_controller_spec.rb
@@ -370,6 +370,22 @@ describe Admin::ThemesController do
expect(UserHistory.where(action: UserHistory.actions[:change_theme]).count).to eq(1)
end
+ it 'blocks remote theme fields from being locally edited' do
+ r = RemoteTheme.create!(remote_url: "https://magic.com/repo.git")
+ theme.update!(remote_theme_id: r.id)
+
+ put "/admin/themes/#{theme.id}.json", params: {
+ theme: {
+ theme_fields: [
+ { name: 'scss', target: 'common', value: '' },
+ { name: 'test', target: 'common', value: 'filename.jpg', upload_id: 4 }
+ ]
+ }
+ }
+
+ expect(response.status).to eq(403)
+ end
+
it 'updates a child theme' do
child_theme = Fabricate(:theme, component: true)
put "/admin/themes/#{child_theme.id}.json", params: {