basic registration functionality, still missing keycloak
This commit is contained in:
parent
798b62fabb
commit
4133ad9173
@ -54,6 +54,9 @@ dependencies {
|
|||||||
implementation 'net.sf.biweekly:biweekly:0.6.6'
|
implementation 'net.sf.biweekly:biweekly:0.6.6'
|
||||||
|
|
||||||
implementation 'org.keycloak:keycloak-spring-boot-starter'
|
implementation 'org.keycloak:keycloak-spring-boot-starter'
|
||||||
|
|
||||||
|
// backward compatibility until the complete registration is converted to keycloak
|
||||||
|
implementation 'org.jasypt:jasypt:1.9.3'
|
||||||
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-jooq'
|
implementation 'org.springframework.boot:spring-boot-starter-jooq'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||||
|
@ -0,0 +1,22 @@
|
|||||||
|
package de.jottyfan.camporganizer.module.common;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class LambdaResultWrapper {
|
||||||
|
private Integer counter;
|
||||||
|
|
||||||
|
public LambdaResultWrapper() {
|
||||||
|
counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getCounter() {
|
||||||
|
return counter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Integer i) {
|
||||||
|
counter += i;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package de.jottyfan.camporganizer.module.registration;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author henkej
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Repository
|
||||||
|
public class KeycloakRepository {
|
||||||
|
private final static Logger LOGGER = LogManager.getLogger(KeycloakRepository.class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register the login in keycloak
|
||||||
|
*
|
||||||
|
* @param login
|
||||||
|
* @param password
|
||||||
|
*/
|
||||||
|
public void register(String login, String password) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
LOGGER.error("not yet implemented registration of user {} in keycloak", login);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,245 @@
|
|||||||
|
package de.jottyfan.camporganizer.module.registration;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.LocalDate;
|
||||||
|
|
||||||
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
|
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||||
|
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author jotty
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class RegistrationBean implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private String forename;
|
||||||
|
private String surname;
|
||||||
|
private EnumSex sex;
|
||||||
|
@DateTimeFormat(pattern="yyyy-MM-dd")
|
||||||
|
private LocalDate birthDate;
|
||||||
|
private String street;
|
||||||
|
private String zip;
|
||||||
|
private String city;
|
||||||
|
private String email;
|
||||||
|
private String phone;
|
||||||
|
private String comment;
|
||||||
|
private Integer fkCamp;
|
||||||
|
private EnumCamprole campRole;
|
||||||
|
private Boolean registerInKeycloak;
|
||||||
|
private String login;
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the sex
|
||||||
|
*/
|
||||||
|
public EnumSex getSex() {
|
||||||
|
return sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sex the sex to set
|
||||||
|
*/
|
||||||
|
public void setSex(EnumSex sex) {
|
||||||
|
this.sex = sex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the birthDate
|
||||||
|
*/
|
||||||
|
public LocalDate getBirthDate() {
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param birthDate the birthDate to set
|
||||||
|
*/
|
||||||
|
public void setBirthDate(LocalDate birthDate) {
|
||||||
|
this.birthDate = birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the street
|
||||||
|
*/
|
||||||
|
public String getStreet() {
|
||||||
|
return street;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param street the street to set
|
||||||
|
*/
|
||||||
|
public void setStreet(String street) {
|
||||||
|
this.street = street;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the zip
|
||||||
|
*/
|
||||||
|
public String getZip() {
|
||||||
|
return zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param zip the zip to set
|
||||||
|
*/
|
||||||
|
public void setZip(String zip) {
|
||||||
|
this.zip = zip;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the city
|
||||||
|
*/
|
||||||
|
public String getCity() {
|
||||||
|
return city;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param city the city to set
|
||||||
|
*/
|
||||||
|
public void setCity(String city) {
|
||||||
|
this.city = city;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the email
|
||||||
|
*/
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param email the email to set
|
||||||
|
*/
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the phone
|
||||||
|
*/
|
||||||
|
public String getPhone() {
|
||||||
|
return phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param phone the phone to set
|
||||||
|
*/
|
||||||
|
public void setPhone(String phone) {
|
||||||
|
this.phone = phone;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the comment
|
||||||
|
*/
|
||||||
|
public String getComment() {
|
||||||
|
return comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param comment the comment to set
|
||||||
|
*/
|
||||||
|
public void setComment(String comment) {
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the registerInKeycloak
|
||||||
|
*/
|
||||||
|
public Boolean getRegisterInKeycloak() {
|
||||||
|
return registerInKeycloak;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param registerInKeycloak the registerInKeycloak to set
|
||||||
|
*/
|
||||||
|
public void setRegisterInKeycloak(Boolean registerInKeycloak) {
|
||||||
|
this.registerInKeycloak = registerInKeycloak;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the login
|
||||||
|
*/
|
||||||
|
public String getLogin() {
|
||||||
|
return login;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param login the login to set
|
||||||
|
*/
|
||||||
|
public void setLogin(String login) {
|
||||||
|
this.login = login;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the password
|
||||||
|
*/
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param password the password to set
|
||||||
|
*/
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the fkCamp
|
||||||
|
*/
|
||||||
|
public Integer getFkCamp() {
|
||||||
|
return fkCamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param fkCamp the fkCamp to set
|
||||||
|
*/
|
||||||
|
public void setFkCamp(Integer fkCamp) {
|
||||||
|
this.fkCamp = fkCamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the campRole
|
||||||
|
*/
|
||||||
|
public EnumCamprole getCampRole() {
|
||||||
|
return campRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param campRole the campRole to set
|
||||||
|
*/
|
||||||
|
public void setCampRole(EnumCamprole campRole) {
|
||||||
|
this.campRole = campRole;
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.ui.Model;
|
import org.springframework.ui.Model;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
import org.springframework.web.bind.annotation.PathVariable;
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
|
||||||
import de.jottyfan.camporganizer.module.common.CommonController;
|
import de.jottyfan.camporganizer.module.common.CommonController;
|
||||||
|
|
||||||
@ -27,9 +29,19 @@ public class RegistrationController extends CommonController {
|
|||||||
@GetMapping("/registration/{fkCamp}")
|
@GetMapping("/registration/{fkCamp}")
|
||||||
public String index(@PathVariable(name = "fkCamp", required = true) Integer fkCamp, Model model) {
|
public String index(@PathVariable(name = "fkCamp", required = true) Integer fkCamp, Model model) {
|
||||||
super.setupSession(model, request);
|
super.setupSession(model, request);
|
||||||
model.addAttribute("camp", service.getCamp(fkCamp));
|
CampBean campBean = service.getCamp(fkCamp);
|
||||||
// TODO: prepare a bean for the form variables; use model.getAttribute("camp").getPk() for the fk_camp
|
model.addAttribute("camp", campBean);
|
||||||
|
RegistrationBean bean = new RegistrationBean();
|
||||||
|
bean.setFkCamp(fkCamp);
|
||||||
|
bean.setRegisterInKeycloak(true); // we want people to register generally
|
||||||
|
model.addAttribute("bean", bean);
|
||||||
return "/registration";
|
return "/registration";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/registration/register")
|
||||||
|
public String register(@ModelAttribute RegistrationBean bean, Model model) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,18 +1,34 @@
|
|||||||
package de.jottyfan.camporganizer.module.registration;
|
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_CAMP;
|
||||||
|
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
|
||||||
|
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import org.jasypt.util.password.StrongPasswordEncryptor;
|
||||||
import org.jooq.DSLContext;
|
import org.jooq.DSLContext;
|
||||||
|
import org.jooq.InsertResultStep;
|
||||||
|
import org.jooq.InsertValuesStep12;
|
||||||
|
import org.jooq.InsertValuesStep13;
|
||||||
import org.jooq.SelectConditionStep;
|
import org.jooq.SelectConditionStep;
|
||||||
|
import org.jooq.exception.DataAccessException;
|
||||||
|
import org.jooq.impl.DSL;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Repository;
|
import org.springframework.stereotype.Repository;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
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.TCampRecord;
|
||||||
|
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||||
|
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
|
||||||
|
import de.jottyfan.camporganizer.module.common.LambdaResultWrapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -49,4 +65,89 @@ public class RegistrationGateway {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* save the content in t_person; also, create a profile for the user if
|
||||||
|
* registerInKeycloak is true
|
||||||
|
*
|
||||||
|
* @param bean the bean
|
||||||
|
* @return true or false
|
||||||
|
*/
|
||||||
|
public Boolean register(RegistrationBean bean) {
|
||||||
|
LambdaResultWrapper lrw = new LambdaResultWrapper();
|
||||||
|
jooq.transaction(t -> {
|
||||||
|
if (bean.getRegisterInKeycloak()) {
|
||||||
|
SelectConditionStep<TProfileRecord> sql0 = DSL.using(t).selectFrom(T_PROFILE)
|
||||||
|
.where(T_PROFILE.USERNAME.eq(bean.getLogin()));
|
||||||
|
LOGGER.debug(sql0);
|
||||||
|
if (sql0.fetch().size() > 0) {
|
||||||
|
throw new DataAccessException("login already in use: " + bean.getLogin());
|
||||||
|
}
|
||||||
|
// TODO: check if teacher is at least 2 years older than the camp participants
|
||||||
|
String oldPassword = new StrongPasswordEncryptor().encryptPassword(bean.getPassword());
|
||||||
|
InsertResultStep<TProfileRecord> sql1 = DSL.using(t)
|
||||||
|
// @formatter:off
|
||||||
|
.insertInto(T_PROFILE,
|
||||||
|
T_PROFILE.FORENAME,
|
||||||
|
T_PROFILE.SURNAME,
|
||||||
|
T_PROFILE.USERNAME,
|
||||||
|
T_PROFILE.PASSWORD,
|
||||||
|
T_PROFILE.DUEDATE,
|
||||||
|
T_PROFILE.UUID)
|
||||||
|
.values(bean.getForename(), bean.getSurname(), bean.getLogin(), oldPassword, LocalDateTime.now().plus(356, ChronoUnit.DAYS), UUID.nameUUIDFromBytes(bean.getLogin().getBytes()).toString())
|
||||||
|
.returning(T_PROFILE.PK);
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug(sql1.toString());
|
||||||
|
Integer fkProfile = sql1.fetchOne().getPk();
|
||||||
|
// register the person for camp participation
|
||||||
|
InsertValuesStep13<TPersonRecord, String, String, EnumSex, LocalDate, String, String, String, String, String, EnumCamprole, Integer, String, Integer> sql2 = DSL
|
||||||
|
.using(t)
|
||||||
|
// @formatter:off
|
||||||
|
.insertInto(T_PERSON,
|
||||||
|
T_PERSON.FORENAME,
|
||||||
|
T_PERSON.SURNAME,
|
||||||
|
T_PERSON.SEX,
|
||||||
|
T_PERSON.BIRTHDATE,
|
||||||
|
T_PERSON.STREET,
|
||||||
|
T_PERSON.ZIP,
|
||||||
|
T_PERSON.CITY,
|
||||||
|
T_PERSON.EMAIL,
|
||||||
|
T_PERSON.PHONE,
|
||||||
|
T_PERSON.CAMPROLE,
|
||||||
|
T_PERSON.FK_CAMP,
|
||||||
|
T_PERSON.COMMENT,
|
||||||
|
T_PERSON.FK_PROFILE)
|
||||||
|
.values(bean.getForename(), bean.getSurname(), bean.getSex(),
|
||||||
|
bean.getBirthDate(), bean.getStreet(), bean.getZip(), bean.getCity(), bean.getEmail(),
|
||||||
|
bean.getPhone(), bean.getCampRole(), bean.getFkCamp(), bean.getComment(), fkProfile);
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug(sql2.toString());
|
||||||
|
lrw.add(sql2.execute());
|
||||||
|
// register the login for the portal
|
||||||
|
} else {
|
||||||
|
InsertValuesStep12<TPersonRecord, String, String, EnumSex, LocalDate, String, String, String, String, String, EnumCamprole, Integer, String> sql = DSL
|
||||||
|
.using(t)
|
||||||
|
// @formatter:off
|
||||||
|
.insertInto(T_PERSON,
|
||||||
|
T_PERSON.FORENAME,
|
||||||
|
T_PERSON.SURNAME,
|
||||||
|
T_PERSON.SEX,
|
||||||
|
T_PERSON.BIRTHDATE,
|
||||||
|
T_PERSON.STREET,
|
||||||
|
T_PERSON.ZIP,
|
||||||
|
T_PERSON.CITY,
|
||||||
|
T_PERSON.EMAIL,
|
||||||
|
T_PERSON.PHONE,
|
||||||
|
T_PERSON.CAMPROLE,
|
||||||
|
T_PERSON.FK_CAMP,
|
||||||
|
T_PERSON.COMMENT)
|
||||||
|
.values(bean.getForename(), bean.getSurname(), bean.getSex(),
|
||||||
|
bean.getBirthDate(), bean.getStreet(), bean.getZip(), bean.getCity(), bean.getEmail(),
|
||||||
|
bean.getPhone(), bean.getCampRole(), bean.getFkCamp(), bean.getComment());
|
||||||
|
// @formatter:on
|
||||||
|
LOGGER.debug(sql.toString());
|
||||||
|
lrw.add(sql.execute());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return lrw.getCounter() > 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,9 @@ public class RegistrationService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RegistrationGateway gateway;
|
private RegistrationGateway gateway;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private KeycloakRepository keycloak;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get the camp
|
* get the camp
|
||||||
@ -24,4 +27,17 @@ public class RegistrationService {
|
|||||||
return gateway.getCamp(fkCamp);
|
return gateway.getCamp(fkCamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* register the person for a camp; if registerInKeycloak, do so also
|
||||||
|
*
|
||||||
|
* @param bean the bean
|
||||||
|
* @return true if successful, false otherwise
|
||||||
|
*/
|
||||||
|
public Boolean register(RegistrationBean bean) {
|
||||||
|
Boolean result = gateway.register(bean);
|
||||||
|
if (result && bean.getRegisterInKeycloak()) {
|
||||||
|
keycloak.register(bean.getLogin(), bean.getPassword());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,66 +15,80 @@
|
|||||||
<h3 class="centered cabin" th:text="'zur ' + ${camp.name} + ' ' + ${camp.year}"></h3>
|
<h3 class="centered cabin" th:text="'zur ' + ${camp.name} + ' ' + ${camp.year}"></h3>
|
||||||
<div class="card centered-card" style="max-width: 48rem">
|
<div class="card centered-card" style="max-width: 48rem">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<form action="#" method="post">
|
<form th:action="@{/registration/register}" th:object="${bean}" method="post">
|
||||||
|
<input type="hidden" th:field="*{fkCamp}" />
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Vorname" />
|
<input type="text" class="form-control" placeholder="Vorname" th:field="*{forename}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Nachname" />
|
<input type="text" class="form-control" placeholder="Nachname" th:field="*{surname}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<select class="form-select">
|
<select class="form-select" th:field="*{sex}">
|
||||||
<option value="">Geschlecht</option>
|
<option value="">Geschlecht</option>
|
||||||
<option value="female">weiblich</option>
|
<option value="female">weiblich</option>
|
||||||
<option value="male">männlich</option>
|
<option value="male">männlich</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="date" class="form-control" placeholder="Geburtsdatum" />
|
<input type="date" class="form-control" placeholder="Geburtsdatum" th:field="*{birthDate}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Straße und Hausnummer" />
|
<input type="text" class="form-control" placeholder="Straße und Hausnummer" th:field="*{street}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-2 rowdist">
|
<div class="col-sm-2 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="PLZ" />
|
<input type="text" class="form-control" placeholder="PLZ" th:field="*{zip}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-4 rowdist">
|
<div class="col-sm-4 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Ort" />
|
<input type="text" class="form-control" placeholder="Ort" th:field="*{city}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="E-Mail" />
|
<input type="text" class="form-control" placeholder="E-Mail" th:field="*{email}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Telefonnummer" />
|
<input type="text" class="form-control" placeholder="Telefonnummer" th:field="*{phone}" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-sm-6 rowdist">
|
||||||
|
<span>mitkommen als</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 rowdist">
|
||||||
|
<select class="form-select" th:field="*{campRole}">
|
||||||
|
<option value="student">Teilnehmer</option>
|
||||||
|
<option value="teacher">Mitarbeiter</option>
|
||||||
|
<option value="feeder">Küchenteam</option>
|
||||||
|
<option value="director">Leiter</option>
|
||||||
|
</select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 rowdist">
|
<div class="col-sm-12 rowdist">
|
||||||
<textarea class="form-control" placeholder="Sonstiges"></textarea>
|
<textarea class="form-control" placeholder="Sonstiges" th:field="*{comment}"></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-12 rowdist">
|
<div class="col-sm-12 rowdist">
|
||||||
<div class="form-check" title="Die Anmeldedaten können in den Kontoeinstellungen bearbeitet und für die nächsten Freizeitanmeldungen verwendet werden.">
|
<div class="form-check" title="Die Anmeldedaten können in den Kontoeinstellungen bearbeitet und für die nächsten Freizeitanmeldungen verwendet werden.">
|
||||||
<input id="save" type="checkbox" class="form-check-input" checked="checked" onchange="$('#createlogin').toggle();" />
|
<input id="save" type="checkbox" class="form-check-input" th:field="*{registerInKeycloak}" onchange="$('#createlogin').toggle();" />
|
||||||
<label class="form-check-label" for="save">Anmeldedaten speichern</label>
|
<label class="form-check-label" for="save">Anmeldedaten speichern</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="createlogin" class="row">
|
<div id="createlogin" class="row">
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="text" class="form-control" placeholder="Login" />
|
<input type="text" class="form-control" placeholder="Login" th:field="*{login}" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-6 rowdist">
|
<div class="col-sm-6 rowdist">
|
||||||
<input type="password" class="form-control" placeholder="Passwort" />
|
<input type="password" class="form-control" placeholder="Passwort" th:field="*{password}" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@ -89,4 +103,4 @@
|
|||||||
</div>
|
</div>
|
||||||
</content>
|
</content>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user