From a928b9ee3ff62a8eb1b5be7f380b6941ca7d7358 Mon Sep 17 00:00:00 2001 From: Peter Marheine Date: Tue, 7 Aug 2018 13:52:48 +1000 Subject: [PATCH] Add settings for CAPTCHA in account recovery. Allowing users to enable it and specify the site and secret key to use with reCAPTCHA. The old hard-coded keys were insecure; the secret key must not be distributed publicly. The current defaults are the test keys provided at https://developers.google.com/recaptcha/docs/faq#id-like-to-run-automated-tests-with-recaptcha-v2-what-should-i-do Signed-off-by: Peter Marheine --- .../command/AdvancedSettingsCommand.java | 28 ++++++++++++++++ .../AdvancedSettingsController.java | 9 ++++++ .../player/service/SettingsService.java | 32 +++++++++++++++++++ .../player/i18n/ResourceBundle_en.properties | 9 ++++++ .../webapp/WEB-INF/jsp/advancedSettings.jsp | 29 ++++++++++++++++- 5 files changed, 106 insertions(+), 1 deletion(-) diff --git a/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java b/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java index 71e44cc4..ab11386e 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java +++ b/airsonic-main/src/main/java/org/airsonic/player/command/AdvancedSettingsCommand.java @@ -45,6 +45,10 @@ public class AdvancedSettingsCommand { private String smtpPassword; private String smtpFrom; + private boolean captchaEnabled; + private String recaptchaSiteKey; + private String recaptchaSecretKey; + public String getDownloadLimit() { return downloadLimit; } @@ -167,4 +171,28 @@ public class AdvancedSettingsCommand { public void setSmtpFrom(String smtpFrom) { this.smtpFrom = smtpFrom; } + + public boolean isCaptchaEnabled() { + return captchaEnabled; + } + + public void setCaptchaEnabled(boolean captchaEnabled) { + this.captchaEnabled = captchaEnabled; + } + + public String getRecaptchaSiteKey() { + return recaptchaSiteKey; + } + + public void setRecaptchaSiteKey(String recaptchaSiteKey) { + this.recaptchaSiteKey = recaptchaSiteKey; + } + + public String getRecaptchaSecretKey() { + return recaptchaSecretKey; + } + + public void setRecaptchaSecretKey(String recaptchaSecretKey) { + this.recaptchaSecretKey = recaptchaSecretKey; + } } diff --git a/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java b/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java index a682bedd..96f9864f 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java +++ b/airsonic-main/src/main/java/org/airsonic/player/controller/AdvancedSettingsController.java @@ -61,6 +61,9 @@ public class AdvancedSettingsController { command.setSmtpUser(settingsService.getSmtpUser()); command.setSmtpFrom(settingsService.getSmtpFrom()); + command.setCaptchaEnabled(settingsService.isCaptchaEnabled()); + command.setRecaptchaSiteKey(settingsService.getRecaptchaSiteKey()); + model.addAttribute("command", command); return "advancedSettings"; } @@ -98,6 +101,12 @@ public class AdvancedSettingsController { settingsService.setSmtpPassword(command.getSmtpPassword()); } + settingsService.setCaptchaEnabled(command.isCaptchaEnabled()); + settingsService.setRecaptchaSiteKey(command.getRecaptchaSiteKey()); + if (StringUtils.isNotEmpty(command.getRecaptchaSecretKey())) { + settingsService.setRecaptchaSecretKey(command.getRecaptchaSecretKey()); + } + settingsService.save(); return "redirect:advancedSettings.view"; diff --git a/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java b/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java index c9463280..1ba3702f 100644 --- a/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java +++ b/airsonic-main/src/main/java/org/airsonic/player/service/SettingsService.java @@ -117,6 +117,10 @@ public class SettingsService { private static final String KEY_IGNORE_SYMLINKS = "IgnoreSymLinks"; private static final String KEY_EXCLUDE_PATTERN_STRING = "ExcludePattern"; + private static final String KEY_CAPTCHA_ENABLED = "CaptchaEnabled"; + private static final String KEY_RECAPTCHA_SITE_KEY = "ReCaptchaSiteKey"; + private static final String KEY_RECAPTCHA_SECRET_KEY = "ReCaptchaSecretKey"; + // Database Settings private static final String KEY_DATABASE_CONFIG_TYPE = "DatabaseConfigType"; private static final String KEY_DATABASE_CONFIG_EMBED_DRIVER = "DatabaseConfigEmbedDriver"; @@ -193,6 +197,10 @@ public class SettingsService { private static final String DEFAULT_SMTP_PASSWORD = null; private static final String DEFAULT_SMTP_FROM = "airsonic@airsonic.org"; + private static final boolean DEFAULT_CAPTCHA_ENABLED = false; + private static final String DEFAULT_RECAPTCHA_SITE_KEY = "6LeIxAcTAAAAAJcZVRqyHh71UMIEGNQ_MXjiZKhI"; + private static final String DEFAULT_RECAPTCHA_SECRET_KEY = "6LeIxAcTAAAAAGG-vFI1TnRWxMZNFuojJ4WifJWe"; + private static final DataSourceConfigType DEFAULT_DATABASE_CONFIG_TYPE = DataSourceConfigType.LEGACY; private static final String DEFAULT_DATABASE_CONFIG_EMBED_DRIVER = null; private static final String DEFAULT_DATABASE_CONFIG_EMBED_URL = null; @@ -1311,6 +1319,30 @@ public class SettingsService { setString(KEY_SMTP_FROM, smtpFrom); } + public boolean isCaptchaEnabled() { + return getBoolean(KEY_CAPTCHA_ENABLED, DEFAULT_CAPTCHA_ENABLED); + } + + public void setCaptchaEnabled(boolean captchaEnabled) { + setBoolean(KEY_CAPTCHA_ENABLED, captchaEnabled); + } + + public String getRecaptchaSiteKey() { + return getProperty(KEY_RECAPTCHA_SITE_KEY, DEFAULT_RECAPTCHA_SITE_KEY); + } + + public void setRecaptchaSiteKey(String recaptchaSiteKey) { + setString(KEY_RECAPTCHA_SITE_KEY, recaptchaSiteKey); + } + + public String getRecaptchaSecretKey() { + return getProperty(KEY_RECAPTCHA_SECRET_KEY, DEFAULT_RECAPTCHA_SECRET_KEY); + } + + public void setRecaptchaSecretKey(String recaptchaSecretKey) { + setString(KEY_RECAPTCHA_SECRET_KEY, recaptchaSecretKey); + } + public DataSourceConfigType getDatabaseConfigType() { String raw = getString(KEY_DATABASE_CONFIG_TYPE, DEFAULT_DATABASE_CONFIG_TYPE.name()); return DataSourceConfigType.valueOf(StringUtils.upperCase(raw)); diff --git a/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties b/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties index b14e9356..09831897 100644 --- a/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties +++ b/airsonic-main/src/main/resources/org/airsonic/player/i18n/ResourceBundle_en.properties @@ -338,6 +338,9 @@ advancedsettings.smtpEncryption.none=None advancedsettings.smtpEncryption.starttls=STARTTLS advancedsettings.smtpEncryption.ssl=SSL/TLS advancedsettings.smtpFrom=E-mail sender +advancedsettings.enableCaptcha=Require CAPTCHA for account recovery +advancedsettings.recaptchaSiteKey=reCAPTCHA site key +advancedsettings.recaptchaSecretKey=reCAPTCHA secret key # personalSettings.jsp personalsettings.title=Personal settings for {0} personalsettings.language=Language @@ -730,6 +733,12 @@ helppopup.smtpEncryption.title=SMTP Encryption helppopup.smtpEncryption.text=

