keycloak registration done
This commit is contained in:
@@ -25,19 +25,19 @@ import org.springframework.stereotype.Repository;
|
||||
public class KeycloakRepository {
|
||||
private final static Logger LOGGER = LogManager.getLogger(KeycloakRepository.class);
|
||||
|
||||
@Value("${keycloak.resource:biblecamp}")
|
||||
@Value("${keycloak.resource}")
|
||||
private String keycloakClientId;
|
||||
|
||||
@Value("${keycloak.auth-server-url}")
|
||||
private String keycloakUrl;
|
||||
|
||||
@Value("${keycloak.realm:ow}")
|
||||
@Value("${keycloak.realm}")
|
||||
private String keycloakRealm;
|
||||
|
||||
@Value("${ow.keycloak.admin.name:admin")
|
||||
@Value("${ow.keycloak.admin.name}")
|
||||
private String keycloakAdminName;
|
||||
|
||||
@Value("${ow.keycloak.admin.password:password")
|
||||
@Value("${ow.keycloak.admin.password}")
|
||||
private String keycloakAdminPassword;
|
||||
|
||||
/**
|
||||
@@ -54,28 +54,32 @@ public class KeycloakRepository {
|
||||
/**
|
||||
* register the login in keycloak
|
||||
*
|
||||
* @param forename the forename
|
||||
* @param surname the surname
|
||||
* @param login the username
|
||||
* @param password the password
|
||||
* @param email the email
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean register(String login, String password, String email) {
|
||||
UserRepresentation user = getUserRepresentation(login, password, email);
|
||||
UsersResource resource = getUsersResource(keycloakUrl, keycloakRealm, keycloakAdminName, keycloakAdminPassword, keycloakClientId);
|
||||
boolean result = register(resource, user);
|
||||
sendVerificationLink(login, resource);
|
||||
return result;
|
||||
public boolean register(String forename, String surname, String login, String password, String email) {
|
||||
UserRepresentation user = getUserRepresentation(forename, surname, login, password, email);
|
||||
UsersResource resource = getUsersResource(keycloakUrl, keycloakRealm, keycloakAdminName, keycloakAdminPassword,
|
||||
keycloakClientId);
|
||||
return register(resource, user);
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a user representation
|
||||
*
|
||||
* @param login the login
|
||||
* @param forename the forename
|
||||
* @param surname the surname
|
||||
* @param login the login
|
||||
* @param password the password
|
||||
* @param email the email
|
||||
* @param email the email
|
||||
* @return the user representation
|
||||
*/
|
||||
protected UserRepresentation getUserRepresentation(String login, String password, String email) {
|
||||
protected UserRepresentation getUserRepresentation(String forename, String surname, String login, String password,
|
||||
String email) {
|
||||
CredentialRepresentation passwordCredentials = new CredentialRepresentation();
|
||||
passwordCredentials.setTemporary(false);
|
||||
passwordCredentials.setType(CredentialRepresentation.PASSWORD);
|
||||
@@ -83,6 +87,8 @@ public class KeycloakRepository {
|
||||
|
||||
UserRepresentation user = new UserRepresentation();
|
||||
user.setUsername(login);
|
||||
user.setFirstName(forename);
|
||||
user.setLastName(surname);
|
||||
user.setEmail(email);
|
||||
user.setCredentials(Collections.singletonList(passwordCredentials));
|
||||
user.setEnabled(true);
|
||||
@@ -94,37 +100,42 @@ public class KeycloakRepository {
|
||||
* register a user in keycloak
|
||||
*
|
||||
* @param resource the resource
|
||||
* @param user the user
|
||||
* @param user the user
|
||||
* @return true or false
|
||||
*/
|
||||
protected boolean register(UsersResource resource, UserRepresentation user) {
|
||||
Response response = resource.create(user);
|
||||
LOGGER.info("created new keycloak user {}", user.getUsername());
|
||||
return Status.OK.equals(response.getStatusInfo());
|
||||
Boolean success = Status.CREATED.equals(response.getStatusInfo());
|
||||
if (success) {
|
||||
LOGGER.info("created new keycloak user {}", user.getUsername());
|
||||
} else {
|
||||
LOGGER.error("error on creating keycloak user {}: {}", user.getUsername(), response.getStatus());
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a keycloak object with the special arguments
|
||||
*
|
||||
* @param url the url
|
||||
* @param realm the realm
|
||||
* @param admin the admin of the realm
|
||||
* @param url the url
|
||||
* @param realm the realm
|
||||
* @param admin the admin of the realm
|
||||
* @param password the password
|
||||
* @param clientId the client ID
|
||||
* @return the keycloak object
|
||||
*/
|
||||
public KeycloakBuilder getKeycloak(String url, String realm, String admin, String password, String clientId) {
|
||||
return KeycloakBuilder.builder().serverUrl(url).realm(realm).grantType(OAuth2Constants.PASSWORD)
|
||||
.username(admin).password(password).clientId(clientId)
|
||||
return KeycloakBuilder.builder().serverUrl(url).realm(realm).grantType(OAuth2Constants.PASSWORD).username(admin)
|
||||
.password(password).clientId(clientId)
|
||||
.resteasyClient(new ResteasyClientBuilderImpl().connectionPoolSize(10).build());
|
||||
}
|
||||
|
||||
/**
|
||||
* generate a users resource object
|
||||
*
|
||||
* @param url the url
|
||||
* @param realm the realm
|
||||
* @param admin the admin of the realm
|
||||
* @param url the url
|
||||
* @param realm the realm
|
||||
* @param admin the admin of the realm
|
||||
* @param password the password
|
||||
* @param clientId the client ID
|
||||
* @return the users resource
|
||||
@@ -138,8 +149,9 @@ public class KeycloakRepository {
|
||||
*
|
||||
* @param userId the ID of the user
|
||||
*/
|
||||
public void sendVerificationLink(String userId, UsersResource usersResource) {
|
||||
usersResource.get(userId).sendVerifyEmail();
|
||||
public void sendVerificationLink(String userId) {
|
||||
getUsersResource(keycloakUrl, keycloakRealm, keycloakAdminName, keycloakAdminPassword, keycloakClientId).get(userId)
|
||||
.sendVerifyEmail();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -37,20 +37,32 @@ public class RegistrationController extends CommonController {
|
||||
bean.setFkCamp(fkCamp);
|
||||
bean.setRegisterInKeycloak(true); // we want people to register generally
|
||||
model.addAttribute("bean", bean);
|
||||
return "/registration";
|
||||
return "/registration/registration";
|
||||
}
|
||||
|
||||
@PostMapping("/registration/register")
|
||||
public String register(@Valid @ModelAttribute RegistrationBean bean, final BindingResult bindingResult, Model model) {
|
||||
public String register(@Valid @ModelAttribute("bean") RegistrationBean bean, final BindingResult bindingResult, Model model) {
|
||||
super.setupSession(model, request);
|
||||
if (bindingResult.hasErrors()) {
|
||||
super.setupSession(model, request);
|
||||
CampBean campBean = service.getCamp(bean.getFkCamp());
|
||||
model.addAttribute("camp", campBean);
|
||||
model.addAttribute("bean", bean);
|
||||
return "/registration";
|
||||
return "/registration/registration";
|
||||
}
|
||||
Boolean result = service.register(bean);
|
||||
// TODO: give the user a message about success or error and, if registered in keycloak, a note about how to login
|
||||
return index(bean.getFkCamp(), model);
|
||||
return result ? "/registration/success" : "/error";
|
||||
}
|
||||
|
||||
@GetMapping("/registration/cancel/{id}")
|
||||
public String cancellation(@PathVariable Integer id, final Model model) {
|
||||
super.setupSession(model, request);
|
||||
model.addAttribute("bean", service.getBooking(id));
|
||||
return "/registration/cancellation";
|
||||
}
|
||||
|
||||
@GetMapping("/registration/remove/{id}")
|
||||
public String remove(@PathVariable Integer id, final Model model) {
|
||||
super.setupSession(model, request);
|
||||
service.removeBooking(id);
|
||||
return "redirect:/dashboard";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package de.jottyfan.camporganizer.module.registration;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSONDOCUMENT;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
|
||||
|
||||
import java.time.LocalDate;
|
||||
@@ -13,9 +14,11 @@ import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jasypt.util.password.StrongPasswordEncryptor;
|
||||
import org.jooq.DSLContext;
|
||||
import org.jooq.DeleteConditionStep;
|
||||
import org.jooq.InsertResultStep;
|
||||
import org.jooq.InsertValuesStep12;
|
||||
import org.jooq.InsertValuesStep13;
|
||||
import org.jooq.Record7;
|
||||
import org.jooq.SelectConditionStep;
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.jooq.impl.DSL;
|
||||
@@ -27,7 +30,9 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersondocumentRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
|
||||
import de.jottyfan.camporganizer.module.common.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.common.LambdaResultWrapper;
|
||||
|
||||
/**
|
||||
@@ -163,4 +168,61 @@ public class RegistrationGateway {
|
||||
});
|
||||
return lrw.getCounter() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the booking from the database
|
||||
*
|
||||
* @param id the id of the booking
|
||||
* @return the booking bean or null
|
||||
*/
|
||||
public BookingBean getBooking(Integer id) {
|
||||
SelectConditionStep<Record7<Integer, String, String, EnumCamprole, String, LocalDateTime, LocalDateTime>> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_PERSON.PK,
|
||||
T_PERSON.FORENAME,
|
||||
T_PERSON.SURNAME,
|
||||
T_PERSON.CAMPROLE,
|
||||
T_CAMP.NAME,
|
||||
T_CAMP.ARRIVE,
|
||||
T_CAMP.DEPART)
|
||||
.from(T_PERSON)
|
||||
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP))
|
||||
.where(T_PERSON.PK.eq(id));
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
Record7<Integer, String, String, EnumCamprole, String, LocalDateTime, LocalDateTime> r = sql.fetchOne();
|
||||
if (r != null) {
|
||||
BookingBean bean = new BookingBean();
|
||||
bean.setPk(r.get(T_PERSON.PK));
|
||||
bean.setForename(r.get(T_PERSON.FORENAME));
|
||||
bean.setSurname(r.get(T_PERSON.SURNAME));
|
||||
bean.setCampName(r.get(T_CAMP.NAME));
|
||||
bean.setArrive(r.get(T_CAMP.ARRIVE));
|
||||
bean.setDepart(r.get(T_CAMP.DEPART));
|
||||
bean.setCamprole(r.get(T_PERSON.CAMPROLE));
|
||||
return bean;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the booking and all of its dependencies
|
||||
*
|
||||
* @param id the pk of t_person
|
||||
* @return number of affected database rows, should be 1
|
||||
*/
|
||||
public Integer removeBooking(Integer id) {
|
||||
LambdaResultWrapper lrw = new LambdaResultWrapper();
|
||||
jooq.transaction(t -> {
|
||||
DeleteConditionStep<TPersondocumentRecord> sql1 = DSL.using(t).deleteFrom(T_PERSONDOCUMENT)
|
||||
.where(T_PERSONDOCUMENT.FK_PERSON.eq(id));
|
||||
LOGGER.debug(sql1.toString());
|
||||
sql1.execute();
|
||||
|
||||
DeleteConditionStep<TPersonRecord> sql2 = DSL.using(t).deleteFrom(T_PERSON).where(T_PERSON.PK.eq(id));
|
||||
LOGGER.debug(sql2.toString());
|
||||
lrw.add(sql2.execute());
|
||||
});
|
||||
return lrw.getCounter();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package de.jottyfan.camporganizer.module.registration;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.common.BookingBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
@@ -10,6 +14,7 @@ import org.springframework.stereotype.Service;
|
||||
*/
|
||||
@Service
|
||||
public class RegistrationService {
|
||||
private final static Logger LOGGER = LogManager.getLogger(RegistrationService.class);
|
||||
|
||||
@Autowired
|
||||
private RegistrationGateway gateway;
|
||||
@@ -36,8 +41,34 @@ public class RegistrationService {
|
||||
public Boolean register(RegistrationBean bean) {
|
||||
Boolean result = gateway.register(bean);
|
||||
if (result && bean.getRegisterInKeycloak()) {
|
||||
keycloak.register(bean.getLogin(), bean.getPassword(), bean.getEmail());
|
||||
keycloak.register(bean.getForename(), bean.getSurname(), bean.getLogin(), bean.getPassword(), bean.getEmail());
|
||||
if (bean.getEmail() != null && !bean.getEmail().isBlank()) {
|
||||
try {
|
||||
keycloak.sendVerificationLink(bean.getLogin());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the booking bean
|
||||
*
|
||||
* @param id the id of the registration (t_person.pk)
|
||||
* @return the booking bean or null
|
||||
*/
|
||||
public BookingBean getBooking(Integer id) {
|
||||
return gateway.getBooking(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* remove the booking and all of its dependencies
|
||||
*
|
||||
* @param id the id of the booking (t_person.pk)
|
||||
*/
|
||||
public Boolean removeBooking(Integer id) {
|
||||
return gateway.removeBooking(id) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user