FEATURE: improve handling of site setting secrets

This commit is contained in:
Arpit Jalan 2018-06-02 19:27:52 +05:30
parent 685083491e
commit 46fc57222f
7 changed files with 61 additions and 10 deletions

View File

@ -16,6 +16,7 @@ export default Ember.Mixin.create({
classNameBindings: [':row', ':setting', 'setting.overridden', 'typeClass'],
content: Ember.computed.alias('setting'),
validationMessage: null,
isSecret: Ember.computed.oneWay('setting.secret'),
@computed("buffered.value", "setting.value")
dirty(bufferVal, settingVal) {
@ -95,13 +96,17 @@ export default Ember.Mixin.create({
});
},
cancel() {
this.rollbackBuffer();
},
resetDefault() {
this.set('buffered.value', this.get('setting.default'));
this._save();
},
cancel() {
this.rollbackBuffer();
toggleSecret() {
this.toggleProperty('isSecret');
}
}
});

View File

@ -2,7 +2,7 @@
<h3>{{unbound settingName}}</h3>
</div>
<div class="setting-value">
{{component componentName setting=setting value=buffered.value validationMessage=validationMessage preview=preview}}
{{component componentName setting=setting value=buffered.value validationMessage=validationMessage preview=preview isSecret=isSecret}}
</div>
{{#if dirty}}
<div class='setting-controls'>
@ -10,5 +10,8 @@
{{d-button class="cancel" action="cancel" icon="times"}}
</div>
{{else if setting.overridden}}
{{#if setting.secret}}
{{d-button action="toggleSecret" icon="eye-slash"}}
{{/if}}
{{d-button action="resetDefault" icon="undo" label="admin.settings.reset"}}
{{/if}}

View File

@ -1,5 +1,7 @@
{{#if setting.textarea}}
{{textarea value=value classNames="input-setting-textarea"}}
{{else if isSecret}}
{{input type="password" value=value classNames="input-setting-string"}}
{{else}}
{{text-field value=value classNames="input-setting-string"}}
{{/if}}

View File

@ -575,7 +575,7 @@ $mobile-breakpoint: 700px;
}
.setting.overridden.string {
input[type=text], textarea {
input[type=text], input[type=password], textarea {
background-color: $highlight-medium;
}
}

View File

@ -8,6 +8,7 @@
# regex - A regex that the value must match.
# validator - The name of the class that will be use to validate the value of the setting.
# allow_any - For choice settings allow items not specified in the choice list (default true)
# secret - Set to true if input type should be password and value needs to be scrubbed from logs (default false).
# enum - The setting has a fixed set of allowed values, and only one can be chosen.
# Set to the class name that defines the set.
# shadowed_by_global - "Shadow" a site setting with a GlobalSetting. If the GlobalSetting
@ -274,7 +275,9 @@ login:
client: true
default: false
google_oauth2_client_id: ''
google_oauth2_client_secret: ''
google_oauth2_client_secret:
default: ''
secret: true
google_oauth2_prompt:
default: ''
type: list
@ -297,6 +300,7 @@ login:
twitter_consumer_secret:
default: ''
regex: "^[\\w+-]+$"
secret: true
enable_instagram_logins:
client: true
default: false
@ -306,6 +310,7 @@ login:
instagram_consumer_secret:
default: ''
regex: "^[a-z0-9]+$"
secret: true
enable_facebook_logins:
client: true
default: false
@ -315,6 +320,7 @@ login:
facebook_app_secret:
default: ''
regex: "^[a-f0-9]+$"
secret: true
enable_github_logins:
client: true
default: false
@ -324,6 +330,7 @@ login:
github_client_secret:
default: ''
regex: "^[a-f0-9]+$"
secret: true
enable_sso:
client: true
default: false
@ -337,7 +344,9 @@ login:
sso_url:
default: ''
regex: '^https?:\/\/.+[^\/]$'
sso_secret: ''
sso_secret:
default: ''
secret: true
sso_overrides_groups: false
sso_overrides_bio: false
sso_overrides_email:
@ -884,7 +893,9 @@ files:
client: true
s3_use_iam_profile: false
s3_access_key_id: ''
s3_secret_access_key: ''
s3_secret_access_key:
default: ''
secret: true
s3_region:
default: 'us-east-1'
enum: 'S3RegionSiteSetting'

View File

@ -66,6 +66,10 @@ module SiteSettingExtension
@previews ||= {}
end
def secret_settings
@secret_settings ||= []
end
def setting(name_arg, default = nil, opts = {})
name = name_arg.to_sym
@ -106,6 +110,10 @@ module SiteSettingExtension
previews[name] = opts[:preview]
end
if opts[:secret]
secret_settings << name
end
type_supervisor.load_setting(
name,
opts.extract!(*SiteSettings::TypeSupervisor::CONSUMED_OPTS)
@ -149,7 +157,8 @@ module SiteSettingExtension
default: defaults[s].to_s,
value: value.to_s,
category: categories[s],
preview: previews[s]
preview: previews[s],
secret: secret_settings.include?(s)
}.merge(type_supervisor.type_hash(s))
opts
@ -284,7 +293,7 @@ module SiteSettingExtension
prev_value = send(name)
set(name, value)
if has_setting?(name)
value = prev_value = "[FILTERED]" if name.to_s =~ /_secret/
value = prev_value = "[FILTERED]" if secret_settings.include?(name.to_sym)
StaffActionLogger.new(user).log_site_setting_change(name, prev_value, value)
end
end

View File

@ -439,7 +439,7 @@ describe SiteSettingExtension do
describe ".set_and_log" do
before do
settings.setting(:s3_secret_access_key, "old_secret_key")
settings.setting(:s3_secret_access_key, "old_secret_key", secret: true)
settings.setting(:title, "Discourse v1")
settings.refresh!
end
@ -592,6 +592,27 @@ describe SiteSettingExtension do
end
end
describe "secret" do
before do
settings.setting(:superman_identity, 'Clark Kent', secret: true)
settings.refresh!
end
it "is in the `secret_settings` collection" do
expect(settings.secret_settings.include?(:superman_identity)).to eq(true)
end
it "can be retrieved" do
expect(settings.superman_identity).to eq("Clark Kent")
end
it "is present in all_settings by default" do
secret_setting = settings.all_settings.find { |s| s[:setting] == :superman_identity }
expect(secret_setting).to be_present
expect(secret_setting[:secret]).to eq(true)
end
end
describe 'locale default overrides are respected' do
before do
settings.setting(:test_override, 'default', locale_default: { zh_CN: 'cn' })