From f415d99e9e2a57bb8794f97ec7b95594fbe70eb9 Mon Sep 17 00:00:00 2001 From: Jottyfan Date: Sun, 12 Mar 2023 23:53:34 +0100 Subject: [PATCH] https://gitlab.com/jottyfan/camporganizer2/-/issues/41 --- build.gradle | 5 +- .../module/migration/MigrationBean.java | 118 ++++++++++++++++++ .../module/migration/MigrationController.java | 48 +++++++ .../module/migration/MigrationRepository.java | 43 +++++++ .../module/migration/MigrationService.java | 44 +++++++ src/main/resources/static/css/style.css | 6 + src/main/resources/templates/camplist.html | 6 +- .../resources/templates/migration/login.html | 60 +++++++++ .../templates/registration/registration.html | 4 +- 9 files changed, 330 insertions(+), 4 deletions(-) create mode 100644 src/main/java/de/jottyfan/camporganizer/module/migration/MigrationBean.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/migration/MigrationController.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/migration/MigrationRepository.java create mode 100644 src/main/java/de/jottyfan/camporganizer/module/migration/MigrationService.java create mode 100644 src/main/resources/templates/migration/login.html diff --git a/build.gradle b/build.gradle index 6a3ede4..b5f07b7 100644 --- a/build.gradle +++ b/build.gradle @@ -18,7 +18,7 @@ apply plugin: 'war' apply plugin: 'application' group = 'de.jottyfan.camporganizer' -version = '0.3.3' +version = '0.3.4' sourceCompatibility = 17 mainClassName = "de.jottyfan.camporganizer.Main" @@ -56,6 +56,9 @@ dependencies { implementation 'org.keycloak:keycloak-spring-boot-starter' + // old login algorithm; can be removed when all accounts have moved + implementation 'org.jasypt:jasypt:1.9.3' + // for using the keycloak rest interface implementation 'org.keycloak:keycloak-admin-client:20.0.1' implementation 'org.jboss.resteasy:resteasy-client:5.0.0.Final' diff --git a/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationBean.java b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationBean.java new file mode 100644 index 0000000..dc3f4a6 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationBean.java @@ -0,0 +1,118 @@ +package de.jottyfan.camporganizer.module.migration; + +import java.io.Serializable; + +import javax.validation.constraints.Email; +import javax.validation.constraints.NotBlank; + +import org.jasypt.exceptions.EncryptionOperationNotPossibleException; +import org.jasypt.util.password.StrongPasswordEncryptor; + +import de.jottyfan.camporganizer.module.registration.validate.UnusedUsername; + +/** + * + * @author jotty + * + */ +@UnusedUsername(field = "email", message = "Diese E-Mail ist als Login leider bereits vergeben. Bitte wähle eine andere.") +public class MigrationBean implements Serializable { + private static final long serialVersionUID = 1L; + + @NotBlank(message = "Bitte gib deinen Vornamen an.") + private String forename; + @NotBlank(message = "Bitte gib deinen Nachnamen an.") + private String surname; + @NotBlank(message = "Bitte gib deinen alten Nutzernamen an.") + private String username; + @NotBlank(message = "Bitte gib dein altes Passwort an.") + private String password; + @NotBlank(message = "Bitte gib eine E-Mail-Adresse an. Ohne kannst du deinen Zugang nicht umziehen.") + @Email(message = "Bitte gib eine gültige E-Mail-Adresse an.") + private String email; + + /** + * check if the current password fits to the encrypted one + * + * @param encryptedPassword the encrypted password from the database + * @return true or false + */ + public boolean checkPassword(String encryptedPassword) { + try { + return new StrongPasswordEncryptor().checkPassword(password, encryptedPassword); + } catch (EncryptionOperationNotPossibleException e) { + return false; // password is not decryptable + } + } + + /** + * @return the username + */ + public String getUsername() { + return username; + } + + /** + * @param username the username to set + */ + public void setUsername(String username) { + this.username = username; + } + + /** + * @return the password + */ + public String getPassword() { + return password; + } + + /** + * @param password the password to set + */ + public void setPassword(String password) { + this.password = password; + } + + /** + * @return the email + */ + public String getEmail() { + return email; + } + + /** + * @param email the email to set + */ + public void setEmail(String email) { + this.email = email; + } + + /** + * @return the forename + */ + public String getForename() { + return forename; + } + + /** + * @param forename the forename to set + */ + public void setForename(String forename) { + this.forename = forename; + } + + /** + * @return the surname + */ + public String getSurname() { + return surname; + } + + /** + * @param surname the surname to set + */ + public void setSurname(String surname) { + this.surname = surname; + } + +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationController.java b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationController.java new file mode 100644 index 0000000..73b226b --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationController.java @@ -0,0 +1,48 @@ +package de.jottyfan.camporganizer.module.migration; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.validation.BindingResult; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PostMapping; + +/** + * + * @author jotty + * + */ +@Controller +public class MigrationController { + + @Autowired + private MigrationService service; + + /** + * to the login page + * + * @return + */ + @GetMapping("/migration/login") + public String getLogin(Model model) { + model.addAttribute("bean", new MigrationBean()); + return "/migration/login"; + } + + @PostMapping("/migration/loginold") + public String loginOld(@Valid @ModelAttribute("bean") MigrationBean bean, final BindingResult bindingResult, Model model) { + if (bindingResult.hasErrors()) { + return "/migration/login"; + } else if (service.checkLogin(bean)) { + service.migrate(bean); + return "redirect:/dashboard"; + } else { + bindingResult.addError(new FieldError("password", "password", "Dein Passwort scheint falsch zu sein, oder den Benutzer gibt es nicht.")); + return "/migration/login"; + } + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationRepository.java b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationRepository.java new file mode 100644 index 0000000..6b4693d --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationRepository.java @@ -0,0 +1,43 @@ +package de.jottyfan.camporganizer.module.migration; + +import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.jooq.DSLContext; +import org.jooq.Record1; +import org.jooq.SelectConditionStep; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +/** + * + * @author jotty + * + */ +@Repository +@Transactional(transactionManager = "transactionManager") +public class MigrationRepository { + private static final Logger LOGGER = LogManager.getLogger(MigrationRepository.class); + + @Autowired + private DSLContext jooq; + + /** + * get the encrypted password of username + * + * @param username the username + * @return the encrypted password or null + */ + public String getEncryptedPassword(String username) { + SelectConditionStep> sql = jooq + // @formatter:off + .select(T_PROFILE.PASSWORD) + .from(T_PROFILE) + .where(T_PROFILE.USERNAME.eq(username)); + // @formatter:on + LOGGER.debug(sql.toString()); + return sql.fetchOne(T_PROFILE.PASSWORD); + } +} diff --git a/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationService.java b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationService.java new file mode 100644 index 0000000..866eb38 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/migration/MigrationService.java @@ -0,0 +1,44 @@ +package de.jottyfan.camporganizer.module.migration; + +import javax.validation.Valid; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import de.jottyfan.camporganizer.module.registration.KeycloakRepository; + +/** + * + * @author jotty + * + */ +@Service +public class MigrationService { + + @Autowired + private MigrationRepository repository; + + @Autowired + private KeycloakRepository keycloak; + + /** + * check if the login is valid + * + * @param bean the bean + * @return true or false + */ + public boolean checkLogin(@Valid MigrationBean bean) { + String encryptedPassword = repository.getEncryptedPassword(bean.getUsername()); + return bean.checkPassword(encryptedPassword); + } + + /** + * do the migration + * + * @param bean the bean + * @return true or false + */ + public boolean migrate(@Valid MigrationBean bean) { + return keycloak.register(bean.getForename(), bean.getSurname(), bean.getUsername(), bean.getPassword(), bean.getEmail()); + } +} diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index 01af74f..80ab00c 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -395,4 +395,10 @@ div { padding: 6px; border-radius: 8px; border: 1px solid gray; +} + +.block660 { + max-width: 660px; + margin-left: auto; + margin-right: auto; } \ No newline at end of file diff --git a/src/main/resources/templates/camplist.html b/src/main/resources/templates/camplist.html index b65c67b..0462050 100644 --- a/src/main/resources/templates/camplist.html +++ b/src/main/resources/templates/camplist.html @@ -16,10 +16,14 @@
+ -
+
  + + +Camp Organizer 2 + + + + + Umziehen der Zugangsdaten aus dem alten Anmeldeportal + + +
+ +
+
+
+
+
+
+
+ [[${error}]]
+ +
+
+ [[${error}]]
+ +
+
+ [[${error}]]
+ +
+
+ [[${error}]]
+ +
+
+ [[${error}]]
+ +
+
+
+
+ +
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/src/main/resources/templates/registration/registration.html b/src/main/resources/templates/registration/registration.html index 5a54080..caa2294 100644 --- a/src/main/resources/templates/registration/registration.html +++ b/src/main/resources/templates/registration/registration.html @@ -22,11 +22,11 @@
- [[${error}]]
+ [[${error}]]
- [[${error}]]
+ [[${error}]]