diff --git a/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java b/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java
new file mode 100644
index 00000000..fe9664b5
--- /dev/null
+++ b/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java
@@ -0,0 +1,67 @@
+/*
+ This file is part of Libresonic.
+
+ Libresonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Libresonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Libresonic. If not, see .
+
+ Copyright 2016 (C) Libresonic Authors
+ Based upon Subsonic, Copyright 2009 (C) Sindre Mehus
+ */
+package org.libresonic.player.command;
+
+import org.libresonic.player.controller.*;
+
+/**
+ * Command used in {@link PasswordSettingsController}.
+ *
+ * @author Sindre Mehus
+ */
+public class PasswordSettingsCommand {
+ private String username;
+ private String password;
+ private String confirmPassword;
+ private boolean ldapAuthenticated;
+
+ public String getUsername() {
+ return username;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getConfirmPassword() {
+ return confirmPassword;
+ }
+
+ public void setConfirmPassword(String confirmPassword) {
+ this.confirmPassword = confirmPassword;
+ }
+
+ public boolean isLdapAuthenticated() {
+ return ldapAuthenticated;
+ }
+
+ public void setLdapAuthenticated(boolean ldapAuthenticated) {
+ this.ldapAuthenticated = ldapAuthenticated;
+ }
+
+}
\ No newline at end of file
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/LoginController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/LoginController.java
index 4bfa6a50..3159a803 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/controller/LoginController.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/LoginController.java
@@ -35,7 +35,7 @@ public class LoginController {
@Autowired
private SettingsService settingsService;
- @RequestMapping(value = "/login", method = { RequestMethod.GET, RequestMethod.POST })
+ @RequestMapping(value = "/login", method = RequestMethod.GET)
public ModelAndView login(HttpServletRequest request, HttpServletResponse response) throws Exception {
// Auto-login if "user" and "password" parameters are given.
@@ -64,14 +64,4 @@ public class LoginController {
return new ModelAndView("login", "model", map);
}
- @RequestMapping(value="/logout", method = RequestMethod.GET)
- public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
- Authentication auth = SecurityContextHolder.getContext().getAuthentication();
- if (auth != null){
- LOG.info("User "+auth.getName()+" requested logout.");
- new SecurityContextLogoutHandler().logout(request, response, auth);
- }
- return "redirect:/login?logout";
- }
-
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java b/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java
new file mode 100644
index 00000000..4451ad98
--- /dev/null
+++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java
@@ -0,0 +1,85 @@
+/*
+ This file is part of Libresonic.
+
+ Libresonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Libresonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Libresonic. If not, see .
+
+ Copyright 2016 (C) Libresonic Authors
+ Based upon Subsonic, Copyright 2009 (C) Sindre Mehus
+ */
+package org.libresonic.player.controller;
+
+import org.libresonic.player.command.PasswordSettingsCommand;
+import org.libresonic.player.domain.User;
+import org.libresonic.player.service.SecurityService;
+import org.libresonic.player.validator.PasswordSettingsValidator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.BindingResult;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.servlet.ModelAndView;
+import org.springframework.web.servlet.mvc.support.RedirectAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * Controller for the page used to change password.
+ *
+ * @author Sindre Mehus
+ */
+@org.springframework.stereotype.Controller
+@RequestMapping("/passwordSettings")
+public class PasswordSettingsController {
+
+ @Autowired
+ private SecurityService securityService;
+ @Autowired
+ private PasswordSettingsValidator passwordSettingsValidator;
+
+ @InitBinder
+ protected void initBinder(WebDataBinder binder) {
+ binder.addValidators(passwordSettingsValidator);
+ }
+
+
+ @RequestMapping(method = RequestMethod.GET)
+ protected ModelAndView displayForm(HttpServletRequest request) throws Exception {
+ PasswordSettingsCommand command = new PasswordSettingsCommand();
+ User user = securityService.getCurrentUser(request);
+ command.setUsername(user.getUsername());
+ command.setLdapAuthenticated(user.isLdapAuthenticated());
+ return new ModelAndView("passwordSettings","command",command);
+ }
+
+ @RequestMapping(method = RequestMethod.POST)
+ protected String doSubmitAction(HttpServletRequest request,@ModelAttribute("command") @Validated PasswordSettingsCommand command,BindingResult bindingResult, RedirectAttributes redirectAttributes) throws Exception {
+ if (!bindingResult.hasErrors()) {
+ User user = securityService.getUserByName(command.getUsername());
+ user.setPassword(command.getPassword());
+ securityService.updateUser(user);
+
+ command.setPassword(null);
+ command.setConfirmPassword(null);
+ redirectAttributes.addFlashAttribute("settings_toast", true);
+
+ } else {
+ return "passwordSettings";
+ }
+ return "redirect:passwordSettings.view";
+ }
+
+}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java b/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java
index 890c527d..1e48a96f 100644
--- a/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java
+++ b/libresonic-main/src/main/java/org/libresonic/player/security/WebSecurityConfig.java
@@ -10,6 +10,7 @@ import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
@Configuration
@EnableWebSecurity
@@ -57,7 +58,7 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
"/flash/**", "/script/**", "/sonos/**", "/crossdomain.xml")
.permitAll()
.antMatchers("/personalSettings.view", "/passwordSettings.view",
- "/playerSettings.view", "/shareSettings.view")
+ "/playerSettings.view", "/shareSettings.view","/passwordSettings.view")
.hasRole("SETTINGS")
.antMatchers("/generalSettings.view","/advancedSettings.view","/userSettings.view",
"/musicFolderSettings.view","/networkSettings.view")
@@ -86,6 +87,8 @@ public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
.failureUrl("/login?error=1")
.usernameParameter("j_username")
.passwordParameter("j_password")
+ // see http://docs.spring.io/spring-security/site/docs/3.2.4.RELEASE/reference/htmlsingle/#csrf-logout
+ .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).logoutSuccessUrl("/login?logout")
.and().rememberMe().userDetailsService(securityService).key("libresonic");
}
diff --git a/libresonic-main/src/main/java/org/libresonic/player/validator/PasswordSettingsValidator.java b/libresonic-main/src/main/java/org/libresonic/player/validator/PasswordSettingsValidator.java
new file mode 100644
index 00000000..bf6ea6fa
--- /dev/null
+++ b/libresonic-main/src/main/java/org/libresonic/player/validator/PasswordSettingsValidator.java
@@ -0,0 +1,48 @@
+/*
+ This file is part of Libresonic.
+
+ Libresonic is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Libresonic is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Libresonic. If not, see .
+
+ Copyright 2016 (C) Libresonic Authors
+ Based upon Subsonic, Copyright 2009 (C) Sindre Mehus
+ */
+package org.libresonic.player.validator;
+
+import org.springframework.stereotype.Component;
+import org.springframework.validation.*;
+import org.libresonic.player.command.*;
+import org.libresonic.player.controller.*;
+
+/**
+ * Validator for {@link PasswordSettingsController}.
+ *
+ * @author Sindre Mehus
+ */
+@Component
+public class PasswordSettingsValidator implements Validator {
+
+ public boolean supports(Class clazz) {
+ return clazz.equals(PasswordSettingsCommand.class);
+ }
+
+ public void validate(Object obj, Errors errors) {
+ PasswordSettingsCommand command = (PasswordSettingsCommand) obj;
+
+ if (command.getPassword() == null || command.getPassword().length() == 0) {
+ errors.rejectValue("password", "usersettings.nopassword");
+ } else if (!command.getPassword().equals(command.getConfirmPassword())) {
+ errors.rejectValue("password", "usersettings.wrongpassword");
+ }
+ }
+}
diff --git a/libresonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp b/libresonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp
index b7010c03..e63f9842 100644
--- a/libresonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp
+++ b/libresonic-main/src/main/webapp/WEB-INF/jsp/passwordSettings.jsp
@@ -23,6 +23,7 @@
${command.username}
${fn:escapeXml(title)}
+