From 884826b3b8eab657e025c4b3ac8dac6ae99c2cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Cocula?= Date: Thu, 5 Jan 2017 22:33:08 +0100 Subject: [PATCH 1/3] WIP --- .../command/PasswordSettingsCommand.java | 75 ++++++++++++++++ .../player/controller/LoginController.java | 12 +-- .../PasswordSettingsController.java | 89 +++++++++++++++++++ .../player/security/WebSecurityConfig.java | 5 +- .../validator/PasswordSettingsValidator.java | 48 ++++++++++ 5 files changed, 217 insertions(+), 12 deletions(-) create mode 100644 libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java create mode 100644 libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java create mode 100644 libresonic-main/src/main/java/org/libresonic/player/validator/PasswordSettingsValidator.java 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..8f12e554 --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java @@ -0,0 +1,75 @@ +/* + 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; + private boolean toast; + + 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; + } + + public boolean isToast() { + return toast; + } + + public void setToast(boolean toast) { + this.toast = toast; + } +} \ 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..63f0504b --- /dev/null +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java @@ -0,0 +1,89 @@ +/* + 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.validator.PasswordSettingsValidator; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpRequest; +import org.springframework.stereotype.*; +import org.springframework.validation.BindingResult; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.WebDataBinder; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.servlet.ModelAndView; +import org.springframework.web.servlet.mvc.*; +import org.libresonic.player.service.*; +import org.libresonic.player.command.*; +import org.libresonic.player.domain.*; +import org.springframework.web.servlet.mvc.support.RedirectAttributes; + +import javax.servlet.http.*; + +/** + * Controller for the page used to change password. + * + * @author Sindre Mehus + */ +@org.springframework.stereotype.Controller +@RequestMapping("/passwordSettings") +@SessionAttributes( value="command", types={PasswordSettingsCommand.class} ) +public class PasswordSettingsController { + + @Autowired + private SecurityService securityService; + @Autowired + private PasswordSettingsValidator passwordSettingsValidator; + + @InitBinder + protected void initBinder(WebDataBinder binder) { + binder.addValidators(passwordSettingsValidator); + } + + /* @ModelAttribute + protected Object formBackingObject(HttpServletRequest request) throws Exception { + PasswordSettingsCommand command = new PasswordSettingsCommand(); + User user = securityService.getCurrentUser(request); + command.setUsername(user.getUsername()); + command.setLdapAuthenticated(user.isLdapAuthenticated()); + return command; + }*/ + + @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(@ModelAttribute("command") @Validated PasswordSettingsCommand command) throws Exception { + User user = securityService.getUserByName(command.getUsername()); + user.setPassword(command.getPassword()); + securityService.updateUser(user); + + command.setPassword(null); + command.setConfirmPassword(null); + command.setToast(true); + return "passwordSettings"; + } + +} 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"); + } + } +} From 4c49c77641e0910c047278842703c10fc3aadcea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Cocula?= Date: Thu, 5 Jan 2017 23:23:47 +0100 Subject: [PATCH 2/3] Restore PasswordSettingsController --- .../command/PasswordSettingsCommand.java | 8 ------ .../PasswordSettingsController.java | 27 ++++++++----------- .../webapp/WEB-INF/jsp/passwordSettings.jsp | 1 + 3 files changed, 12 insertions(+), 24 deletions(-) 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 index 8f12e554..fe9664b5 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java +++ b/libresonic-main/src/main/java/org/libresonic/player/command/PasswordSettingsCommand.java @@ -31,7 +31,6 @@ public class PasswordSettingsCommand { private String password; private String confirmPassword; private boolean ldapAuthenticated; - private boolean toast; public String getUsername() { return username; @@ -65,11 +64,4 @@ public class PasswordSettingsCommand { this.ldapAuthenticated = ldapAuthenticated; } - public boolean isToast() { - return toast; - } - - public void setToast(boolean toast) { - this.toast = toast; - } } \ No newline at end of file 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 index 63f0504b..003792f6 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java @@ -43,7 +43,7 @@ import javax.servlet.http.*; */ @org.springframework.stereotype.Controller @RequestMapping("/passwordSettings") -@SessionAttributes( value="command", types={PasswordSettingsCommand.class} ) +//@SessionAttributes( value="command", types={PasswordSettingsCommand.class} ) public class PasswordSettingsController { @Autowired @@ -56,14 +56,6 @@ public class PasswordSettingsController { binder.addValidators(passwordSettingsValidator); } - /* @ModelAttribute - protected Object formBackingObject(HttpServletRequest request) throws Exception { - PasswordSettingsCommand command = new PasswordSettingsCommand(); - User user = securityService.getCurrentUser(request); - command.setUsername(user.getUsername()); - command.setLdapAuthenticated(user.isLdapAuthenticated()); - return command; - }*/ @RequestMapping(method = RequestMethod.GET) protected ModelAndView displayForm(HttpServletRequest request) throws Exception { @@ -75,14 +67,17 @@ public class PasswordSettingsController { } @RequestMapping(method = RequestMethod.POST) - protected String doSubmitAction(@ModelAttribute("command") @Validated PasswordSettingsCommand command) throws Exception { - User user = securityService.getUserByName(command.getUsername()); - user.setPassword(command.getPassword()); - securityService.updateUser(user); + protected String doSubmitAction(HttpServletRequest request,@ModelAttribute("command") @Validated PasswordSettingsCommand command,BindingResult bindingResult) throws Exception { + if (!bindingResult.hasErrors()) { + User user = securityService.getUserByName(command.getUsername()); + user.setPassword(command.getPassword()); + securityService.updateUser(user); + + command.setPassword(null); + command.setConfirmPassword(null); + request.setAttribute("settings_toast",true); - command.setPassword(null); - command.setConfirmPassword(null); - command.setToast(true); + } return "passwordSettings"; } 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)}

