From b78ec441514b0d9f0dd097cff144c982c506811e Mon Sep 17 00:00:00 2001 From: DOHA Date: Wed, 4 Mar 2015 12:49:05 +0200 Subject: [PATCH 1/4] fix database properties --- spring-security-oauth/src/main/resources/persistence.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spring-security-oauth/src/main/resources/persistence.properties b/spring-security-oauth/src/main/resources/persistence.properties index 75df42e5d0..0bfb48fce4 100644 --- a/spring-security-oauth/src/main/resources/persistence.properties +++ b/spring-security-oauth/src/main/resources/persistence.properties @@ -1,6 +1,6 @@ ################### DataSource Configuration ########################## jdbc.driverClassName=com.mysql.jdbc.Driver -jdbc.url=jdbc:mysql://localhost:3606/oauth_reddit?createDatabaseIfNotExist=true +jdbc.url=jdbc:mysql://localhost:3306/oauth_reddit?createDatabaseIfNotExist=true jdbc.user=tutorialuser jdbc.pass=tutorialmy5ql init-db=false From a838368db4c82a04d28daf1c08edaad95d54c352 Mon Sep 17 00:00:00 2001 From: DOHA Date: Wed, 4 Mar 2015 13:03:33 +0200 Subject: [PATCH 2/4] minor fix --- .../src/main/webapp/WEB-INF/jsp/postListView.jsp | 2 +- .../src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp index 0e9e20a674..5c750cbda4 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp @@ -40,7 +40,7 @@ Post title Submission Date -Notes +Status diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp index 5539ce6ff5..9f808012b1 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp @@ -63,7 +63,7 @@

