This commit is contained in:
		| @@ -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; | ||||
| 	} | ||||
|  | ||||
| } | ||||
| @@ -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"; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -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<Record1<String>> 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); | ||||
| 	} | ||||
| } | ||||
| @@ -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()); | ||||
| 	} | ||||
| } | ||||
| @@ -395,4 +395,10 @@ div { | ||||
| 	padding: 6px; | ||||
| 	border-radius: 8px; | ||||
| 	border: 1px solid gray; | ||||
| } | ||||
|  | ||||
| .block660 { | ||||
| 	max-width: 660px; | ||||
| 	margin-left: auto; | ||||
| 	margin-right: auto; | ||||
| } | ||||
| @@ -16,10 +16,14 @@ | ||||
| 	</th:block> | ||||
| 	<th:block layout:fragment="content"> | ||||
| 		<div class="mainpage"> | ||||
| 		  <div class="alert alert-warning alert-dismissible fade show block660" role="alert"> | ||||
| 		  	<span>alte Zugangsdaten ins neue System </span><a th:href="@{/migration/login}">umziehen</a> | ||||
| 		  	<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Schließen"></button> | ||||
| 		  </div> | ||||
| 			<script type="text/javascript"> | ||||
| 				var mytoggle = new MyToggle(); | ||||
| 			</script> | ||||
| 			<div class="card bottomdist16" style="max-width: 660px; margin-left: auto; margin-right: auto; background: transparent" th:each="c : ${camps}"> | ||||
| 			<div class="card bottomdist16 block660" style="background: transparent" th:each="c : ${camps}"> | ||||
| 				<div class="card-header mytoggle_btn" style="background: transparent" th:onclick="mytoggle.toggle('campdiv_[[${c.pk}]]')"> | ||||
| 					<div style="margin-left: auto; margin-right: auto;"> | ||||
| 						<span th:text="${c.name}" class="headlinefont"></span><span class="headlinefont"> </span><span th:text="${#numbers.formatInteger(c.year, 0)}" class="headlinefont" | ||||
|   | ||||
							
								
								
									
										60
									
								
								src/main/resources/templates/migration/login.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								src/main/resources/templates/migration/login.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| <!DOCTYPE html> | ||||
| <html xmlns:th="http://www.thymeleaf.org" layout:decorate="~{template}" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" xmlns:sec="http://www.thymeleaf.org/extras/spring-security"> | ||||
| <head> | ||||
| <title>Camp Organizer 2</title> | ||||
| <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||||
| </head> | ||||
| <body> | ||||
| 	<th:block layout:fragment="header"> | ||||
| 		Umziehen der Zugangsdaten aus dem alten Anmeldeportal | ||||
| 	</th:block> | ||||
| 	<th:block layout:fragment="content"> | ||||
| 		<div class="mainpage"> | ||||
| 			<div class="alert alert-success alert-dismissible fade show block660" role="alert"> | ||||
| 			  Mit dem Umzug in das neue Anmeldeportal ist es leider notwendig, dass du dir ein neues Login anlegst. | ||||
| 			  Damit das für dich leichter geht, haben wir ein Migrationswerkzeug entwickelt, mit dem du deinen alten Zugang übertragen kannst.<br /> | ||||
| 			  <br /> | ||||
| 			  Wichtig dabei ist, dass du beim Anlegen des neuen Zugangs eine gültige E-Mail-Adresse verwendest. Die wird im neuen System benötigt, | ||||
| 			  falls du dein Passwort vergessen hast. Damit eine sinnvolle Zuordnung möglich ist, gib bitte ebenfalls Vor- und Nachname an.<br /> | ||||
| 			  <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Schließen"></button> | ||||
| 			</div> | ||||
| 			<div class="block660"> | ||||
| 				<div class="card centered-card" style="max-width: 48rem"> | ||||
| 				<div class="card-body"> | ||||
| 					<form th:action="@{/migration/loginold}" th:object="${bean}" method="post"> | ||||
| 						<div class="container"> | ||||
| 							<div class="row"> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('username')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="username" th:field="*{username}" th:class="${'form-control ' + (#fields.hasErrors('username') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('password')}">[[${error}]]<br /></span> | ||||
| 									<input type="password" placeholder="Passwort" th:field="*{password}" th:class="${'form-control ' + (#fields.hasErrors('password') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('forename')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="Vorname" th:field="*{forename}" th:class="${'form-control ' + (#fields.hasErrors('forename') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('surname')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="Nachname" th:field="*{surname}" th:class="${'form-control ' + (#fields.hasErrors('surname') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 								<div class="col-sm-12 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('email')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="E-Mail" th:field="*{email}" th:class="${'form-control ' + (#fields.hasErrors('email') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 							<div class="row"> | ||||
| 								<div class="col-sm-12 rowdist centered"> | ||||
| 									<input type="submit" class="btn btn-linda buttonfont" value="jetzt umziehen" /> | ||||
| 								</div> | ||||
| 							</div> | ||||
| 						</div> | ||||
| 					</form> | ||||
| 				</div> | ||||
| 			</div> | ||||
| 		</div> | ||||
| 	</th:block> | ||||
| </body> | ||||
| </html> | ||||
| @@ -22,11 +22,11 @@ | ||||
| 						<div class="container"> | ||||
| 							<div class="row"> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('surname')}">[[${error}]]<br /></span> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('forename')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="Vorname" th:field="*{forename}" th:class="${'form-control ' + (#fields.hasErrors('forename') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 								<div class="col-sm-6 rowdist"> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('forename')}">[[${error}]]<br /></span> | ||||
| 									<span class="error"	th:each="error : ${#fields.errors('surname')}">[[${error}]]<br /></span> | ||||
| 									<input type="text" placeholder="Nachname" th:field="*{surname}" th:class="${'form-control ' + (#fields.hasErrors('surname') ? 'inputerror' : '')}" /> | ||||
| 								</div> | ||||
| 							</div> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user