Encryption method used for connections to the SMTP server. Choose "None" for no encryption.

helppopup.smtpFrom.title=From address helppopup.smtpFrom.text=

The sender address for e-mails originating from the Airsonic server. Must be a valid e-mail address.

+helppopup.captcha.title=CAPTCHA +helppopup.captcha.text=

When enabled, users must solve a CAPTCHA to prove they are human when requesting a password reset.

Requires registration with an external service; see the documentation.

+helppopup.recaptchaSiteKey.title=reCAPTCHA site key +helppopup.recaptchaSiteKey.text=

A site key obtained from the reCAPTCHA admin console.

+helppopup.recaptchaSecretKey.title=reCAPTCHA secret key +helppopup.recaptchaSecretKey.text=

A secret key obtained from the reCAPTCHA admin console. Left unchanged if blank.

helppopup.scanMediaFolders.title=Media folders scanning rules helppopup.scanMediaFolders.text=

Note that subfolder names starting with a dot (.) or @eaDir, as well as Thumbs.db files, are ignored.

# wap/index.jsp diff --git a/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp b/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp index 66937f7a..42fb932e 100644 --- a/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp +++ b/airsonic-main/src/main/webapp/WEB-INF/jsp/advancedSettings.jsp @@ -91,7 +91,34 @@ + + + + + + + + + + + + + + +
+ + + +
+ + +
+ + +
@@ -152,4 +179,4 @@ - \ No newline at end of file +