- + From e86cc290febd2dbe3572b9361fca7360931b90ab Mon Sep 17 00:00:00 2001 From: DOHA Date: Wed, 4 Mar 2015 18:09:01 +0200 Subject: [PATCH 3/4] minor changes --- .../org/baeldung/web/RedditController.java | 12 ++++++--- .../main/webapp/WEB-INF/jsp/postListView.jsp | 10 +++++--- .../src/main/webapp/WEB-INF/jsp/reddit.jsp | 25 ++++++++----------- .../webapp/WEB-INF/jsp/schedulePostForm.jsp | 10 +++++--- .../webapp/WEB-INF/jsp/submissionForm.jsp | 10 +++++--- .../webapp/WEB-INF/jsp/submissionResponse.jsp | 8 +++--- 6 files changed, 42 insertions(+), 33 deletions(-) diff --git a/spring-security-oauth/src/main/java/org/baeldung/web/RedditController.java b/spring-security-oauth/src/main/java/org/baeldung/web/RedditController.java index 5fb746551b..a8f48684cf 100644 --- a/spring-security-oauth/src/main/java/org/baeldung/web/RedditController.java +++ b/spring-security-oauth/src/main/java/org/baeldung/web/RedditController.java @@ -7,6 +7,8 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import javax.servlet.http.HttpSession; + import org.baeldung.persistence.dao.PostRepository; import org.baeldung.persistence.dao.UserRepository; import org.baeldung.persistence.model.Post; @@ -22,6 +24,7 @@ import org.springframework.ui.Model; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import com.fasterxml.jackson.databind.JsonNode; @@ -43,15 +46,15 @@ public class RedditController { private PostRepository postReopsitory; @RequestMapping("/info") - public final String getInfo(final Model model) { + public final String getInfo(HttpSession session) { final JsonNode node = redditRestTemplate.getForObject("https://oauth.reddit.com/api/v1/me", JsonNode.class); final String name = node.get("name").asText(); addUser(name, redditRestTemplate.getAccessToken()); - model.addAttribute("info", name); + session.setAttribute("username", name); return "reddit"; } - @RequestMapping("/submit") + @RequestMapping(value = "/submit", method = RequestMethod.POST) public final String submit(final Model model, @RequestParam final Map formParams) { final MultiValueMap param1 = constructParams(formParams); @@ -83,7 +86,7 @@ public class RedditController { return "schedulePostForm"; } - @RequestMapping("/schedule") + @RequestMapping(value = "/schedule", method = RequestMethod.POST) public final String schedule(final Model model, @RequestParam final Map formParams) throws ParseException { logger.info("User scheduling Post with these parameters: " + formParams.entrySet()); final User user = userReopsitory.findByAccessToken(redditRestTemplate.getAccessToken().getValue()); @@ -182,6 +185,7 @@ public class RedditController { user.setTokenExpiration(token.getExpiration()); userReopsitory.save(user); } + } } diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp index 5c750cbda4..dc32612c8e 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/postListView.jsp @@ -19,15 +19,17 @@ - Spring Security OAuth + Schedule to Reddit + + diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/reddit.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/reddit.jsp index d8c9809fd8..1da8e5a580 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/reddit.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/reddit.jsp @@ -17,32 +17,29 @@ - Spring Security OAuth + Schedule to Reddit + +
- - -

Welcome, ${info}

- Submit to Reddit -
- - Sorry, error occurred -

-
${error}
-
-
+

Welcome,

+
+ My Scheduled Posts + Post to Reddit + Schedule Post to Reddit +
\ No newline at end of file diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp index 9f808012b1..976354976c 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/schedulePostForm.jsp @@ -20,22 +20,24 @@ - Spring Security OAuth + Schedule to Reddit + +
-

Schedule Post

+

Schedule Post to Reddit

diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionForm.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionForm.jsp index 9944a6893e..17d8c3680c 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionForm.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionForm.jsp @@ -17,22 +17,24 @@ - Spring Security OAuth + Schedule to Reddit
+ +
-

Submit to Reddit

+

Post to Reddit

diff --git a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionResponse.jsp b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionResponse.jsp index 2b6337e2a0..3f35c396d2 100755 --- a/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionResponse.jsp +++ b/spring-security-oauth/src/main/webapp/WEB-INF/jsp/submissionResponse.jsp @@ -17,15 +17,17 @@ - Spring Security OAuth + Schedule to Reddit
+ + From 87283a97f9fe2a79458559c52c4db1c2e53375d0 Mon Sep 17 00:00:00 2001 From: DOHA Date: Fri, 6 Mar 2015 21:20:05 +0200 Subject: [PATCH 4/4] add spring registration front end --- .../.classpath | 32 +++ .../.project | 48 ++++ .../pom.xml | 192 ++++++++++++++++ .../dao/PasswordResetTokenRepository.java | 12 + .../persistence/dao/PrivilegeRepository.java | 10 + .../persistence/dao/RoleRepository.java | 10 + .../persistence/dao/UserRepository.java | 11 + .../dao/VerificationTokenRepository.java | 12 + .../persistence/model/PasswordResetToken.java | 132 +++++++++++ .../baeldung/persistence/model/Privilege.java | 83 +++++++ .../org/baeldung/persistence/model/Role.java | 98 +++++++++ .../org/baeldung/persistence/model/User.java | 137 ++++++++++++ .../persistence/model/VerificationToken.java | 132 +++++++++++ .../persistence/service/IUserService.java | 35 +++ .../baeldung/persistence/service/UserDto.java | 88 ++++++++ .../persistence/service/UserService.java | 131 +++++++++++ .../OnRegistrationCompleteEvent.java | 33 +++ .../listener/RegistrationListener.java | 63 ++++++ .../AuthenticationFailureListener.java | 19 ++ .../AuthenticationSuccessEventListener.java | 19 ++ .../security/LoginAttemptService.java | 49 +++++ ...SimpleUrlAuthenticationSuccessHandler.java | 83 +++++++ .../security/MyUserDetailsService.java | 95 ++++++++ .../java/org/baeldung/spring/AppConfig.java | 44 ++++ .../java/org/baeldung/spring/MvcConfig.java | 104 +++++++++ .../baeldung/spring/PersistenceJPAConfig.java | 75 +++++++ .../baeldung/spring/SecSecurityConfig.java | 94 ++++++++ .../org/baeldung/spring/SetupDataLoader.java | 89 ++++++++ .../java/org/baeldung/test/TestConfig.java | 17 ++ .../validation/EmailExistsException.java | 9 + .../baeldung/validation/EmailValidator.java | 28 +++ .../baeldung/validation/PasswordMatches.java | 24 ++ .../validation/PasswordMatchesValidator.java | 19 ++ .../baeldung/validation/UserValidator.java | 23 ++ .../org/baeldung/validation/ValidEmail.java | 24 ++ .../controller/RegistrationController.java | 207 ++++++++++++++++++ .../RestResponseEntityExceptionHandler.java | 48 ++++ .../web/error/UserNotFoundException.java | 23 ++ .../baeldung/web/util/GenericResponse.java | 54 +++++ .../src/main/resources/.gitignore | 1 + .../main/resources/email.properties.sample | 7 + .../src/main/resources/logback.xml | 20 ++ .../src/main/resources/messages_en.properties | 67 ++++++ .../main/resources/messages_es_ES.properties | 67 ++++++ .../src/main/resources/persistence.properties | 10 + .../src/main/resources/webSecurityConfig.xml | 39 ++++ .../src/main/webapp/META-INF/MANIFEST.MF | 3 + .../src/main/webapp/WEB-INF/mvc-servlet.xml | 5 + .../src/main/webapp/WEB-INF/view/admin.jsp | 34 +++ .../src/main/webapp/WEB-INF/view/badUser.jsp | 54 +++++ .../src/main/webapp/WEB-INF/view/console.jsp | 36 +++ .../main/webapp/WEB-INF/view/emailError.jsp | 17 ++ .../webapp/WEB-INF/view/expiredAccount.jsp | 24 ++ .../webapp/WEB-INF/view/forgetPassword.jsp | 56 +++++ .../src/main/webapp/WEB-INF/view/home.jsp | 28 +++ .../src/main/webapp/WEB-INF/view/homepage.jsp | 38 ++++ .../webapp/WEB-INF/view/invalidSession.jsp | 18 ++ .../src/main/webapp/WEB-INF/view/login.jsp | 109 +++++++++ .../src/main/webapp/WEB-INF/view/logout.jsp | 31 +++ .../main/webapp/WEB-INF/view/registration.jsp | 94 ++++++++ .../WEB-INF/view/regitrationConfirm.jsp | 23 ++ .../webapp/WEB-INF/view/successRegister.jsp | 25 +++ .../webapp/WEB-INF/view/updatePassword.jsp | 60 +++++ .../src/main/webapp/WEB-INF/web.xml | 51 +++++ .../test/SpringSecurityRolesTest.java | 121 ++++++++++ 65 files changed, 3444 insertions(+) create mode 100644 spring-security-login-and-registration-frontend/.classpath create mode 100644 spring-security-login-and-registration-frontend/.project create mode 100644 spring-security-login-and-registration-frontend/pom.xml create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/RoleRepository.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/UserRepository.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Privilege.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Role.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/User.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/VerificationToken.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/IUserService.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserDto.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserService.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/listener/RegistrationListener.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationFailureListener.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/LoginAttemptService.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MyUserDetailsService.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/AppConfig.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/MvcConfig.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SecSecurityConfig.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SetupDataLoader.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/test/TestConfig.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailExistsException.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailValidator.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatches.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/UserValidator.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/ValidEmail.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/controller/RegistrationController.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/UserNotFoundException.java create mode 100644 spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/util/GenericResponse.java create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/.gitignore create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/email.properties.sample create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/logback.xml create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/messages_en.properties create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/messages_es_ES.properties create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/persistence.properties create mode 100644 spring-security-login-and-registration-frontend/src/main/resources/webSecurityConfig.xml create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/META-INF/MANIFEST.MF create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/mvc-servlet.xml create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/admin.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/badUser.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/console.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/emailError.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/expiredAccount.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/forgetPassword.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/home.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/homepage.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/invalidSession.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/login.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/logout.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/registration.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/successRegister.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/updatePassword.jsp create mode 100644 spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/web.xml create mode 100644 spring-security-login-and-registration-frontend/src/test/java/org/baeldung/test/SpringSecurityRolesTest.java diff --git a/spring-security-login-and-registration-frontend/.classpath b/spring-security-login-and-registration-frontend/.classpath new file mode 100644 index 0000000000..c0f4868f56 --- /dev/null +++ b/spring-security-login-and-registration-frontend/.classpath @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-security-login-and-registration-frontend/.project b/spring-security-login-and-registration-frontend/.project new file mode 100644 index 0000000000..00da6328b5 --- /dev/null +++ b/spring-security-login-and-registration-frontend/.project @@ -0,0 +1,48 @@ + + + spring-security-login-and-registration-frontend + + + + + + org.eclipse.wst.jsdt.core.javascriptValidator + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.wst.common.project.facet.core.builder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + org.springframework.ide.eclipse.core.springbuilder + + + + + org.eclipse.wst.validation.validationbuilder + + + + + + org.eclipse.jem.workbench.JavaEMFNature + org.eclipse.wst.common.modulecore.ModuleCoreNature + org.springframework.ide.eclipse.core.springnature + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + org.eclipse.wst.common.project.facet.core.nature + org.eclipse.wst.jsdt.core.jsNature + + diff --git a/spring-security-login-and-registration-frontend/pom.xml b/spring-security-login-and-registration-frontend/pom.xml new file mode 100644 index 0000000000..36774b713c --- /dev/null +++ b/spring-security-login-and-registration-frontend/pom.xml @@ -0,0 +1,192 @@ + + + 4.0.0 + org.baeldung + spring-security-login-and-registration-frontend + spring-security-login-and-registration-frontend + war + 1.0.1-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-parent + 1.1.10.RELEASE + + + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework + spring-context-support + + + org.springframework.security + spring-security-config + runtime + + + + + + + + + + + javax.servlet + javax.servlet-api + + + javax.servlet.jsp + javax.servlet.jsp-api + ${javax.servlet.jsp-api.version} + + + javax.servlet + jstl + + + org.springframework.security + spring-security-taglibs + + + javax.el + el-api + 2.2 + + + + org.springframework + spring-test + 4.1.4.RELEASE + test + + + + + org.springframework.data + spring-data-jpa + + + org.hibernate + hibernate-entitymanager + + + + + + + + + org.hibernate + hibernate-validator + + + + + mysql + mysql-connector-java + + + commons-dbcp + commons-dbcp + + + com.fasterxml.jackson.core + jackson-databind + + + javax.mail + mail + 1.4.7 + + + com.google.guava + guava + ${guava.version} + + + + + org.slf4j + slf4j-api + + + ch.qos.logback + logback-classic + + + org.slf4j + jcl-over-slf4j + + + + org.slf4j + log4j-over-slf4j + + + + + junit + junit + test + + + + + + spring-security-login-and-registration-frontend + + + src/main/resources + true + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java-version} + ${java-version} + + + + + org.apache.maven.plugins + maven-war-plugin + + + + + + + 1.7 + 3.1.4.RELEASE + 3.2.5.RELEASE + + + 1.7.7 + 1.1.2 + + + 2.3.2-b01 + + + 1 + + + 1.7.1.RELEASE + + + 18.0 + + + diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java new file mode 100644 index 0000000000..9ef80fe8b1 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PasswordResetTokenRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.PasswordResetToken; +import org.baeldung.persistence.model.User; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PasswordResetTokenRepository extends JpaRepository { + + public PasswordResetToken findByToken(String token); + + public PasswordResetToken findByUser(User user); +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java new file mode 100644 index 0000000000..3f8016f314 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/PrivilegeRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.Privilege; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface PrivilegeRepository extends JpaRepository { + public Privilege findByName(String name); + + public void delete(Privilege privilege); +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/RoleRepository.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/RoleRepository.java new file mode 100644 index 0000000000..90d6de60f2 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/RoleRepository.java @@ -0,0 +1,10 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.Role; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface RoleRepository extends JpaRepository { + public Role findByName(String name); + + public void delete(Role role); +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/UserRepository.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/UserRepository.java new file mode 100644 index 0000000000..12f07d8692 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/UserRepository.java @@ -0,0 +1,11 @@ +package org.baeldung.persistence.dao; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.baeldung.persistence.model.User; + +public interface UserRepository extends JpaRepository { + public User findByEmail(String email); + + public void delete(User user); + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java new file mode 100644 index 0000000000..f9fc850d41 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/dao/VerificationTokenRepository.java @@ -0,0 +1,12 @@ +package org.baeldung.persistence.dao; + +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.model.VerificationToken; +import org.springframework.data.jpa.repository.JpaRepository; + +public interface VerificationTokenRepository extends JpaRepository { + + public VerificationToken findByToken(String token); + + public VerificationToken findByUser(User user); +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java new file mode 100644 index 0000000000..cfff0135da --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/PasswordResetToken.java @@ -0,0 +1,132 @@ +package org.baeldung.persistence.model; + +import java.util.Calendar; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Entity +public class PasswordResetToken { + + private static final int EXPIRATION = 60 * 24; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String token; + + @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER) + @JoinColumn(nullable = false, name = "user_id") + private User user; + + private Date expiryDate; + + public PasswordResetToken() { + super(); + } + + public PasswordResetToken(String token) { + super(); + + this.token = token; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + public PasswordResetToken(String token, User user) { + super(); + + this.token = token; + this.user = user; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Date getExpiryDate() { + return expiryDate; + } + + public void setExpiryDate(Date expiryDate) { + this.expiryDate = expiryDate; + } + + private Date calculateExpiryDate(int expiryTimeInMinutes) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(new Date().getTime()); + cal.add(Calendar.MINUTE, expiryTimeInMinutes); + return new Date(cal.getTime().getTime()); + } + + public void updateToken(String token) { + this.token = token; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((expiryDate == null) ? 0 : expiryDate.hashCode()); + result = prime * result + ((token == null) ? 0 : token.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + PasswordResetToken other = (PasswordResetToken) obj; + if (expiryDate == null) { + if (other.expiryDate != null) + return false; + } else if (!expiryDate.equals(other.expiryDate)) + return false; + if (token == null) { + if (other.token != null) + return false; + } else if (!token.equals(other.token)) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Token [String=").append(token).append("]").append("[Expires").append(expiryDate).append("]"); + return builder.toString(); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Privilege.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Privilege.java new file mode 100644 index 0000000000..c403ffb7a2 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Privilege.java @@ -0,0 +1,83 @@ +package org.baeldung.persistence.model; + +import java.util.Collection; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.ManyToMany; + +@Entity +public class Privilege { + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String name; + + @ManyToMany(mappedBy = "privileges") + private Collection roles; + + public Privilege() { + super(); + } + + public Privilege(String name) { + super(); + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(Collection roles) { + this.roles = roles; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Privilege privilege = (Privilege) obj; + if (!privilege.equals(privilege.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Privilege [name=").append(name).append("]").append("[id=").append(id).append("]"); + return builder.toString(); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Role.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Role.java new file mode 100644 index 0000000000..c656f134d9 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/Role.java @@ -0,0 +1,98 @@ +package org.baeldung.persistence.model; + +import java.util.Collection; + +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; +import javax.persistence.JoinColumn; + +@Entity +public class Role { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + @ManyToMany(mappedBy = "roles") + private Collection users; + + @ManyToMany + @JoinTable(name = "roles_privileges", joinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "privilege_id", referencedColumnName = "id")) + private Collection privileges; + + private String name; + + public Role() { + super(); + } + + public Role(String name) { + super(); + this.name = name; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Collection getUsers() { + return users; + } + + public void setUsers(Collection users) { + this.users = users; + } + + public Collection getPrivileges() { + return privileges; + } + + public void setPrivileges(Collection privileges) { + this.privileges = privileges; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((name == null) ? 0 : name.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final Role role = (Role) obj; + if (!role.equals(role.name)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Role [name=").append(name).append("]").append("[id=").append(id).append("]"); + return builder.toString(); + } +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/User.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/User.java new file mode 100644 index 0000000000..4fc2d57f5b --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/User.java @@ -0,0 +1,137 @@ +package org.baeldung.persistence.model; + +import java.util.Collection; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.JoinTable; +import javax.persistence.ManyToMany; + +@Entity +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String firstName; + + private String lastName; + + private String email; + + @Column(length = 60) + private String password; + + private boolean enabled; + + private boolean tokenExpired; + + @ManyToMany + @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")) + private Collection roles; + + public User() { + super(); + this.enabled = false; + this.tokenExpired = false; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getEmail() { + return email; + } + + public void setEmail(String username) { + this.email = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public Collection getRoles() { + return roles; + } + + public void setRoles(Collection roles) { + this.roles = roles; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public boolean isTokenExpired() { + return tokenExpired; + } + + public void setTokenExpired(boolean expired) { + this.tokenExpired = expired; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((email == null) ? 0 : email.hashCode()); + return result; + } + + @Override + public boolean equals(final Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + final User user = (User) obj; + if (!email.equals(user.email)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[username").append(email).append("]"); + return builder.toString(); + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/VerificationToken.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/VerificationToken.java new file mode 100644 index 0000000000..a25750d3d0 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/model/VerificationToken.java @@ -0,0 +1,132 @@ +package org.baeldung.persistence.model; + +import java.util.Calendar; +import java.util.Date; + +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Entity +public class VerificationToken { + + private static final int EXPIRATION = 60 * 24; + + @Id + @GeneratedValue(strategy = GenerationType.AUTO) + private Long id; + + private String token; + + @OneToOne(targetEntity = User.class, fetch = FetchType.EAGER) + @JoinColumn(nullable = false, name = "user_id") + private User user; + + private Date expiryDate; + + public VerificationToken() { + super(); + } + + public VerificationToken(String token) { + super(); + + this.token = token; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + public VerificationToken(String token, User user) { + super(); + + this.token = token; + this.user = user; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + public String getToken() { + return token; + } + + public void setToken(String token) { + this.token = token; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Date getExpiryDate() { + return expiryDate; + } + + public void setExpiryDate(Date expiryDate) { + this.expiryDate = expiryDate; + } + + private Date calculateExpiryDate(int expiryTimeInMinutes) { + Calendar cal = Calendar.getInstance(); + cal.setTimeInMillis(new Date().getTime()); + cal.add(Calendar.MINUTE, expiryTimeInMinutes); + return new Date(cal.getTime().getTime()); + } + + public void updateToken(String token) { + this.token = token; + this.expiryDate = calculateExpiryDate(EXPIRATION); + } + + // + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((expiryDate == null) ? 0 : expiryDate.hashCode()); + result = prime * result + ((token == null) ? 0 : token.hashCode()); + result = prime * result + ((user == null) ? 0 : user.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + VerificationToken other = (VerificationToken) obj; + if (expiryDate == null) { + if (other.expiryDate != null) + return false; + } else if (!expiryDate.equals(other.expiryDate)) + return false; + if (token == null) { + if (other.token != null) + return false; + } else if (!token.equals(other.token)) + return false; + if (user == null) { + if (other.user != null) + return false; + } else if (!user.equals(other.user)) + return false; + return true; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("Token [String=").append(token).append("]").append("[Expires").append(expiryDate).append("]"); + return builder.toString(); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/IUserService.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/IUserService.java new file mode 100644 index 0000000000..50466449a1 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/IUserService.java @@ -0,0 +1,35 @@ +package org.baeldung.persistence.service; + +import org.baeldung.persistence.model.PasswordResetToken; +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.model.VerificationToken; +import org.baeldung.validation.EmailExistsException; + +public interface IUserService { + + User registerNewUserAccount(UserDto accountDto) throws EmailExistsException; + + User getUser(String verificationToken); + + void saveRegisteredUser(User user); + + void deleteUser(User user); + + void createVerificationTokenForUser(User user, String token); + + VerificationToken getVerificationToken(String VerificationToken); + + VerificationToken generateNewVerificationToken(String token); + + void createPasswordResetTokenForUser(User user, String token); + + User findUserByEmail(String email); + + PasswordResetToken getPasswordResetToken(String token); + + User getUserByPasswordResetToken(String token); + + User getUserByID(long id); + + void changeUserPassword(User user, String password); +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserDto.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserDto.java new file mode 100644 index 0000000000..4dac41c533 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserDto.java @@ -0,0 +1,88 @@ +package org.baeldung.persistence.service; + +import javax.validation.constraints.NotNull; + +import org.baeldung.validation.PasswordMatches; +import org.baeldung.validation.ValidEmail; +import org.hibernate.validator.constraints.NotEmpty; + +@PasswordMatches +public class UserDto { + @NotNull + @NotEmpty + private String firstName; + + @NotNull + @NotEmpty + private String lastName; + + @NotNull + @NotEmpty + private String password; + + @NotNull + @NotEmpty + private String matchingPassword; + + @ValidEmail + @NotNull + @NotEmpty + private String email; + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + private Integer role; + + public Integer getRole() { + return role; + } + + public void setRole(Integer role) { + this.role = role; + } + + public String getFirstName() { + return firstName; + } + + public void setFirstName(String firstName) { + this.firstName = firstName; + } + + public String getLastName() { + return lastName; + } + + public void setLastName(String lastName) { + this.lastName = lastName; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getMatchingPassword() { + return matchingPassword; + } + + public void setMatchingPassword(String matchingPassword) { + this.matchingPassword = matchingPassword; + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + builder.append("User [firstName=").append(firstName).append("]").append("[lastName=").append(lastName).append("]").append("[email").append(email).append("]").append("[password").append(password).append("]"); + return builder.toString(); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserService.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserService.java new file mode 100644 index 0000000000..b9509f4f3a --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/persistence/service/UserService.java @@ -0,0 +1,131 @@ +package org.baeldung.persistence.service; + +import java.util.Arrays; +import java.util.UUID; + +import javax.transaction.Transactional; + +import org.baeldung.persistence.dao.PasswordResetTokenRepository; +import org.baeldung.persistence.dao.RoleRepository; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.dao.VerificationTokenRepository; +import org.baeldung.persistence.model.PasswordResetToken; +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.model.VerificationToken; +import org.baeldung.validation.EmailExistsException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +@Service +@Transactional +public class UserService implements IUserService { + @Autowired + private UserRepository repository; + + @Autowired + private VerificationTokenRepository tokenRepository; + + @Autowired + private PasswordResetTokenRepository passwordTokenRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + @Autowired + private RoleRepository roleRepository; + + // API + + @Override + public User registerNewUserAccount(final UserDto accountDto) throws EmailExistsException { + if (emailExist(accountDto.getEmail())) { + throw new EmailExistsException("There is an account with that email adress: " + accountDto.getEmail()); + } + final User user = new User(); + + user.setFirstName(accountDto.getFirstName()); + user.setLastName(accountDto.getLastName()); + user.setPassword(passwordEncoder.encode(accountDto.getPassword())); + user.setEmail(accountDto.getEmail()); + + user.setRoles(Arrays.asList(roleRepository.findByName("ROLE_USER"))); + return repository.save(user); + } + + @Override + public User getUser(final String verificationToken) { + final User user = tokenRepository.findByToken(verificationToken).getUser(); + return user; + } + + @Override + public VerificationToken getVerificationToken(final String VerificationToken) { + return tokenRepository.findByToken(VerificationToken); + } + + @Override + public void saveRegisteredUser(final User user) { + repository.save(user); + } + + @Override + public void deleteUser(final User user) { + repository.delete(user); + } + + @Override + public void createVerificationTokenForUser(final User user, final String token) { + final VerificationToken myToken = new VerificationToken(token, user); + tokenRepository.save(myToken); + } + + @Override + public VerificationToken generateNewVerificationToken(final String existingVerificationToken) { + VerificationToken vToken = tokenRepository.findByToken(existingVerificationToken); + vToken.updateToken(UUID.randomUUID().toString()); + vToken = tokenRepository.save(vToken); + return vToken; + } + + @Override + public void createPasswordResetTokenForUser(final User user, final String token) { + final PasswordResetToken myToken = new PasswordResetToken(token, user); + passwordTokenRepository.save(myToken); + } + + @Override + public User findUserByEmail(final String email) { + return repository.findByEmail(email); + } + + @Override + public PasswordResetToken getPasswordResetToken(final String token) { + return passwordTokenRepository.findByToken(token); + } + + @Override + public User getUserByPasswordResetToken(final String token) { + return passwordTokenRepository.findByToken(token).getUser(); + } + + @Override + public User getUserByID(final long id) { + return repository.findOne(id); + } + + @Override + public void changeUserPassword(final User user, final String password) { + user.setPassword(passwordEncoder.encode(password)); + repository.save(user); + } + + private boolean emailExist(final String email) { + final User user = repository.findByEmail(email); + if (user != null) { + return true; + } + return false; + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java new file mode 100644 index 0000000000..ede14537e8 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/OnRegistrationCompleteEvent.java @@ -0,0 +1,33 @@ +package org.baeldung.registration; + +import java.util.Locale; + +import org.baeldung.persistence.model.User; +import org.springframework.context.ApplicationEvent; + +@SuppressWarnings("serial") +public class OnRegistrationCompleteEvent extends ApplicationEvent { + + private final String appUrl; + private final Locale locale; + private final User user; + + public OnRegistrationCompleteEvent(User user, Locale locale, String appUrl) { + super(user); + this.user = user; + this.locale = locale; + this.appUrl = appUrl; + } + + public String getAppUrl() { + return appUrl; + } + + public Locale getLocale() { + return locale; + } + + public User getUser() { + return user; + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/listener/RegistrationListener.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/listener/RegistrationListener.java new file mode 100644 index 0000000000..e57a3a1361 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/registration/listener/RegistrationListener.java @@ -0,0 +1,63 @@ +package org.baeldung.registration.listener; + +import java.util.UUID; + +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.service.IUserService; +import org.baeldung.registration.OnRegistrationCompleteEvent; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.MessageSource; +import org.springframework.core.env.Environment; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.stereotype.Component; + +@Component +public class RegistrationListener implements ApplicationListener { + @Autowired + private IUserService service; + + @Autowired + private MessageSource messages; + + @Autowired + private JavaMailSender mailSender; + + @Autowired + private Environment env; + + // API + + @Override + public void onApplicationEvent(final OnRegistrationCompleteEvent event) { + this.confirmRegistration(event); + } + + private void confirmRegistration(final OnRegistrationCompleteEvent event) { + final User user = event.getUser(); + final String token = UUID.randomUUID().toString(); + service.createVerificationTokenForUser(user, token); + + final SimpleMailMessage email = constructEmailMessage(event, user, token); + mailSender.send(email); + } + + // + + private final SimpleMailMessage constructEmailMessage(final OnRegistrationCompleteEvent event, final User user, final String token) { + final String recipientAddress = user.getEmail(); + final String subject = "Registration Confirmation"; + final String confirmationUrl = event.getAppUrl() + "/regitrationConfirm.html?token=" + token; + final String message = messages.getMessage("message.regSucc", null, event.getLocale()); + final SimpleMailMessage email = new SimpleMailMessage(); + email.setTo(recipientAddress); + email.setSubject(subject); + email.setText(message + " \r\n" + confirmationUrl); + email.setFrom(env.getProperty("support.email")); + System.out.println("ddddd"); + System.out.println(email.getText()); + return email; + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationFailureListener.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationFailureListener.java new file mode 100644 index 0000000000..3f1702defe --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationFailureListener.java @@ -0,0 +1,19 @@ +package org.baeldung.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.security.authentication.event.AuthenticationFailureBadCredentialsEvent; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +@Component +public class AuthenticationFailureListener implements ApplicationListener { + + @Autowired + private LoginAttemptService loginAttemptService; + + public void onApplicationEvent(AuthenticationFailureBadCredentialsEvent e) { + WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails(); + loginAttemptService.loginFailed(auth.getRemoteAddress()); + } +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java new file mode 100644 index 0000000000..dff78ac0db --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/AuthenticationSuccessEventListener.java @@ -0,0 +1,19 @@ +package org.baeldung.security; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.security.authentication.event.AuthenticationSuccessEvent; +import org.springframework.security.web.authentication.WebAuthenticationDetails; +import org.springframework.stereotype.Component; + +@Component +public class AuthenticationSuccessEventListener implements ApplicationListener { + + @Autowired + private LoginAttemptService loginAttemptService; + + public void onApplicationEvent(AuthenticationSuccessEvent e) { + WebAuthenticationDetails auth = (WebAuthenticationDetails) e.getAuthentication().getDetails(); + loginAttemptService.loginSucceeded(auth.getRemoteAddress()); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/LoginAttemptService.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/LoginAttemptService.java new file mode 100644 index 0000000000..d03b50932a --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/LoginAttemptService.java @@ -0,0 +1,49 @@ +package org.baeldung.security; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; + +import org.springframework.stereotype.Service; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +@Service +public class LoginAttemptService { + + private final int MAX_ATTEMPT = 10; + private LoadingCache attemptsCache; + + public LoginAttemptService() { + super(); + attemptsCache = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.DAYS).build(new CacheLoader() { + public Integer load(String key) { + return 0; + } + }); + } + + public void loginSucceeded(String key) { + attemptsCache.invalidate(key); + } + + public void loginFailed(String key) { + int attempts = 0; + try { + attempts = attemptsCache.get(key); + } catch (ExecutionException e) { + attempts = 0; + } + attempts++; + attemptsCache.put(key, attempts); + } + + public boolean isBlocked(String key) { + try { + return attemptsCache.get(key) >= MAX_ATTEMPT; + } catch (ExecutionException e) { + return false; + } + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java new file mode 100644 index 0000000000..09b22064b7 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MySimpleUrlAuthenticationSuccessHandler.java @@ -0,0 +1,83 @@ +package org.baeldung.security; + +import java.io.IOException; +import java.util.Collection; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.web.DefaultRedirectStrategy; +import org.springframework.security.web.RedirectStrategy; +import org.springframework.security.web.WebAttributes; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +@Component("myAuthenticationSuccessHandler") +public class MySimpleUrlAuthenticationSuccessHandler implements AuthenticationSuccessHandler { + private final Logger logger = LoggerFactory.getLogger(getClass()); + + private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy(); + + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + handle(request, response, authentication); + HttpSession session = request.getSession(false); + if (session != null) { + session.setMaxInactiveInterval(30); + } + clearAuthenticationAttributes(request); + } + + protected void handle(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException { + String targetUrl = determineTargetUrl(authentication); + + if (response.isCommitted()) { + logger.debug("Response has already been committed. Unable to redirect to " + targetUrl); + return; + } + + redirectStrategy.sendRedirect(request, response, targetUrl); + } + + protected String determineTargetUrl(Authentication authentication) { + boolean isUser = false; + boolean isAdmin = false; + Collection authorities = authentication.getAuthorities(); + for (GrantedAuthority grantedAuthority : authorities) { + if (grantedAuthority.getAuthority().equals("READ_PRIVILEGE")) { + isUser = true; + } else if (grantedAuthority.getAuthority().equals("WRITE_PRIVILEGE")) { + isAdmin = true; + isUser = false; + break; + } + } + if (isUser) { + return "/homepage.html?user=" + authentication.getName(); + } else if (isAdmin) { + return "/console.html"; + } else { + throw new IllegalStateException(); + } + } + + protected void clearAuthenticationAttributes(HttpServletRequest request) { + HttpSession session = request.getSession(false); + if (session == null) { + return; + } + session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION); + } + + public void setRedirectStrategy(RedirectStrategy redirectStrategy) { + this.redirectStrategy = redirectStrategy; + } + + protected RedirectStrategy getRedirectStrategy() { + return redirectStrategy; + } +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MyUserDetailsService.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MyUserDetailsService.java new file mode 100644 index 0000000000..0de7fadd46 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/security/MyUserDetailsService.java @@ -0,0 +1,95 @@ +package org.baeldung.security; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import javax.servlet.http.HttpServletRequest; + +import org.baeldung.persistence.dao.RoleRepository; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.Privilege; +import org.baeldung.persistence.model.Role; +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.service.IUserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service("userDetailsService") +@Transactional +public class MyUserDetailsService implements UserDetailsService { + + @Autowired + private UserRepository userRepository; + @Autowired + private IUserService service; + @Autowired + private MessageSource messages; + @Autowired + private RoleRepository roleRepository; + + @Autowired + private LoginAttemptService loginAttemptService; + + @Autowired + private HttpServletRequest request; + + public MyUserDetailsService() { + super(); + } + + // API + + @Override + public UserDetails loadUserByUsername(final String email) throws UsernameNotFoundException { + String ip = request.getRemoteAddr(); + if (loginAttemptService.isBlocked(ip)) { + throw new RuntimeException("blocked"); + } + + try { + final User user = userRepository.findByEmail(email); + if (user == null) { + return new org.springframework.security.core.userdetails.User(" ", " ", true, true, true, true, getAuthorities(Arrays.asList(roleRepository.findByName("ROLE_USER")))); + } + + return new org.springframework.security.core.userdetails.User(user.getEmail(), user.getPassword(), user.isEnabled(), true, true, true, getAuthorities(user.getRoles())); + } catch (final Exception e) { + throw new RuntimeException(e); + } + } + + // UTIL + + public final Collection getAuthorities(final Collection roles) { + return getGrantedAuthorities(getPrivileges(roles)); + } + + private final List getPrivileges(final Collection roles) { + final List privileges = new ArrayList(); + final List collection = new ArrayList(); + for (Role role : roles) { + collection.addAll(role.getPrivileges()); + } + for (final Privilege item : collection) { + privileges.add(item.getName()); + } + return privileges; + } + + private final List getGrantedAuthorities(final List privileges) { + final List authorities = new ArrayList(); + for (final String privilege : privileges) { + authorities.add(new SimpleGrantedAuthority(privilege)); + } + return authorities; + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/AppConfig.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/AppConfig.java new file mode 100644 index 0000000000..219fcb729e --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/AppConfig.java @@ -0,0 +1,44 @@ +package org.baeldung.spring; + +import java.util.Properties; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.context.support.PropertySourcesPlaceholderConfigurer; +import org.springframework.core.env.Environment; +import org.springframework.mail.javamail.JavaMailSenderImpl; + +@Configuration +@ComponentScan(basePackages = { "org.baeldung.registration" }) +@PropertySource("classpath:email.properties") +public class AppConfig { + + @Autowired + private Environment env; + + // beans + + @Bean + public static PropertySourcesPlaceholderConfigurer propertyPlaceHolderConfigurer() { + return new PropertySourcesPlaceholderConfigurer(); + } + + @Bean + public JavaMailSenderImpl javaMailSenderImpl() { + JavaMailSenderImpl mailSenderImpl = new JavaMailSenderImpl(); + mailSenderImpl.setHost(env.getProperty("smtp.host")); + mailSenderImpl.setPort(env.getProperty("smtp.port", Integer.class)); + mailSenderImpl.setProtocol(env.getProperty("smtp.protocol")); + mailSenderImpl.setUsername(env.getProperty("smtp.username")); + mailSenderImpl.setPassword(env.getProperty("smtp.password")); + Properties javaMailProps = new Properties(); + javaMailProps.put("mail.smtp.auth", true); + javaMailProps.put("mail.smtp.starttls.enable", true); + mailSenderImpl.setJavaMailProperties(javaMailProps); + return mailSenderImpl; + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/MvcConfig.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/MvcConfig.java new file mode 100644 index 0000000000..bdf56f9fc5 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/MvcConfig.java @@ -0,0 +1,104 @@ +package org.baeldung.spring; + +import java.util.Locale; + +import org.baeldung.validation.EmailValidator; +import org.baeldung.validation.PasswordMatchesValidator; +import org.springframework.context.MessageSource; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.support.ReloadableResourceBundleMessageSource; +import org.springframework.web.servlet.LocaleResolver; +import org.springframework.web.servlet.ViewResolver; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; +import org.springframework.web.servlet.i18n.CookieLocaleResolver; +import org.springframework.web.servlet.i18n.LocaleChangeInterceptor; +import org.springframework.web.servlet.view.InternalResourceViewResolver; +import org.springframework.web.servlet.view.JstlView; + +@Configuration +@ComponentScan(basePackages = { "org.baeldung.web" }) +@EnableWebMvc +public class MvcConfig extends WebMvcConfigurerAdapter { + + public MvcConfig() { + super(); + } + + // + + @Override + public void addViewControllers(final ViewControllerRegistry registry) { + super.addViewControllers(registry); + registry.addViewController("/login.html"); + registry.addViewController("/logout.html"); + registry.addViewController("/registration.html"); + registry.addViewController("/homepage.html"); + registry.addViewController("/expiredAccount.html"); + registry.addViewController("/badUser.html"); + registry.addViewController("/emailError.html"); + registry.addViewController("/home.html"); + registry.addViewController("/invalidSession.html"); + registry.addViewController("/console.html"); + registry.addViewController("/admin.html"); + registry.addViewController("/successRegister.html"); + registry.addViewController("/forgetPassword.html"); + registry.addViewController("/updatePassword.html"); + } + + @Override + public void addResourceHandlers(final ResourceHandlerRegistry registry) { + registry.addResourceHandler("/resources/**").addResourceLocations("/", "/resources/"); + } + + @Override + public void addInterceptors(final InterceptorRegistry registry) { + final LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor(); + localeChangeInterceptor.setParamName("lang"); + registry.addInterceptor(localeChangeInterceptor); + } + + // beans + + @Bean + public ViewResolver viewResolver() { + final InternalResourceViewResolver bean = new InternalResourceViewResolver(); + bean.setViewClass(JstlView.class); + bean.setPrefix("/WEB-INF/view/"); + bean.setSuffix(".jsp"); + return bean; + } + + @Bean + public LocaleResolver localeResolver() { + final CookieLocaleResolver cookieLocaleResolver = new CookieLocaleResolver(); + cookieLocaleResolver.setDefaultLocale(Locale.ENGLISH); + return cookieLocaleResolver; + } + + @Bean + public MessageSource messageSource() { + final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource(); + messageSource.setBasename("classpath:messages"); + messageSource.setUseCodeAsDefaultMessage(true); + messageSource.setDefaultEncoding("UTF-8"); + messageSource.setCacheSeconds(0); + return messageSource; + } + + @Bean + public EmailValidator usernameValidator() { + return new EmailValidator(); + } + + @Bean + public PasswordMatchesValidator passwordMatchesValidator() { + return new PasswordMatchesValidator(); + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java new file mode 100644 index 0000000000..d2465af345 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/PersistenceJPAConfig.java @@ -0,0 +1,75 @@ +package org.baeldung.spring; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +@Configuration +@EnableTransactionManagement +@PropertySource({ "classpath:persistence.properties" }) +@ComponentScan({ "org.baeldung.persistence" }) +@EnableJpaRepositories(basePackages = "org.baeldung.persistence.dao") +public class PersistenceJPAConfig { + + @Autowired + private Environment env; + + public PersistenceJPAConfig() { + super(); + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "org.baeldung.persistence.model" }); + final HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + em.setJpaVendorAdapter(vendorAdapter); + em.setJpaProperties(additionalProperties()); + return em; + } + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName")); + dataSource.setUrl(env.getProperty("jdbc.url")); + dataSource.setUsername(env.getProperty("jdbc.user")); + dataSource.setPassword(env.getProperty("jdbc.pass")); + return dataSource; + } + + @Bean + public JpaTransactionManager transactionManager() { + final JpaTransactionManager transactionManager = new JpaTransactionManager(); + transactionManager.setEntityManagerFactory(entityManagerFactory().getObject()); + return transactionManager; + } + + @Bean + public PersistenceExceptionTranslationPostProcessor exceptionTranslation() { + return new PersistenceExceptionTranslationPostProcessor(); + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + return hibernateProperties; + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SecSecurityConfig.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SecSecurityConfig.java new file mode 100644 index 0000000000..ec07c22811 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SecSecurityConfig.java @@ -0,0 +1,94 @@ +package org.baeldung.spring; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +@Configuration +@ComponentScan(basePackages = { "org.baeldung.security" }) +@EnableWebSecurity +public class SecSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private AuthenticationSuccessHandler myAuthenticationSuccessHandler; + + public SecSecurityConfig() { + super(); + } + + @Override + protected void configure(AuthenticationManagerBuilder auth) throws Exception { + auth.authenticationProvider(authProvider()); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring().antMatchers("/resources/**"); + } + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http + .csrf().disable() + .authorizeRequests() + .antMatchers("/j_spring_security_check*","/login*", "/logout*", "/signin/**", "/signup/**", + "/user/registration*", "/regitrationConfirm*", "/expiredAccount*", "/registration*", + "/badUser*", "/user/resendRegistrationToken*" ,"/forgetPassword*", "/user/resetPassword*", + "/user/changePassword*", "/emailError*", "/resources/**").permitAll() + .antMatchers("/invalidSession*").anonymous() + .anyRequest().authenticated() + .and() + .formLogin() + .loginPage("/login.html") + .loginProcessingUrl("/j_spring_security_check") + .defaultSuccessUrl("/homepage.html") + .failureUrl("/login.html?error=true") + .successHandler(myAuthenticationSuccessHandler) + .usernameParameter("j_username") + .passwordParameter("j_password") + .permitAll() + .and() + .sessionManagement() + .invalidSessionUrl("/invalidSession.html") + .sessionFixation().none() + .and() + .logout() + .invalidateHttpSession(false) + .logoutUrl("/j_spring_security_logout") + .logoutSuccessUrl("/logout.html?logSucc=true") + .deleteCookies("JSESSIONID") + .permitAll(); + // @formatter:on + } + + // beans + + @Bean + public DaoAuthenticationProvider authProvider() { + DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(encoder()); + return authProvider; + } + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(11); + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SetupDataLoader.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SetupDataLoader.java new file mode 100644 index 0000000000..9f785b3239 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/spring/SetupDataLoader.java @@ -0,0 +1,89 @@ +package org.baeldung.spring; + +import java.util.Arrays; +import java.util.Collection; +import java.util.List; + +import org.baeldung.persistence.dao.PrivilegeRepository; +import org.baeldung.persistence.dao.RoleRepository; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.Privilege; +import org.baeldung.persistence.model.Role; +import org.baeldung.persistence.model.User; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +public class SetupDataLoader implements ApplicationListener { + + private boolean alreadySetup = false; + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + // API + + @Override + @Transactional + public void onApplicationEvent(final ContextRefreshedEvent event) { + if (alreadySetup) { + return; + } + + // == create initial privileges + final Privilege readPrivilege = createPrivilegeIfNotFound("READ_PRIVILEGE"); + final Privilege writePrivilege = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); + + // == create initial roles + final List adminPrivileges = Arrays.asList(readPrivilege, writePrivilege); + createRoleIfNotFound("ROLE_ADMIN", adminPrivileges); + createRoleIfNotFound("ROLE_USER", Arrays.asList(readPrivilege)); + + final Role adminRole = roleRepository.findByName("ROLE_ADMIN"); + final User user = new User(); + user.setFirstName("Test"); + user.setLastName("Test"); + user.setPassword(passwordEncoder.encode("test")); + user.setEmail("test@test.com"); + user.setRoles(Arrays.asList(adminRole)); + user.setEnabled(true); + userRepository.save(user); + + alreadySetup = true; + } + + @Transactional + private final Privilege createPrivilegeIfNotFound(final String name) { + Privilege privilege = privilegeRepository.findByName(name); + if (privilege == null) { + privilege = new Privilege(name); + privilegeRepository.save(privilege); + } + return privilege; + } + + @Transactional + private final Role createRoleIfNotFound(final String name, final Collection privileges) { + Role role = roleRepository.findByName(name); + if (role == null) { + role = new Role(name); + role.setPrivileges(privileges); + roleRepository.save(role); + } + return role; + } + +} \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/test/TestConfig.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/test/TestConfig.java new file mode 100644 index 0000000000..97b2c20632 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/test/TestConfig.java @@ -0,0 +1,17 @@ +package org.baeldung.test; + +import org.baeldung.spring.PersistenceJPAConfig; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +@ComponentScan({ "org.baeldung.persistence.dao" }) +public class TestConfig extends PersistenceJPAConfig { + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(11); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailExistsException.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailExistsException.java new file mode 100644 index 0000000000..952931bcff --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailExistsException.java @@ -0,0 +1,9 @@ +package org.baeldung.validation; + +@SuppressWarnings("serial") +public class EmailExistsException extends Throwable { + + public EmailExistsException(String message) { + super(message); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailValidator.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailValidator.java new file mode 100644 index 0000000000..bd69c7d550 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/EmailValidator.java @@ -0,0 +1,28 @@ +package org.baeldung.validation; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +public class EmailValidator implements ConstraintValidator { + private Pattern pattern; + private Matcher matcher; + private static final String EMAIL_PATTERN = "^[_A-Za-z0-9-\\+]+(\\.[_A-Za-z0-9-]+)*@" + "[A-Za-z0-9-]+(\\.[A-Za-z0-9]+)*(\\.[A-Za-z]{2,})$"; + + @Override + public void initialize(ValidEmail constraintAnnotation) { + } + + @Override + public boolean isValid(String username, ConstraintValidatorContext context) { + return (validateEmail(username)); + } + + private boolean validateEmail(String email) { + pattern = Pattern.compile(EMAIL_PATTERN); + matcher = pattern.matcher(email); + return matcher.matches(); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatches.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatches.java new file mode 100644 index 0000000000..a8322ad2f3 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatches.java @@ -0,0 +1,24 @@ +package org.baeldung.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({ TYPE, ANNOTATION_TYPE }) +@Retention(RUNTIME) +@Constraint(validatedBy = PasswordMatchesValidator.class) +@Documented +public @interface PasswordMatches { + + String message() default "Passwords don't match"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java new file mode 100644 index 0000000000..e8ec952fa8 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/PasswordMatchesValidator.java @@ -0,0 +1,19 @@ +package org.baeldung.validation; + +import javax.validation.ConstraintValidator; +import javax.validation.ConstraintValidatorContext; + +import org.baeldung.persistence.service.UserDto; + +public class PasswordMatchesValidator implements ConstraintValidator { + + @Override + public void initialize(PasswordMatches constraintAnnotation) { + } + + @Override + public boolean isValid(Object obj, ConstraintValidatorContext context) { + UserDto user = (UserDto) obj; + return user.getPassword().equals(user.getMatchingPassword()); + } +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/UserValidator.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/UserValidator.java new file mode 100644 index 0000000000..cfd3a78f81 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/UserValidator.java @@ -0,0 +1,23 @@ +package org.baeldung.validation; + +import org.baeldung.persistence.service.UserDto; +import org.springframework.validation.Errors; +import org.springframework.validation.ValidationUtils; +import org.springframework.validation.Validator; + +public class UserValidator implements Validator { + + @Override + public boolean supports(Class clazz) { + return UserDto.class.isAssignableFrom(clazz); + } + + @Override + public void validate(Object obj, Errors errors) { + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "firstName", "message.firstName", "Firstname is required."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "lastName", "message.lastName", "LastName is required."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "password", "message.password", "LastName is required."); + ValidationUtils.rejectIfEmptyOrWhitespace(errors, "username", "message.username", "UserName is required."); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/ValidEmail.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/ValidEmail.java new file mode 100644 index 0000000000..fa556c417c --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/validation/ValidEmail.java @@ -0,0 +1,24 @@ +package org.baeldung.validation; + +import javax.validation.Constraint; +import javax.validation.Payload; +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +@Target({ TYPE, FIELD, ANNOTATION_TYPE }) +@Retention(RUNTIME) +@Constraint(validatedBy = EmailValidator.class) +@Documented +public @interface ValidEmail { + + String message() default "Invalid Email"; + + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/controller/RegistrationController.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/controller/RegistrationController.java new file mode 100644 index 0000000000..906e36b0f4 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/controller/RegistrationController.java @@ -0,0 +1,207 @@ +package org.baeldung.web.controller; + +import java.util.Calendar; +import java.util.Locale; +import java.util.UUID; + +import javax.servlet.http.HttpServletRequest; +import javax.validation.Valid; + +import org.baeldung.persistence.model.PasswordResetToken; +import org.baeldung.persistence.model.User; +import org.baeldung.persistence.model.VerificationToken; +import org.baeldung.persistence.service.IUserService; +import org.baeldung.persistence.service.UserDto; +import org.baeldung.registration.OnRegistrationCompleteEvent; +import org.baeldung.validation.EmailExistsException; +import org.baeldung.web.error.UserNotFoundException; +import org.baeldung.web.util.GenericResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.MessageSource; +import org.springframework.core.env.Environment; +import org.springframework.mail.SimpleMailMessage; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; + +@Controller +public class RegistrationController { + private final Logger LOGGER = LoggerFactory.getLogger(getClass()); + + @Autowired + private IUserService userService; + + @Autowired + private MessageSource messages; + + @Autowired + private JavaMailSender mailSender; + + @Autowired + private ApplicationEventPublisher eventPublisher; + + @Autowired + private UserDetailsService userDetailsService; + + @Autowired + private Environment env; + + public RegistrationController() { + + } + + // Registration + + @RequestMapping(value = "/user/registration", method = RequestMethod.POST) + @ResponseBody + public GenericResponse registerUserAccount(@Valid final UserDto accountDto, final BindingResult result, final HttpServletRequest request) { + LOGGER.debug("Registering user account with information: {}", accountDto); + if (result.hasErrors()) { + return new GenericResponse(result.getFieldErrors(), result.getGlobalErrors()); + } + final User registered = createUserAccount(accountDto); + if (registered == null) { + return new GenericResponse("email", messages.getMessage("message.regError", null, request.getLocale())); + } + final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); + eventPublisher.publishEvent(new OnRegistrationCompleteEvent(registered, request.getLocale(), appUrl)); + + return new GenericResponse("success"); + } + + @RequestMapping(value = "/regitrationConfirm", method = RequestMethod.GET) + public String confirmRegistration(final Locale locale, final Model model, @RequestParam("token") final String token) { + final VerificationToken verificationToken = userService.getVerificationToken(token); + if (verificationToken == null) { + final String message = messages.getMessage("auth.message.invalidToken", null, locale); + model.addAttribute("message", message); + return "redirect:/badUser.html?lang=" + locale.getLanguage(); + } + + final User user = verificationToken.getUser(); + final Calendar cal = Calendar.getInstance(); + if ((verificationToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { + model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); + model.addAttribute("expired", true); + model.addAttribute("token", token); + return "redirect:/badUser.html?lang=" + locale.getLanguage(); + } + + user.setEnabled(true); + userService.saveRegisteredUser(user); + model.addAttribute("message", messages.getMessage("message.accountVerified", null, locale)); + return "redirect:/login.html?lang=" + locale.getLanguage(); + } + + // user activation - verification + + @RequestMapping(value = "/user/resendRegistrationToken", method = RequestMethod.GET) + @ResponseBody + public GenericResponse resendRegistrationToken(final HttpServletRequest request, @RequestParam("token") final String existingToken) { + final VerificationToken newToken = userService.generateNewVerificationToken(existingToken); + final User user = userService.getUser(newToken.getToken()); + final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); + final SimpleMailMessage email = constructResendVerificationTokenEmail(appUrl, request.getLocale(), newToken, user); + mailSender.send(email); + + return new GenericResponse(messages.getMessage("message.resendToken", null, request.getLocale())); + } + + // Reset password + + @RequestMapping(value = "/user/resetPassword", method = RequestMethod.POST) + @ResponseBody + public GenericResponse resetPassword(final HttpServletRequest request, @RequestParam("email") final String userEmail) { + final User user = userService.findUserByEmail(userEmail); + if (user == null) { + throw new UserNotFoundException(); + } + + final String token = UUID.randomUUID().toString(); + userService.createPasswordResetTokenForUser(user, token); + final String appUrl = "http://" + request.getServerName() + ":" + request.getServerPort() + request.getContextPath(); + final SimpleMailMessage email = constructResetTokenEmail(appUrl, request.getLocale(), token, user); + mailSender.send(email); + + return new GenericResponse(messages.getMessage("message.resetPasswordEmail", null, request.getLocale())); + } + + @RequestMapping(value = "/user/changePassword", method = RequestMethod.GET) + public String showChangePasswordPage(final Locale locale, final Model model, @RequestParam("id") final long id, @RequestParam("token") final String token) { + final PasswordResetToken passToken = userService.getPasswordResetToken(token); + final User user = passToken.getUser(); + if (passToken == null || user.getId() != id) { + final String message = messages.getMessage("auth.message.invalidToken", null, locale); + model.addAttribute("message", message); + return "redirect:/login.html?lang=" + locale.getLanguage(); + } + + final Calendar cal = Calendar.getInstance(); + if ((passToken.getExpiryDate().getTime() - cal.getTime().getTime()) <= 0) { + model.addAttribute("message", messages.getMessage("auth.message.expired", null, locale)); + return "redirect:/login.html?lang=" + locale.getLanguage(); + } + + final Authentication auth = new UsernamePasswordAuthenticationToken(user, null, userDetailsService.loadUserByUsername(user.getEmail()).getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(auth); + + return "redirect:/updatePassword.html?lang=" + locale.getLanguage(); + } + + @RequestMapping(value = "/user/savePassword", method = RequestMethod.POST) + @PreAuthorize("hasRole('READ_PRIVILEGE')") + @ResponseBody + public GenericResponse savePassword(final Locale locale, @RequestParam("password") final String password) { + final User user = (User) SecurityContextHolder.getContext().getAuthentication().getPrincipal(); + userService.changeUserPassword(user, password); + return new GenericResponse(messages.getMessage("message.resetPasswordSuc", null, locale)); + } + + // NON-API + + private final SimpleMailMessage constructResendVerificationTokenEmail(final String contextPath, final Locale locale, final VerificationToken newToken, final User user) { + final String confirmationUrl = contextPath + "/regitrationConfirm.html?token=" + newToken.getToken(); + final String message = messages.getMessage("message.resendToken", null, locale); + final SimpleMailMessage email = new SimpleMailMessage(); + email.setSubject("Resend Registration Token"); + email.setText(message + " \r\n" + confirmationUrl); + email.setTo(user.getEmail()); + email.setFrom(env.getProperty("support.email")); + return email; + } + + private final SimpleMailMessage constructResetTokenEmail(final String contextPath, final Locale locale, final String token, final User user) { + final String url = contextPath + "/user/changePassword?id=" + user.getId() + "&token=" + token; + final String message = messages.getMessage("message.resetPassword", null, locale); + final SimpleMailMessage email = new SimpleMailMessage(); + email.setTo(user.getEmail()); + email.setSubject("Reset Password"); + email.setText(message + " \r\n" + url); + email.setFrom(env.getProperty("support.email")); + return email; + } + + private User createUserAccount(final UserDto accountDto) { + User registered = null; + try { + registered = userService.registerNewUserAccount(accountDto); + } catch (final EmailExistsException e) { + return null; + } + return registered; + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java new file mode 100644 index 0000000000..3585cbc932 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/RestResponseEntityExceptionHandler.java @@ -0,0 +1,48 @@ +package org.baeldung.web.error; + +import org.baeldung.web.util.GenericResponse; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.MessageSource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.mail.MailAuthenticationException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; +import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler; + +@ControllerAdvice +public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler { + + @Autowired + private MessageSource messages; + + public RestResponseEntityExceptionHandler() { + super(); + } + + // 404 + @ExceptionHandler({ UserNotFoundException.class }) + public ResponseEntity handleUserNotFound(final RuntimeException ex, final WebRequest request) { + logger.error("404 Status Code", ex); + final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.userNotFound", null, request.getLocale()), "UserNotFound"); + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.NOT_FOUND, request); + } + + // 500 + @ExceptionHandler({ MailAuthenticationException.class }) + public ResponseEntity handleMail(final RuntimeException ex, final WebRequest request) { + logger.error("500 Status Code", ex); + final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.email.config.error", null, request.getLocale()), "MailError"); + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + + @ExceptionHandler({ Exception.class }) + public ResponseEntity handleInternal(final RuntimeException ex, final WebRequest request) { + logger.error("500 Status Code", ex); + final GenericResponse bodyOfResponse = new GenericResponse(messages.getMessage("message.error", null, request.getLocale()), "InternalError"); + return handleExceptionInternal(ex, bodyOfResponse, new HttpHeaders(), HttpStatus.BAD_REQUEST, request); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/UserNotFoundException.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/UserNotFoundException.java new file mode 100644 index 0000000000..4f45e0f978 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/error/UserNotFoundException.java @@ -0,0 +1,23 @@ +package org.baeldung.web.error; + +public final class UserNotFoundException extends RuntimeException { + + private static final long serialVersionUID = 5861310537366287163L; + + public UserNotFoundException() { + super(); + } + + public UserNotFoundException(final String message, final Throwable cause) { + super(message, cause); + } + + public UserNotFoundException(final String message) { + super(message); + } + + public UserNotFoundException(final Throwable cause) { + super(cause); + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/util/GenericResponse.java b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/util/GenericResponse.java new file mode 100644 index 0000000000..076c481580 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/java/org/baeldung/web/util/GenericResponse.java @@ -0,0 +1,54 @@ +package org.baeldung.web.util; + +import java.util.List; + +import org.springframework.validation.FieldError; +import org.springframework.validation.ObjectError; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public class GenericResponse { + private String message; + private String error; + + public GenericResponse(final String message) { + super(); + this.message = message; + } + + public GenericResponse(final String message, final String error) { + super(); + this.message = message; + this.error = error; + } + + public GenericResponse(final List fieldErrors, final List globalErrors) { + super(); + final ObjectMapper mapper = new ObjectMapper(); + try { + this.message = mapper.writeValueAsString(fieldErrors); + this.error = mapper.writeValueAsString(globalErrors); + } catch (final JsonProcessingException e) { + this.message = ""; + this.error = ""; + } + } + + public String getMessage() { + return message; + } + + public void setMessage(final String message) { + this.message = message; + } + + public String getError() { + return error; + } + + public void setError(final String error) { + this.error = error; + } + +} diff --git a/spring-security-login-and-registration-frontend/src/main/resources/.gitignore b/spring-security-login-and-registration-frontend/src/main/resources/.gitignore new file mode 100644 index 0000000000..ec4a72ea93 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/.gitignore @@ -0,0 +1 @@ +email.properties \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/resources/email.properties.sample b/spring-security-login-and-registration-frontend/src/main/resources/email.properties.sample new file mode 100644 index 0000000000..8e8207d7ab --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/email.properties.sample @@ -0,0 +1,7 @@ +################### JavaMail Configuration ########################## +smtp.host=email-smtp.us-east-1.amazonaws.com +smtp.port=465 +smtp.protocol=smtps +smtp.username=AKIAJIKXZAQFFJDXI4VQ +smtp.password= +support.email=eugen@baeldung.com diff --git a/spring-security-login-and-registration-frontend/src/main/resources/logback.xml b/spring-security-login-and-registration-frontend/src/main/resources/logback.xml new file mode 100644 index 0000000000..1146dade63 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/logback.xml @@ -0,0 +1,20 @@ + + + + + web - %date [%thread] %-5level %logger{36} - %message%n + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/resources/messages_en.properties b/spring-security-login-and-registration-frontend/src/main/resources/messages_en.properties new file mode 100644 index 0000000000..f3ad8d2307 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/messages_en.properties @@ -0,0 +1,67 @@ +message.username=Username required +message.password=Password required +message.unauth=Unauthorized Access !! +message.badCredentials=Invalid Username or Password +message.sessionExpired=Session Timed Out +message.logoutError=Sorry, error logging out +message.logoutSucc=You logged out successfully +message.regSucc=You registered successfully. We will send you a confirmation message to your email account. +message.regError=An account for that username/email already exists. Please enter a different username. +message.lastName=Last name is required +message.firstName=First name required +message.badEmail=Invalid email address +message.email.config.error=Error in java mail configuration +token.message=Your token is: +auth.message.disabled=Your account is disabled please check your mail and click on the confirmation link +auth.message.expired=Your registration token has expired. Please register again. +auth.message.invalidUser=This username is invalid, or does not exist. +auth.message.invalidToken=Invalid account confirmation token. +label.user.email=Email: +label.user.firstName=First name: +label.user.lastName=Last name: +label.user.password=Password: +label.user.confirmPass=Confirm password +label.form.submit=Submit +label.form.title=Registration Form +label.form.loginLink=Back to login +label.login=Login here +label.form.loginTitle=Login +label.form.loginEmail=Email +label.form.loginPass=Password +label.form.loginEnglish=English +label.form.loginSpanish=Spanish +label.form.loginSignUp=Sign up +label.pages.logout=Logout +label.pages.admin=Administrator +label.pages.home.title=Home +label.pages.home.message=Welcome Home +label.pages.admin.message=Welcome Admin +label.pages.user.message=Welcome User +label.successRegister.title=Registration Success +label.badUser.title=Invalid Link +ValidEmail.user.email=Invalid email address! +UniqueUsername.user.username=An account with that username/email already exists +NotNull.user.firstName=First name required +NotEmpty.user.firstName=First name required +NotNull.user.lastName=Last name required +NotEmpty.user.lastName=Last name required +NotNull.user.username=Username(Email) required +NotEmpty.user.username=Username(Email) required +NotNull.user.password=Password required +NotEmpty.user.password=Password required +NotNull.user.matchingPassword=Required +NotEmpty.user.matchingPassword=Required +PasswordMatches.user:Password does not match! +Email.user.email=Invalid Username (Email) +label.form.resendRegistrationToken=Re-send Token +message.resendToken=We will send an email with a new registration token to your email account +message.forgetPassword=Forget Password +message.resetPassword=Reset Password +message.updatePassword=Update Password +message.userNotFound=User Not Found +auth.message.blocked=This ip is blocked for 24 hours +message.accountVerified=Your account verified successfully +message.resetPasswordSuc=Password reset successfully +message.resetYourPassword=Reset your password +message.resetPasswordEmail=You should receive an Password Reset Email shortly +message.error=Error Occurred \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/resources/messages_es_ES.properties b/spring-security-login-and-registration-frontend/src/main/resources/messages_es_ES.properties new file mode 100644 index 0000000000..0830f94336 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/messages_es_ES.properties @@ -0,0 +1,67 @@ +message.username=Por favor ingrese el nombre de usuario +message.password=Por favor ingrese una clave +message.unauth=Acceso denegado !! +message.badCredentials=Usuario o clave invalida +message.sessionExpired=La sesion expiro +message.logoutError=Lo sentimos, hubo problemas al salir +message.logoutSucc=Salida con exito +message.regSucc=Se registro correctamente. Le enviaremos un mensaje de confirmacion a su direccion de email. +message.regError=Ya existe una cuenta con ese nombre de usuario. Ingrese un nombre de usuario diferente. +message.lastName=Por favor ingrese su apellido +message.firstName=Por favor ingrese su nombre +message.badEmail=Direccion de correo no es valida +message.email.config.error=Error en configuracion de java mail +token.message=Su token es: +auth.message.disabled=Su cuenta no esta habilitada. Hemos enviado a su correo un link para habilitar su cuenta. +auth.message.expired=Su ficha de registro ha caducado, por favor registrese de nuevo. +auth.message.invalidUser=Este nombre de usuario es invalido o no existe. +auth.message.invalidToken=Codigo de confirmacion incorrecto. +label.user.email=Correo Electronico: +label.user.firstName=Nombre: +label.user.lastName=Apellido: +label.user.password=Contrasenia: +label.user.confirmPass=Confirme la contrasenia +label.form.submit=Enviar +label.form.title=Formulario de Registro +label.login=Autehtifiquese aqui +label.form.loginTitle=Ingreso +label.form.loginLink=Regrese a autentificacion +label.form.loginEmail=Correo Electronico +label.form.loginPass=Contrasenia +label.form.loginEnglish=Ingles +label.form.loginSpanish=Espaniol +label.form.loginSignUp=Registrese +label.pages.logout=Salir +label.pages.admin=Administrador +label.pages.home.title=Inicio +label.pages.home.message=Bienveni@ a Casa +label.pages.admin.message=Bienvenid@ Admin +label.pages.user.message=Bienvenid@ Usuari@ +label.successRegister.title=Registro Exitoso +label.badUser.title=Enlace Invalido +ValidEmail.user.email=Cuenta correo invlida! +UniqueUsername.user.username=Ya existe una cuenta con ese nombre de usuario +NotNull.user.firstName=Por favor ingrese su nombre +NotEmpty.user.firstName=Por favor ingrese su nombre +NotNull.user.lastName=Por favor ingrese su apellido +NotEmpty.user.lastName=Por favor ingrese su apellido +NotNull.user.username=Por favor ingrese su cuenta de email +NotEmpty.user.username=Por favor ingrese su cuenta de email +NotNull.user.password=Por favor ingrese su clave +NotEmpty.user.password=Por favor ingrese su contraseña +NotNull.user.matchingPassword=Campo obligatirio +NotEmpty.user.matchingPassword=Campo obligatrio +PasswordMatches.user:Las claves no coinciden! +Email.user.email=Email no es valido +label.form.resendRegistrationToken=Reenviar mensaje de emergencia +message.resendToken=Te enviaremos un correo electrónico con un nuevo token de registro en su cuenta de correo electrónico +message.forgetPassword=Olvide la contraseña +message.resetPassword=Restablecer contraseña +message.updatePassword=Actualizar contraseña +message.userNotFound=Usuario no encontrado +auth.message.blocked=Esta IP se bloquea durante 24 horas +message.accountVerified=Su cuenta verificada con éxito +message.resetPasswordSuc=Contraseña reajusta correctamente +message.resetYourPassword=Restablecer su contraseña +message.resetPasswordEmail=Te enviaremos un correo electrónico para restablecer su contraseña +message.error=Se produjo un error \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/resources/persistence.properties b/spring-security-login-and-registration-frontend/src/main/resources/persistence.properties new file mode 100644 index 0000000000..cd282b147b --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/persistence.properties @@ -0,0 +1,10 @@ +################### DataSource Configuration ########################## +jdbc.driverClassName=com.mysql.jdbc.Driver +jdbc.url=jdbc:mysql://localhost:3606/registration_02?createDatabaseIfNotExist=true +jdbc.user=tutorialuser +jdbc.pass=tutorialmy5ql +init-db=false +################### Hibernate Configuration ########################## +hibernate.dialect=org.hibernate.dialect.MySQLDialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop diff --git a/spring-security-login-and-registration-frontend/src/main/resources/webSecurityConfig.xml b/spring-security-login-and-registration-frontend/src/main/resources/webSecurityConfig.xml new file mode 100644 index 0000000000..b929f1ffa9 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/resources/webSecurityConfig.xml @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/META-INF/MANIFEST.MF b/spring-security-login-and-registration-frontend/src/main/webapp/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..5e9495128c --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Class-Path: + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/mvc-servlet.xml b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/mvc-servlet.xml new file mode 100644 index 0000000000..7862ca24c0 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/mvc-servlet.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/admin.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/admin.jsp new file mode 100644 index 0000000000..d94c80bd25 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/admin.jsp @@ -0,0 +1,34 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + + +<spring:message code="label.pages.home.title"></spring:message> + + + + +
+ + + + +

+ +

+
+
+ + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/badUser.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/badUser.jsp new file mode 100644 index 0000000000..6d15b87d88 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/badUser.jsp @@ -0,0 +1,54 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> + +<%@ page session="true"%> + + + + <spring:message +code="label.badUser.title"></spring:message> + + +
+

+ ${param.message} +

+
+"> + + +
+

${label.form.resendRegistrationToken}

+ + + + +
+
+ + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/console.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/console.jsp new file mode 100644 index 0000000000..b993fc4a94 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/console.jsp @@ -0,0 +1,36 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + + + + + +
+

This is the landing page for the admin

+ + This text is only visible to a user +
+
+ + This text is only visible to an admin +
+
+ + "> +
+ + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/emailError.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/emailError.jsp new file mode 100644 index 0000000000..ea3b5fac88 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/emailError.jsp @@ -0,0 +1,17 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + +<spring:message code="label.pages.home.title"></spring:message> + + +
+

+ +

+ +
+ + + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/expiredAccount.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/expiredAccount.jsp new file mode 100644 index 0000000000..8f00b64acc --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/expiredAccount.jsp @@ -0,0 +1,24 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> + +<%@ page session="true"%> + + + + + <spring:message code="label.pages.home.title"></spring:message> + + +
+

+ +

+
+"> +
+ + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/forgetPassword.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/forgetPassword.jsp new file mode 100644 index 0000000000..450edc1d10 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/forgetPassword.jsp @@ -0,0 +1,56 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@ page session="false"%> + + + + +<spring:message code="message.resetPassword"></spring:message> + + +
+

+
+
+ + + +
+ +
+"> +

+"> + +
+ + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/home.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/home.jsp new file mode 100644 index 0000000000..7ef1fb60ec --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/home.jsp @@ -0,0 +1,28 @@ +<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c"%> +<%@ page session="true"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + + +<spring:message code="label.pages.home.title"></spring:message> + + + +
+

+ +

+
+ + + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/homepage.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/homepage.jsp new file mode 100644 index 0000000000..327606745b --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/homepage.jsp @@ -0,0 +1,38 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ page session="true"%> + + + +<spring:message code="label.pages.home.title"></spring:message> + + + + +
+ + + +
+
+ + + +
+
+ ${param.user} + "> +
+ + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/invalidSession.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/invalidSession.jsp new file mode 100644 index 0000000000..107e9d3032 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/invalidSession.jsp @@ -0,0 +1,18 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + +<spring:message code="label.pages.home.title"></spring:message> + + +
+

+ +

+ "> +
+ + + diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/login.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/login.jsp new file mode 100644 index 0000000000..6767de5c5e --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/login.jsp @@ -0,0 +1,109 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> + +<%@ page session="true"%> + + + + + +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+ + +
+
+
+
+ + + + +<spring:message code="label.pages.home.title"></spring:message> + + + + + +
+${param.message} +
+
+ +
+
+

+ +

+ + | +

+ + + + + +

+ + + +

+ /> + + +
Current Locale : ${pageContext.response.locale}

+ "> +

+ "> +
+
+ + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/logout.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/logout.jsp new file mode 100644 index 0000000000..9862ef4c78 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/logout.jsp @@ -0,0 +1,31 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> + + + + + +

+ +

+
+ +<spring:message code="label.pages.home.title"></spring:message> + + + +
+ + +

+ +

+
+ "> +
+ + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/registration.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/registration.jsp new file mode 100644 index 0000000000..49666d7fa3 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/registration.jsp @@ -0,0 +1,94 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ page session="false"%> + + + + +<spring:message code="label.form.title"></spring:message> + + +
+
+

+ +

+
+
+ + + + +
+
+ + + + +
+
+ + + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ "> +
+
+ + + + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp new file mode 100644 index 0000000000..c2bda675ec --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/regitrationConfirm.jsp @@ -0,0 +1,23 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> + +<%@ page session="true"%> + + + + + + + +<spring:message code="label.pages.home.title"></spring:message> + + +
+

+ "> +
+ + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/successRegister.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/successRegister.jsp new file mode 100644 index 0000000000..4982da1621 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/successRegister.jsp @@ -0,0 +1,25 @@ +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@taglib uri="http://www.springframework.org/tags" prefix="spring"%> +<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt"%> + +<%@ page session="true"%> + + + + +" rel="stylesheet"> + +<spring:message code="label.pages.home.title"></spring:message> + + +
+

+ +

+ "> +
+ + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/updatePassword.jsp b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/updatePassword.jsp new file mode 100644 index 0000000000..859c0a9be4 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/view/updatePassword.jsp @@ -0,0 +1,60 @@ + +<%@ page contentType="text/html;charset=UTF-8" language="java"%> +<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> +<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form"%> +<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%> +<%@ taglib prefix="sec" + uri="http://www.springframework.org/security/tags"%> +<%@ page session="false"%> + + + + +<spring:message code="message.updatePassword"></spring:message> + + + +
+
+

+
+
+ + + + +

+ + + + +

+ +
+ +
+
+ + + +
+ + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/web.xml b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/web.xml new file mode 100644 index 0000000000..ed3d1b3ce7 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/main/webapp/WEB-INF/web.xml @@ -0,0 +1,51 @@ + + + + + contextClass + org.springframework.web.context.support.AnnotationConfigWebApplicationContext + + + contextConfigLocation + org.baeldung.spring + + + + org.springframework.web.context.ContextLoaderListener + + + + org.springframework.web.context.request.RequestContextListener + + + + mvc + org.springframework.web.servlet.DispatcherServlet + 1 + + + mvc + / + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + springSecurityFilterChain + /* + + + localizationFilter + org.springframework.web.filter.RequestContextFilter + + + localizationFilter + /* + + + \ No newline at end of file diff --git a/spring-security-login-and-registration-frontend/src/test/java/org/baeldung/test/SpringSecurityRolesTest.java b/spring-security-login-and-registration-frontend/src/test/java/org/baeldung/test/SpringSecurityRolesTest.java new file mode 100644 index 0000000000..77a67d17d7 --- /dev/null +++ b/spring-security-login-and-registration-frontend/src/test/java/org/baeldung/test/SpringSecurityRolesTest.java @@ -0,0 +1,121 @@ +package org.baeldung.test; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; + +import java.util.ArrayList; +import java.util.Arrays; + +import org.baeldung.persistence.dao.PrivilegeRepository; +import org.baeldung.persistence.dao.RoleRepository; +import org.baeldung.persistence.dao.UserRepository; +import org.baeldung.persistence.model.Privilege; +import org.baeldung.persistence.model.Role; +import org.baeldung.persistence.model.User; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TransactionConfiguration; +import org.springframework.transaction.annotation.Transactional; + +@RunWith(SpringJUnit4ClassRunner.class) +@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class) +@Transactional +@TransactionConfiguration +public class SpringSecurityRolesTest { + + @Autowired + private UserRepository userRepository; + + @Autowired + private RoleRepository roleRepository; + + @Autowired + private PrivilegeRepository privilegeRepository; + + @Autowired + private PasswordEncoder passwordEncoder; + + private User user; + private Role role; + private Privilege privilege; + + // tests + + @Test + public void testDeleteUser() { + role = new Role("TEST_ROLE"); + roleRepository.save(role); + + user = new User(); + user.setFirstName("John"); + user.setLastName("Doe"); + user.setPassword(passwordEncoder.encode("123")); + user.setEmail("john@doe.com"); + user.setRoles(Arrays.asList(role)); + user.setEnabled(true); + userRepository.save(user); + + assertNotNull(userRepository.findByEmail(user.getEmail())); + assertNotNull(roleRepository.findByName(role.getName())); + user.setRoles(null); + userRepository.delete(user); + + assertNull(userRepository.findByEmail(user.getEmail())); + assertNotNull(roleRepository.findByName(role.getName())); + } + + @Test + public void testDeleteRole() { + privilege = new Privilege("TEST_PRIVILEGE"); + privilegeRepository.save(privilege); + + role = new Role("TEST_ROLE"); + role.setPrivileges(Arrays.asList(privilege)); + roleRepository.save(role); + + user = new User(); + user.setFirstName("John"); + user.setLastName("Doe"); + user.setPassword(passwordEncoder.encode("123")); + user.setEmail("john@doe.com"); + user.setRoles(Arrays.asList(role)); + user.setEnabled(true); + userRepository.save(user); + + assertNotNull(privilegeRepository.findByName(privilege.getName())); + assertNotNull(userRepository.findByEmail(user.getEmail())); + assertNotNull(roleRepository.findByName(role.getName())); + + user.setRoles(new ArrayList()); + role.setPrivileges(new ArrayList()); + roleRepository.delete(role); + + assertNull(roleRepository.findByName(role.getName())); + assertNotNull(privilegeRepository.findByName(privilege.getName())); + assertNotNull(userRepository.findByEmail(user.getEmail())); + } + + @Test + public void testDeletePrivilege() { + privilege = new Privilege("TEST_PRIVILEGE"); + privilegeRepository.save(privilege); + + role = new Role("TEST_ROLE"); + role.setPrivileges(Arrays.asList(privilege)); + roleRepository.save(role); + + assertNotNull(roleRepository.findByName(role.getName())); + assertNotNull(privilegeRepository.findByName(privilege.getName())); + + role.setPrivileges(new ArrayList()); + privilegeRepository.delete(privilege); + + assertNull(privilegeRepository.findByName(privilege.getName())); + assertNotNull(roleRepository.findByName(role.getName())); + } +}