+ From 6027f7ce15de05cd0276ec1eb5747409014e0cf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Cocula?= Date: Sat, 7 Jan 2017 14:26:48 +0100 Subject: [PATCH 3/3] Fix after code review --- .../PasswordSettingsController.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) 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 index 003792f6..4451ad98 100644 --- a/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java +++ b/libresonic-main/src/main/java/org/libresonic/player/controller/PasswordSettingsController.java @@ -19,22 +19,22 @@ */ 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.http.HttpRequest; -import org.springframework.stereotype.*; import org.springframework.validation.BindingResult; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.WebDataBinder; -import org.springframework.web.bind.annotation.*; +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.*; -import org.libresonic.player.service.*; -import org.libresonic.player.command.*; -import org.libresonic.player.domain.*; import org.springframework.web.servlet.mvc.support.RedirectAttributes; -import javax.servlet.http.*; +import javax.servlet.http.HttpServletRequest; /** * Controller for the page used to change password. @@ -43,7 +43,6 @@ import javax.servlet.http.*; */ @org.springframework.stereotype.Controller @RequestMapping("/passwordSettings") -//@SessionAttributes( value="command", types={PasswordSettingsCommand.class} ) public class PasswordSettingsController { @Autowired @@ -67,7 +66,7 @@ public class PasswordSettingsController { } @RequestMapping(method = RequestMethod.POST) - protected String doSubmitAction(HttpServletRequest request,@ModelAttribute("command") @Validated PasswordSettingsCommand command,BindingResult bindingResult) throws Exception { + 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()); @@ -75,10 +74,12 @@ public class PasswordSettingsController { command.setPassword(null); command.setConfirmPassword(null); - request.setAttribute("settings_toast",true); + redirectAttributes.addFlashAttribute("settings_toast", true); + } else { + return "passwordSettings"; } - return "passwordSettings"; + return "redirect:passwordSettings.view"; } }