diff --git a/build.gradle b/build.gradle index beb359f..b26be53 100644 --- a/build.gradle +++ b/build.gradle @@ -1,5 +1,5 @@ plugins { - id 'org.springframework.boot' version '3.2.1' + id 'org.springframework.boot' version '3.2.3' id "io.spring.dependency-management" version "1.1.4" id 'java' id 'war' diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 41dfb87..8049c68 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 9d9cdba..cccdd3d 100755 --- a/gradlew +++ b/gradlew @@ -162,7 +162,7 @@ save () { APP_ARGS=$(save "$@") # Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS --illegal-access=permit $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationController.java b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationController.java index 2e92140..32e0150 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationController.java +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationController.java @@ -1,11 +1,12 @@ package de.jottyfan.camporganizer.module.registration; -import jakarta.validation.Valid; - +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; 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.ObjectError; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; import org.springframework.web.bind.annotation.PathVariable; @@ -15,6 +16,7 @@ import de.jottyfan.camporganizer.db.EnumConverter; import de.jottyfan.camporganizer.module.camplist.CommonController; import de.jottyfan.camporganizer.module.registration.model.CampBean; import de.jottyfan.camporganizer.module.registration.model.RegistrationBean; +import jakarta.validation.Valid; /** * @@ -23,6 +25,7 @@ import de.jottyfan.camporganizer.module.registration.model.RegistrationBean; */ @Controller public class RegistrationController extends CommonController { + private static final Logger LOGGER = LogManager.getLogger(RegistrationController.class); @Autowired private RegistrationService service; @@ -61,14 +64,33 @@ public class RegistrationController extends CommonController { public String register(@Valid @ModelAttribute("bean") RegistrationBean bean, final BindingResult bindingResult, Model model) { if (bindingResult.hasErrors()) { + for (ObjectError error : bindingResult.getAllErrors()) { + LOGGER.info("found {}", error); + } CampBean campBean = service.getCamp(bean.getFkCamp()); model.addAttribute("camp", campBean); model.addAttribute("sexes", EnumConverter.getSexes()); model.addAttribute("roles", EnumConverter.getRoles()); + String currentUser = getCurrentUser(); + if (currentUser != null) { + model.addAttribute("wellknown", service.getWellKnownRegistrations(currentUser)); + } return "/registration/registration"; } - Boolean result = service.register(bean, getCurrentUser()); - return result ? "/registration/success" : "/error"; + Integer result = service.register(bean, getCurrentUser()); + if (result < 1) { + LOGGER.trace("added less than 1 row"); + CampBean campBean = service.getCamp(bean.getFkCamp()); + model.addAttribute("camp", campBean); + model.addAttribute("sexes", EnumConverter.getSexes()); + model.addAttribute("roles", EnumConverter.getRoles()); + String currentUser = getCurrentUser(); + if (currentUser != null) { + model.addAttribute("wellknown", service.getWellKnownRegistrations(currentUser)); + } + return "/registration/registration"; + } + return "/registration/success"; } @GetMapping("/registration/cancel/{id}") diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationRepository.java b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationRepository.java index 47e56fb..b630835 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationRepository.java +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationRepository.java @@ -23,8 +23,7 @@ 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.InsertReturningStep; import org.jooq.InsertValuesStep2; import org.jooq.Record; import org.jooq.Record1; @@ -75,7 +74,7 @@ public class RegistrationRepository { */ public CampBean getCamp(Integer pk) { SelectConditionStep sql = jooq.selectFrom(V_CAMP).where(V_CAMP.PK.eq(pk)); - LOGGER.debug(sql.toString()); + LOGGER.trace(sql.toString()); VCampRecord r = sql.fetchOne(); if (r != null) { CampBean bean = new CampBean(); @@ -103,7 +102,7 @@ public class RegistrationRepository { .selectFrom(T_PROFILE) .where(DSL.lower(T_PROFILE.USERNAME).eq(login)); // @formatter:on - LOGGER.debug(sql); + LOGGER.trace(sql); return sql.fetch().size() < 1; } @@ -112,9 +111,9 @@ public class RegistrationRepository { * registerInKeycloak is true * * @param bean the bean - * @return true or false + * @return number of data base rows; should be > 0 */ - public Boolean register(RegistrationBean bean) { + public Integer register(RegistrationBean bean) { LambdaResultWrapper lrw = new LambdaResultWrapper(); jooq.transaction(t -> { if (bean.getLogin() != null && !bean.getLogin().isEmpty()) { @@ -137,7 +136,7 @@ public class RegistrationRepository { .values(bean.getForename(), bean.getSurname(), bean.getLogin().toLowerCase(), oldPassword, LocalDateTime.now().plus(356, ChronoUnit.DAYS), UUID.nameUUIDFromBytes(bean.getLogin().getBytes()).toString()) .returning(T_PROFILE.PK); // @formatter:on - LOGGER.debug(sql1.toString()); + LOGGER.trace(sql1.toString()); fkProfile = sql1.fetchOne().getPk(); InsertValuesStep2 sql2 = jooq @@ -156,13 +155,12 @@ public class RegistrationRepository { .from(T_PROFILE) .where(DSL.lower(T_PROFILE.USERNAME).eq(bean.getLogin().toLowerCase())); // @formatter:on - LOGGER.debug(sql1.toString()); + LOGGER.trace(sql1.toString()); fkProfile = sql1.fetchOne().get(T_PROFILE.PK); } // register the person for camp participation - InsertValuesStep13 sql2 = DSL - .using(t) - // @formatter:off + InsertReturningStep sql2 = DSL.using(t) + // @formatter:off .insertInto(T_PERSON, T_PERSON.FORENAME, T_PERSON.SURNAME, @@ -179,15 +177,16 @@ public class RegistrationRepository { 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); + bean.getPhone(), bean.getCampRole(), bean.getFkCamp(), bean.getComment(), fkProfile) + .onConflict(T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.BIRTHDATE, T_PERSON.FK_CAMP) + .doNothing(); // @formatter:on - LOGGER.debug(sql2.toString()); + LOGGER.trace(sql2.toString()); lrw.add(sql2.execute()); // register the login for the portal } else { - InsertValuesStep12 sql = DSL - .using(t) - // @formatter:off + InsertReturningStep sql = DSL.using(t) + // @formatter:off .insertInto(T_PERSON, T_PERSON.FORENAME, T_PERSON.SURNAME, @@ -203,13 +202,15 @@ public class RegistrationRepository { 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()); + bean.getPhone(), bean.getCampRole(), bean.getFkCamp(), bean.getComment()) + .onConflict(T_PERSON.FORENAME, T_PERSON.SURNAME, T_PERSON.BIRTHDATE, T_PERSON.FK_CAMP) + .doNothing(); // @formatter:on - LOGGER.debug(sql.toString()); + LOGGER.trace(sql.toString()); lrw.add(sql.execute()); } }); - return lrw.getCounter() > 0; + return lrw.getCounter(); } /** @@ -232,7 +233,7 @@ public class RegistrationRepository { .leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_PERSON.FK_CAMP)) .where(T_PERSON.PK.eq(id)); // @formatter:on - LOGGER.debug(sql.toString()); + LOGGER.trace(sql.toString()); Record7 r = sql.fetchOne(); if (r != null) { BookingBean bean = new BookingBean(); @@ -265,7 +266,7 @@ public class RegistrationRepository { .leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_PERSON.FK_PROFILE)) .where(T_PERSON.PK.eq(id)); // @formatter:on - LOGGER.debug(sql0.toString()); + LOGGER.trace(sql0.toString()); Record5 r = sql0.fetchOne(); if (r == null) { throw new DataAccessException("no such entry in t_person with id = " + id); @@ -286,11 +287,11 @@ public class RegistrationRepository { DeleteConditionStep sql1 = DSL.using(t).deleteFrom(T_PERSONDOCUMENT) .where(T_PERSONDOCUMENT.FK_PERSON.eq(id)); - LOGGER.debug(sql1.toString()); + LOGGER.trace(sql1.toString()); sql1.execute(); DeleteConditionStep sql2 = DSL.using(t).deleteFrom(T_PERSON).where(T_PERSON.PK.eq(id)); - LOGGER.debug(sql2.toString()); + LOGGER.trace(sql2.toString()); lrw.add(sql2.execute()); InsertValuesStep2 sql3 = DSL.using(t) @@ -300,7 +301,7 @@ public class RegistrationRepository { T_RSS.RECIPIENT) .values(rssMessage.toString(), "registrator"); // @formatter:on - LOGGER.debug("{}", sql3.toString()); + LOGGER.trace("{}", sql3.toString()); sql3.execute(); }); return lrw.getCounter(); @@ -319,7 +320,7 @@ public class RegistrationRepository { .from(T_CAMP) .where(T_CAMP.PK.eq(fkCamp)); // @formatter:on - LOGGER.debug(sql.toString()); + LOGGER.trace(sql.toString()); Iterator> i = sql.fetch().iterator(); while (i.hasNext()) { LocalDateTime depart = i.next().get(T_CAMP.DEPART); @@ -343,7 +344,7 @@ public class RegistrationRepository { .set(T_PERSON.FK_PROFILE, (Integer) null) .where(T_PERSON.FK_PROFILE.eq(bean.getPk())); // @formatter:off - LOGGER.debug("{}", sql.toString()); + LOGGER.trace("{}", sql.toString()); sql.execute(); DeleteConditionStep sql1 = DSL.using(t) @@ -356,7 +357,7 @@ public class RegistrationRepository { .where(T_PROFILE.USERNAME.eq(bean.getUsername()) ))); // @formatter:on - LOGGER.debug("{}", sql1.toString()); + LOGGER.trace("{}", sql1.toString()); sql1.execute(); DeleteConditionStep sql2 = DSL.using(t) @@ -364,7 +365,7 @@ public class RegistrationRepository { .deleteFrom(T_PROFILE) .where(T_PROFILE.USERNAME.eq(bean.getUsername())); // @formatter:on - LOGGER.debug("{}", sql2.toString()); + LOGGER.trace("{}", sql2.toString()); sql2.execute(); InsertValuesStep2 sql3 = DSL.using(t) @@ -374,7 +375,7 @@ public class RegistrationRepository { T_RSS.RECIPIENT) .values(new StringBuilder(bean.getFullname()).append(" hat sich vom Portal CampOrganizer2 abgemeldet.").toString(), "admin"); // @formatter:on - LOGGER.debug("{}", sql3.toString()); + LOGGER.trace("{}", sql3.toString()); sql3.execute(); }); } @@ -393,7 +394,7 @@ public class RegistrationRepository { .set(T_PERSON.CONSENT_CATALOG_PHOTO, consent) .where(T_PERSON.PK.eq(id)); // @formatter:on - LOGGER.debug("{}", sql.toString()); + LOGGER.trace("{}", sql.toString()); sql.execute(); } @@ -415,7 +416,7 @@ public class RegistrationRepository { .from(T_CAMP) .where(T_CAMP.PK.eq(fkCamp)); // @formatter:on - LOGGER.debug(sql.toString()); + LOGGER.trace(sql.toString()); Record r = sql.fetchOne(); Integer minTeacherAge = r.get(T_CAMP.MAX_AGE) + 2; // by default, we need 2 years older teachers at least DayToSecond currentTeacherAge = r.get("teacherAge", DayToSecond.class); @@ -468,4 +469,28 @@ public class RegistrationRepository { } return list; } + + /** + * returns true if and only if this combination of registration has already been done + * + * @param forename the forename + * @param surname the surname + * @param birthDate the birth date + * @param campId the ID of the camp + * @return true or false + */ + public Boolean checkAlreadyRegistered(String forename, String surname, LocalDate birthDate, Integer campId) { + SelectConditionStep> sql = jooq + // @formatter:off + .select(T_PERSON.PK) + .from(T_PERSON) + .where(T_PERSON.FORENAME.eq(forename)) + .and(T_PERSON.SURNAME.eq(surname)) + .and(T_PERSON.BIRTHDATE.eq(birthDate)) + .and(T_PERSON.FK_CAMP.eq(campId)); + // @formatter:on + LOGGER.trace(sql); + Iterator i = sql.fetch(T_PERSON.PK).iterator(); + return i.hasNext(); + } } diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationService.java b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationService.java index 80fa902..9e4fa17 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationService.java +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/RegistrationService.java @@ -20,7 +20,7 @@ import de.jottyfan.camporganizer.module.registration.model.RegistrationBean; public class RegistrationService { @Autowired - private RegistrationRepository gateway; + private RegistrationRepository repository; @Autowired private KeycloakRepository keycloak; @@ -32,7 +32,7 @@ public class RegistrationService { * @return true or false */ public Boolean campIsNotYetOver(Integer fkCamp) { - return gateway.campIsNotYetOver(fkCamp); + return repository.campIsNotYetOver(fkCamp); } /** @@ -42,22 +42,22 @@ public class RegistrationService { * @return the camp bean or null */ public CampBean getCamp(Integer fkCamp) { - return gateway.getCamp(fkCamp); + return repository.getCamp(fkCamp); } /** * register the person for a camp; if registerInKeycloak, do so also * * @param bean the bean - * @return true if successful, false otherwise + * @return number of database rows; should be > 0 */ - public Boolean register(RegistrationBean bean, String currentUser) { + public Integer register(RegistrationBean bean, String currentUser) { if (currentUser != null) { bean.setRegisterInKeycloak(false); // already registered bean.setLogin(currentUser); } - Boolean result = gateway.register(bean); - if (result && bean.getRegisterInKeycloak()) { + Integer result = repository.register(bean); + if (result > 0 && bean.getRegisterInKeycloak()) { keycloak.register(bean.getKcForename(), bean.getKcSurname(), bean.getLogin(), bean.getPassword(), bean.getKcEmail()); } @@ -71,7 +71,7 @@ public class RegistrationService { * @return the booking bean or null */ public BookingBean getBooking(Integer id) { - return gateway.getBooking(id); + return repository.getBooking(id); } /** @@ -80,11 +80,11 @@ public class RegistrationService { * @param id the id of the booking (t_person.pk) */ public Boolean removeBooking(Integer id) { - return gateway.removeBooking(id) > 0; + return repository.removeBooking(id) > 0; } public void toggleConsent(Integer id) { - gateway.toggleConsent(id); + repository.toggleConsent(id); } /** @@ -97,7 +97,7 @@ public class RegistrationService { if (currentUser == null) { return null; } else { - List r = gateway.getRegistrations(currentUser); + List r = repository.getRegistrations(currentUser); if (r == null) { return null; } else { diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/model/RegistrationBean.java b/src/main/java/de/jottyfan/camporganizer/module/registration/model/RegistrationBean.java index 4e60422..9093a89 100644 --- a/src/main/java/de/jottyfan/camporganizer/module/registration/model/RegistrationBean.java +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/model/RegistrationBean.java @@ -11,6 +11,7 @@ import org.springframework.format.annotation.DateTimeFormat; import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole; import de.jottyfan.camporganizer.db.jooq.enums.EnumSex; +import de.jottyfan.camporganizer.module.registration.validate.AlreadyRegisteredCheck; import de.jottyfan.camporganizer.module.registration.validate.TeacherAgeCheck; import de.jottyfan.camporganizer.module.registration.validate.UnusedUsername; @@ -21,9 +22,10 @@ import de.jottyfan.camporganizer.module.registration.validate.UnusedUsername; */ @UnusedUsername(field = "login", message = "Dieses Login ist leider bereits vergeben. Bitte wähle ein anderes.") @TeacherAgeCheck(field = "birthDate", fkCamp = "fkCamp", campRole = "campRole", message = "Als Mitarbeiter bist Du leider zu jung für diese Freizeit.") -// TODO: registration completeness annotation; in case of registerInKeycloak == true, force login, password, kcForename, kcSurname and kcEmail not to be blank +@AlreadyRegisteredCheck(field = "forename", surname = "surname", birthDate = "birthDate", fkCamp = "fkCamp", message = "Diese Anmeldung wurde bereits vorgenommen. Wenn Du sie in Deinem Profil nicht sehen kannst, wurde sie vielleicht von jemand Anderem durchgeführt. In Absprache mit der Freizeitleitung kannst Du die Anmeldung von einem Administrator Deinem Konto zuordnen lassen.") public class RegistrationBean implements Serializable { - private static final long serialVersionUID = 1L; +//TODO: registration completeness annotation; in case of registerInKeycloak == true, force login, password, kcForename, kcSurname and kcEmail not to be blank + private static final long serialVersionUID = 2L; @NotBlank(message = "Bitte gib deinen Vornamen an.") private String forename; @@ -55,6 +57,31 @@ public class RegistrationBean implements Serializable { private String kcSurname; private String kcEmail; + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + buf.append("RegistrationBean{forename=").append(forename); + buf.append(", surname=").append(surname); + buf.append(", sex=").append(sex); + buf.append(", birthDate=").append(birthDate); + buf.append(", street=").append(street); + buf.append(", zip=").append(zip); + buf.append(", city=").append(city); + buf.append(", email=").append(email); + buf.append(", phone=").append(phone); + buf.append(", comment=").append(comment); + buf.append(", fkCamp=").append(fkCamp); + buf.append(", campRole=").append(campRole); + buf.append(", registerInKeycloak=").append(registerInKeycloak); + buf.append(", login=").append(login); + buf.append(", password=********"); + buf.append(", kcForename=").append(kcForename); + buf.append(", kcSurname=").append(kcSurname); + buf.append(", kcEmail=").append(kcEmail); + buf.append("}"); + return buf.toString(); + } + /** * @return forename + surname, separated by a space */ diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheck.java b/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheck.java new file mode 100644 index 0000000..d72e243 --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheck.java @@ -0,0 +1,33 @@ +package de.jottyfan.camporganizer.module.registration.validate; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +/** +* +* @author jotty +* +*/ +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = AlreadyRegisteredCheckValidator.class) +@Documented +public @interface AlreadyRegisteredCheck { + String message() default "already registered"; + + String field(); + String surname(); + String birthDate(); + String fkCamp(); + + Class[] groups() default {}; + + Class[] payload() default {}; +} + diff --git a/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheckValidator.java b/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheckValidator.java new file mode 100644 index 0000000..1a4836b --- /dev/null +++ b/src/main/java/de/jottyfan/camporganizer/module/registration/validate/AlreadyRegisteredCheckValidator.java @@ -0,0 +1,60 @@ +package de.jottyfan.camporganizer.module.registration.validate; + +import java.time.LocalDate; + +import org.springframework.beans.BeanWrapperImpl; +import org.springframework.beans.factory.annotation.Autowired; + +import de.jottyfan.camporganizer.module.registration.RegistrationRepository; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +/** + * + * @author jotty + * + */ +public class AlreadyRegisteredCheckValidator implements ConstraintValidator { + + private String field; + private String fkCamp; + private String surname; + private String birthDate; + private String message; + + @Autowired + private RegistrationRepository gateway; + + public void initialize(AlreadyRegisteredCheck arc) { + this.field = arc.field(); + this.fkCamp = arc.fkCamp(); + this.surname = arc.surname(); + this.birthDate = arc.birthDate(); + this.message = arc.message(); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + Object forename = new BeanWrapperImpl(value).getPropertyValue(field); + Object campId = new BeanWrapperImpl(value).getPropertyValue(fkCamp); + Object theSurname = new BeanWrapperImpl(value).getPropertyValue(surname); + Object theBirthDate = new BeanWrapperImpl(value).getPropertyValue(birthDate); + Boolean found = false; + if (theBirthDate != null) { + String fn = (String) forename; + Integer camp = (Integer) campId; + String sn = (String) theSurname; + LocalDate bd = (LocalDate) theBirthDate; + found = gateway.checkAlreadyRegistered(fn, sn, bd, camp); + if (found) { + context.disableDefaultConstraintViolation(); + context.buildConstraintViolationWithTemplate(message).addPropertyNode(fkCamp).addConstraintViolation(); + context.buildConstraintViolationWithTemplate("s.o.").addPropertyNode(field).addConstraintViolation(); + context.buildConstraintViolationWithTemplate("s.o.").addPropertyNode(surname).addConstraintViolation(); + context.buildConstraintViolationWithTemplate("s.o.").addPropertyNode(birthDate).addConstraintViolation(); + } + } + return !found; + } + +} diff --git a/src/main/resources/templates/verein.html b/src/main/resources/templates/verein.html index 7b5d538..2e28291 100644 --- a/src/main/resources/templates/verein.html +++ b/src/main/resources/templates/verein.html @@ -9,72 +9,50 @@
-

Was ist der Onkel Werner Freizeiten Verein?

-

Der Verein „Onkel Werner Freizeiten e.V.“ ist ein christliches Kinder- und Jugendwerk.

-

Seit unserer Gründung führen wir Ferienfreizeiten für Kinder und Jugendliche an verschiedenen Orten in Deutschland und - der Schweiz durch. Diese ziehen jährlich bis zu 400 junge Menschen im Alter von 6 bis 17 Jahren aus ganz Deutschland an.

-

Wir sind vom Finanzamt Heilbronn als gemeinnützig und mildtätig anerkannt. Unser Name leitet sich vom Gründer der - Freizeitarbeit, Werner Blödtner, ab, der von vielen schlicht „Onkel Werner“ genannt wird.

-

Wie ist der Verein entstanden?

-

Unser Verein wurde offiziell im November 2013 gegründet, um dem sozialen Engagement für Kinder und Jugendliche in der - christlichen Freizeitarbeit einen Rahmen zu geben.

-

Wie alles anfing

-

Doch unsere Geschichte beginnt eigentlich schon vor mehr als fünf Jahrzehnten mit einem jungen Mann, der seine Liebe zu - Jesus Christus fand und diese teilen wollte. Werner Blödtner (später schlicht Onkel Werner genannt) hatte bereits zahlreiche - Stunden in Sonntagsschule und Jungschar einer christlichen Gemeinde gestaltet, als er 1963 angefragt wird, eine mehrtägige - Freizeit in den Schulferien durchzuführen. Er lässt sich auf das Abenteuer ein und übernimmt 1978 die überregionale Kinder- - und Teeniearbeit der Barmer Zeltmission.

-

Die Bedingung

-

Allerdings nur unter folgender Vereinbarung mit Gott: Sollte sich kein Kind für den Herrn Jesus entscheiden, würde er - mit der Arbeit wieder aufhören. Zu einer Kinderwoche im Odenwald an Ostern kommen ca. 100 Kinder aus dem Ort und umliegenden - Dörfern. Onkel Werner selbst sagt: „Das war für mich eine große Herausforderung. Wie würde Gott antworten? Ich war sehr - erstaunt, dass nach und nach fünf Kinder den Wunsch äußerten, den Herrn Jesus in ihr Herz und Leben einzuladen.“

-

Unterwegs für Jesus

-

Seither ist Onkel Werner also für Jesus Christus unterwegs. Neben den Kinderstundenwochen entwickelte sich nach und - nach die Freizeitarbeit als Angebot in den Ferien der Kinder und Teenies.

-

Der Verein

-

Und unser Verein? Der ist eben aus genau diesen Kindern und Jugendlichen entstanden, die selbst Onkel Werners - Freizeiten besucht haben und später dort Mitarbeiter geworden sind. Wir möchten, dass seine Arbeit weitergeführt wird. Aber - vor allem wollen wir, dass noch viele Kinder und Jugendliche den Herrn Jesus kennen lernen können und mit ihm leben wollen.

-

-

Die Vereinsmitglieder

-

- In unserem Verein arbeiten verschiedene Freizeitbegeisterte mit, von denen sich hier ein paar vorstellen: -

+

Was ist der Onkel Werner Freizeiten Verein?

+

Der Verein „Onkel Werner Freizeiten e.V.“ ist ein christliches Kinder- und Jugendwerk.

+

Seit unserer Gründung führen wir Ferienfreizeiten für Kinder und Jugendliche an verschiedenen Orten in Deutschland und der Schweiz durch. Diese ziehen jährlich bis zu 400 junge + Menschen im Alter von 6 bis 17 Jahren aus ganz Deutschland an.

+

Wir sind vom Finanzamt Heilbronn als gemeinnützig und mildtätig anerkannt. Unser Name leitet sich vom Gründer der Freizeitarbeit, Werner Blödtner, ab, der von vielen schlicht + „Onkel Werner“ genannt wird.

+

Wie ist der Verein entstanden?

+

Unser Verein wurde offiziell im November 2013 gegründet, um dem sozialen Engagement für Kinder und Jugendliche in der christlichen Freizeitarbeit einen Rahmen zu geben.

+

Wie alles anfing

+

Doch unsere Geschichte beginnt eigentlich schon vor mehr als fünf Jahrzehnten mit einem jungen Mann, der seine Liebe zu Jesus Christus fand und diese teilen wollte. Werner Blödtner + (später schlicht Onkel Werner genannt) hatte bereits zahlreiche Stunden in Sonntagsschule und Jungschar einer christlichen Gemeinde gestaltet, als er 1963 angefragt wird, eine mehrtägige + Freizeit in den Schulferien durchzuführen. Er lässt sich auf das Abenteuer ein und übernimmt 1978 die überregionale Kinder- und Teeniearbeit der Barmer Zeltmission.

+

Die Bedingung

+

Allerdings nur unter folgender Vereinbarung mit Gott: Sollte sich kein Kind für den Herrn Jesus entscheiden, würde er mit der Arbeit wieder aufhören. Zu einer Kinderwoche im + Odenwald an Ostern kommen ca. 100 Kinder aus dem Ort und umliegenden Dörfern. Onkel Werner selbst sagt: „Das war für mich eine große Herausforderung. Wie würde Gott antworten? Ich war + sehr erstaunt, dass nach und nach fünf Kinder den Wunsch äußerten, den Herrn Jesus in ihr Herz und Leben einzuladen.“

+

Unterwegs für Jesus

+

Seither ist Onkel Werner also für Jesus Christus unterwegs. Neben den Kinderstundenwochen entwickelte sich nach und nach die Freizeitarbeit als Angebot in den Ferien der Kinder und + Teenies.

+

Der Verein

+

Und unser Verein? Der ist eben aus genau diesen Kindern und Jugendlichen entstanden, die selbst Onkel Werners Freizeiten besucht haben und später dort Mitarbeiter geworden sind. + Wir möchten, dass seine Arbeit weitergeführt wird. Aber vor allem wollen wir, dass noch viele Kinder und Jugendliche den Herrn Jesus kennen lernen können und mit ihm leben wollen.

+

+

Die Vereinsmitglieder

+

In unserem Verein arbeiten verschiedene Freizeitbegeisterte mit, von denen sich hier ein paar vorstellen:

- - Simeon Velleuer, 41 Jahre, verheiratet mit Anja und Vater von zwei wunderbaren Kindern, Sophie und Kaleb. Für alle „Süddeutschen“ - – meine Heimat liegt „im Norden“ – in Mettmann.
-
- Ich darf mittlerweile auf eine über zwanzigjährige Zeit in der Mitarbeit mit Kids und Teens zurückblicken und bin unserem gnädigen - Gott und Vater dafür sehr dankbar. Er hat mich errettet und aus der Finsternis in sein wunderbares Licht berufen (1.Petr. 2,9). - Diese Botschaft möchte ich gerne weitergeben - auf Freizeiten durch die froh machende Botschaft der Bibel und durch das ganz - praktische und tägliche Leben.
-
- Ich erhoffe mir von den Freizeiten, dass wir auf ein Leben mit Gott aufmerksam machen können. Das ist spannend und herausfordernd - zugleich. Durch zahlreiche Erfahrungen in meinem Leben habe ich feststellen können, dass Gott immer den richtigen Plan für jeden - ganz persönlich längst fertig hat. Wir dürfen uns ihm ganz anvertrauen.
-
- (Es ist schon ein paar Jahre her, als ich selber noch Teilnehmer auf der wunderschönen Griesalp war. Heutzutage fahren wir ins - Kiental. Großartig gelegen inmitten der faszinierenden Bergwelt des Schweizer Berner Oberlandes. Die Kombination aus Wanderungen - und Andachten ist genau das Richtige für mich...und mit Sicherheit auch für dich.)
-
-
- - Jörg Henke, Vater von zwei atemberaubenden Töchtern. Aus Dresden unterstütze ich die Freizeitarbeit v.a. im Bereich der Homepage und - den Abrechnungen. Wenn ich es mal wieder schaffe, auch an einer Freizeit teilzunehmen, spiele ich gerne Gitarre und singe viele - Lieder mit den Teilnehmern.
-
- Als einer von Onkel Werners "Erben" darf ich mich an meine Bekehrung erinnern, die ich am 31.10.1993 erlebt habe. Details dazu gibt - es auch hier: https://www.jottyfan.de/bekehrung/.
-
- Gerade deswegen ist es mir wichtig, dass unsere Freizeiten stattfinden, offen für finanziell schwächere Familien sind und wir durch - die uns anvertrauten Spenden unterstützen können. Jedes Kind / jeder Teenie soll die rettende Botschaft vom Kreuz hören: dass Jesus - Christus gerade für dich gestorben und auferstanden ist, um dich von deinen Sünden zu befreien und dir damit ewiges Leben in der - Gemeinschaft mit Gott schenkt. Sehr wertvoll finde ich daher auch die Abendandachten, die es ermöglichen, genau diese Wahrheit zu - verdeutlichen.
-
+ Simeon Velleuer, 41 Jahre, verheiratet mit Anja und Vater von zwei wunderbaren + Kindern, Sophie und Kaleb. Für alle „Süddeutschen“ – meine Heimat liegt „im Norden“ – in Mettmann.

Ich darf mittlerweile auf eine über zwanzigjährige Zeit in der Mitarbeit + mit Kids und Teens zurückblicken und bin unserem gnädigen Gott und Vater dafür sehr dankbar. Er hat mich errettet und aus der Finsternis in sein wunderbares Licht berufen (1.Petr. 2,9). + Diese Botschaft möchte ich gerne weitergeben - auf Freizeiten durch die froh machende Botschaft der Bibel und durch das ganz praktische und tägliche Leben.

Ich erhoffe mir + von den Freizeiten, dass wir auf ein Leben mit Gott aufmerksam machen können. Das ist spannend und herausfordernd zugleich. Durch zahlreiche Erfahrungen in meinem Leben habe ich + feststellen können, dass Gott immer den richtigen Plan für jeden ganz persönlich längst fertig hat. Wir dürfen uns ihm ganz anvertrauen.

(Es ist schon ein paar Jahre her, + als ich selber noch Teilnehmer auf der wunderschönen Griesalp war. Heutzutage fahren wir ins Kiental. Großartig gelegen inmitten der faszinierenden Bergwelt des Schweizer Berner + Oberlandes. Die Kombination aus Wanderungen und Andachten ist genau das Richtige für mich...und mit Sicherheit auch für dich.)
+
+
+ Jörg Henke, Vater von zwei atemberaubenden Töchtern. Aus Dresden unterstütze ich die + Freizeitarbeit v.a. im Bereich der Homepage und den Abrechnungen. Wenn ich es mal wieder schaffe, auch an einer Freizeit teilzunehmen, spiele ich gerne Gitarre und singe viele Lieder mit + den Teilnehmern.

Als einer von Onkel Werners "Erben" darf ich mich an meine Bekehrung erinnern, die ich am 31.10.1993 erlebt habe. Details dazu gibt es auch hier: https://www.jottyfan.de/bekehrung/.

Gerade deswegen ist es mir wichtig, dass unsere Freizeiten stattfinden, + offen für finanziell schwächere Familien sind und wir durch die uns anvertrauten Spenden unterstützen können. Jedes Kind / jeder Teenie soll die rettende Botschaft vom Kreuz hören: dass + Jesus Christus gerade für dich gestorben und auferstanden ist, um dich von deinen Sünden zu befreien und dir damit ewiges Leben in der Gemeinschaft mit Gott schenkt. Sehr wertvoll finde + ich daher auch die Abendandachten, die es ermöglichen, genau diese Wahrheit zu verdeutlichen.