Compare commits
10 Commits
4d604974e2
...
12a325ee03
Author | SHA1 | Date | |
---|---|---|---|
12a325ee03 | |||
497a4dfcf9 | |||
f31c433c80 | |||
7732d6da25 | |||
b07de9f2bc | |||
e8354c3f6e | |||
4a2d743a23 | |||
89cfbc6741 | |||
5b861f730f | |||
d1ee923f0a |
67
build.gradle
67
build.gradle
@ -1,25 +1,20 @@
|
||||
buildscript {
|
||||
ext {
|
||||
springBootVersion = '2.7.4'
|
||||
plugins {
|
||||
id 'org.springframework.boot' version '3.1.1'
|
||||
id "io.spring.dependency-management" version "1.1.2"
|
||||
id 'java'
|
||||
id 'war'
|
||||
id 'eclipse'
|
||||
id 'application'
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'org.springframework.boot'
|
||||
apply plugin: 'io.spring.dependency-management'
|
||||
apply plugin: 'war'
|
||||
apply plugin: 'application'
|
||||
|
||||
group = 'de.jottyfan.camporganizer'
|
||||
version = '0.5.0'
|
||||
version = '0.5.7'
|
||||
|
||||
description = """CampOrganizer2"""
|
||||
|
||||
sourceCompatibility = 17
|
||||
targetCompatibility = 17
|
||||
|
||||
mainClassName = "de.jottyfan.camporganizer.Main"
|
||||
|
||||
repositories {
|
||||
@ -27,16 +22,21 @@ repositories {
|
||||
maven {
|
||||
url "https://www.jottyfan.de/libs/"
|
||||
}
|
||||
maven {
|
||||
url "https://repo.maven.apache.org/maven2"
|
||||
}
|
||||
|
||||
ext {
|
||||
set('keycloakVersion', '21.1.1')
|
||||
}
|
||||
|
||||
war {
|
||||
doFirst {
|
||||
manifest {
|
||||
attributes("Implementation-Version": version)
|
||||
attributes("Implementation-Title": project.name,
|
||||
"Implementation-Version": version,
|
||||
"Implementation-Timestamp": new Date())
|
||||
}
|
||||
}
|
||||
baseName = project.name
|
||||
version = version
|
||||
archiveName = 'CampOrganizer2.war'
|
||||
}
|
||||
|
||||
@ -54,11 +54,10 @@ dependencies {
|
||||
|
||||
implementation 'net.sf.biweekly:biweekly:0.6.6'
|
||||
|
||||
implementation 'org.keycloak:keycloak-spring-boot-starter'
|
||||
|
||||
// for using the keycloak rest interface
|
||||
implementation 'org.keycloak:keycloak-admin-client:21.1.1'
|
||||
implementation 'org.jboss.resteasy:resteasy-client:5.0.0.Final'
|
||||
implementation 'org.keycloak:keycloak-server-spi:22.0.1'
|
||||
implementation 'org.keycloak:keycloak-admin-client:22.0.0'
|
||||
implementation 'org.jboss.resteasy:resteasy-client:6.2.4.Final'
|
||||
|
||||
// backward compatibility until the complete registration is converted to keycloak
|
||||
implementation 'org.jasypt:jasypt:1.9.3'
|
||||
@ -72,19 +71,27 @@ dependencies {
|
||||
|
||||
implementation 'org.springframework.boot:spring-boot-starter-jooq'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-security'
|
||||
implementation "org.springframework.boot:spring-boot-starter-oauth2-client"
|
||||
implementation 'org.springframework.security:spring-security-oauth2-authorization-server:1.1.1'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-web'
|
||||
implementation 'org.springframework.boot:spring-boot-starter-validation'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
|
||||
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
|
||||
implementation 'de.jottyfan:COJooq:2023.03'
|
||||
implementation 'nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect:3.0.0'
|
||||
|
||||
implementation 'commons-io:commons-io:2.13.0'
|
||||
|
||||
runtimeOnly 'org.springframework.boot:spring-boot-starter-tomcat'
|
||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
||||
testImplementation 'org.springframework.security:spring-security-test'
|
||||
}
|
||||
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "org.keycloak.bom:keycloak-adapter-bom:${keycloakVersion}"
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
// add version to manifest
|
||||
springBoot {
|
||||
buildInfo()
|
||||
}
|
||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
57
gradlew
vendored
57
gradlew
vendored
@ -1,21 +1,5 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
@ -44,7 +28,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
DEFAULT_JVM_OPTS=""
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
@ -72,7 +56,7 @@ case "`uname`" in
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MSYS* | MINGW* )
|
||||
MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
@ -82,7 +66,6 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@ -126,11 +109,10 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
@ -156,19 +138,19 @@ if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@ -177,9 +159,14 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
APP_ARGS=$(save "$@")
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
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"
|
||||
|
||||
# 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
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
@ -0,0 +1,78 @@
|
||||
package de.jottyfan.camporganizer.config;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2UserAuthority;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
public class AuthorizationConfiguration {
|
||||
|
||||
private static final String REALM_ACCESS_CLAIM = "realm_access";
|
||||
private static final String ROLES_CLAIM = "roles";
|
||||
private static final String RESOURCE_ACCESS_CLAIM = "resource_access";
|
||||
|
||||
@Value("${spring.security.oauth2.client.registration.keycloak.client-id}")
|
||||
private String clientId;
|
||||
|
||||
@Bean
|
||||
GrantedAuthoritiesMapper userAuthoritiesMapperForKeycloak() {
|
||||
return authorities -> {
|
||||
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
||||
var authority = authorities.iterator().next();
|
||||
boolean isOidc = authority instanceof OidcUserAuthority;
|
||||
|
||||
if (isOidc) {
|
||||
var oidcUserAuthority = (OidcUserAuthority) authority;
|
||||
var userInfo = oidcUserAuthority.getUserInfo();
|
||||
|
||||
if (userInfo.hasClaim(REALM_ACCESS_CLAIM)) {
|
||||
var realmAccess = userInfo.getClaimAsMap(REALM_ACCESS_CLAIM);
|
||||
@SuppressWarnings("unchecked")
|
||||
var roles = (Collection<String>) realmAccess.get(ROLES_CLAIM);
|
||||
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
|
||||
}
|
||||
if (userInfo.hasClaim(RESOURCE_ACCESS_CLAIM)) {
|
||||
var resourceAccess = userInfo.getClaimAsMap(RESOURCE_ACCESS_CLAIM);
|
||||
if (resourceAccess.containsKey(clientId)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var roles = (Collection<String>) ((Map<?, ?>) resourceAccess.get(clientId)).get(ROLES_CLAIM);
|
||||
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var oauth2UserAuthority = (OAuth2UserAuthority) authority;
|
||||
Map<String, Object> userAttributes = oauth2UserAuthority.getAttributes();
|
||||
|
||||
if (userAttributes.containsKey(REALM_ACCESS_CLAIM)) {
|
||||
@SuppressWarnings("unchecked")
|
||||
var realmAccess = (Map<String, Object>) userAttributes.get(REALM_ACCESS_CLAIM);
|
||||
@SuppressWarnings("unchecked")
|
||||
var roles = (Collection<String>) realmAccess.get(ROLES_CLAIM);
|
||||
mappedAuthorities.addAll(generateAuthoritiesFromClaim(roles));
|
||||
}
|
||||
}
|
||||
|
||||
return mappedAuthorities;
|
||||
};
|
||||
}
|
||||
|
||||
private Collection<GrantedAuthority> generateAuthoritiesFromClaim(Collection<String> roles) {
|
||||
return roles.stream().map(role -> new SimpleGrantedAuthority("ROLE_" + role)).collect(Collectors.toList());
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
package de.jottyfan.camporganizer.config;
|
||||
|
||||
import org.keycloak.adapters.springboot.KeycloakSpringBootConfigResolver;
|
||||
import org.keycloak.adapters.springsecurity.KeycloakConfiguration;
|
||||
import org.keycloak.adapters.springsecurity.authentication.KeycloakAuthenticationProvider;
|
||||
import org.keycloak.adapters.springsecurity.config.KeycloakWebSecurityConfigurerAdapter;
|
||||
import org.keycloak.adapters.springsecurity.management.HttpSessionManager;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.core.authority.mapping.SimpleAuthorityMapper;
|
||||
import org.springframework.security.core.session.SessionRegistryImpl;
|
||||
import org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@KeycloakConfiguration
|
||||
@ComponentScan(basePackageClasses = KeycloakSpringBootConfigResolver.class)
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true, jsr250Enabled = true)
|
||||
public class SecurityConfig extends KeycloakWebSecurityConfigurerAdapter {
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
KeycloakAuthenticationProvider keycloakAuthenticationProvider = keycloakAuthenticationProvider();
|
||||
keycloakAuthenticationProvider.setGrantedAuthoritiesMapper(new SimpleAuthorityMapper());
|
||||
auth.authenticationProvider(keycloakAuthenticationProvider);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KeycloakSpringBootConfigResolver KeycloakConfigResolver() {
|
||||
return new KeycloakSpringBootConfigResolver();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
@ConditionalOnMissingBean(HttpSessionManager.class)
|
||||
protected HttpSessionManager httpSessionManager() {
|
||||
return new HttpSessionManager();
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
||||
return new RegisterSessionAuthenticationStrategy(new SessionRegistryImpl());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
super.configure(http);
|
||||
http.authorizeRequests()
|
||||
// @formatter:off
|
||||
.antMatchers("/dashboard/**", "/business/**", "/confirmation/**").authenticated()
|
||||
.anyRequest().permitAll();
|
||||
// @formatter:on
|
||||
// http.anonymous().disable();
|
||||
http.csrf().disable();
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
package de.jottyfan.camporganizer.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.Customizer;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.oauth2.client.oidc.web.logout.OidcClientInitiatedLogoutSuccessHandler;
|
||||
import org.springframework.security.oauth2.client.registration.InMemoryClientRegistrationRepository;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy;
|
||||
import org.springframework.security.web.authentication.session.SessionAuthenticationStrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Configuration
|
||||
@EnableWebSecurity
|
||||
@EnableMethodSecurity
|
||||
public class SecurityConfiguration {
|
||||
|
||||
@Bean
|
||||
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
|
||||
return new NullAuthenticatedSessionStrategy();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain securityFilterChain(HttpSecurity sec, InMemoryClientRegistrationRepository crr)
|
||||
throws Exception {
|
||||
sec.csrf(o -> o.disable()).anonymous(o -> o.disable())
|
||||
// @formatter:off
|
||||
.oauth2Login(o -> o.defaultSuccessUrl("/"))
|
||||
.logout(o -> o.logoutSuccessHandler(new OidcClientInitiatedLogoutSuccessHandler(crr)))
|
||||
.authorizeHttpRequests(o -> o.requestMatchers("/dashboard/**", "/business/**", "/confirmation/**", "/userlogin/**").authenticated()
|
||||
.anyRequest().permitAll())
|
||||
.oauth2ResourceServer(o -> o.jwt(Customizer.withDefaults()))
|
||||
.sessionManagement(o -> o.init(sec));
|
||||
// @formatter:on
|
||||
return sec.build();
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.validation.Valid;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -17,8 +16,13 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
|
||||
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import de.jottyfan.camporganizer.module.mail.MailBean;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -37,10 +41,10 @@ public class AdminController extends CommonController {
|
||||
private String from;
|
||||
|
||||
@GetMapping("/admin/mail")
|
||||
public String getMail(Model model, HttpServletRequest request) {
|
||||
public String getMail(Model model, Principal principal) {
|
||||
MailBean mailBean = new MailBean();
|
||||
mailBean.setFrom(from);
|
||||
mailBean.getTo().add(getCurrentEmail(request));
|
||||
mailBean.getTo().add(getCurrentEmail(principal));
|
||||
model.addAttribute("bean", mailBean);
|
||||
return "/admin/mail";
|
||||
}
|
||||
|
@ -0,0 +1,125 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import jakarta.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.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampProfileBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
public class AdminPrivilegesController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private AdminPrivilegesService service;
|
||||
|
||||
@GetMapping("/admin/privileges/userbased")
|
||||
public String getUserbased(Model model) {
|
||||
model.addAttribute("list", service.getProfiles());
|
||||
return "/admin/privileges/userbased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/rolebased")
|
||||
public String getRolebased(Model model) {
|
||||
model.addAttribute("list", service.getAllModules());
|
||||
return "/admin/privileges/rolebased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/campbased")
|
||||
public String getCampbased(Model model) {
|
||||
model.addAttribute("list", service.getAllCamps());
|
||||
return "/admin/privileges/campbased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/rolebased/{role}")
|
||||
public String getRolebased(@PathVariable String role, Model model) {
|
||||
model.addAttribute("list", service.getAllModules());
|
||||
model.addAttribute("selected", role);
|
||||
model.addAttribute("container", service.getPersonCampMappingByModule(EnumModule.valueOf(role)));
|
||||
model.addAttribute("pagedest", "_admin_privileges_rolebased_" + role);
|
||||
return "/admin/privileges/rolebased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/campbased/{campid}")
|
||||
public String getCampbased(@PathVariable Integer campid, Model model) {
|
||||
List<CampBean> list = service.getAllCamps();
|
||||
model.addAttribute("list", list);
|
||||
String campname = "?";
|
||||
for (CampBean p : list) {
|
||||
if (p.getPk().equals(campid)) {
|
||||
campname = p.getFullname();
|
||||
}
|
||||
}
|
||||
model.addAttribute("selected", campname);
|
||||
model.addAttribute("container", service.getPersonModuleMappingByCamp(campid));
|
||||
model.addAttribute("pagedest", "_admin_privileges_campbased_" + campid);
|
||||
return "/admin/privileges/campbased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/userbased/{userid}")
|
||||
public String getUserbased(@PathVariable Integer userid, Model model) {
|
||||
List<ProfileBean> list = service.getProfiles();
|
||||
model.addAttribute("list", list);
|
||||
String selected = "?";
|
||||
for (ProfileBean p : list) {
|
||||
if (p.getPk().equals(userid)) {
|
||||
selected = p.getFullname();
|
||||
}
|
||||
}
|
||||
model.addAttribute("selected", selected);
|
||||
model.addAttribute("container", service.getModuleCampMappingByPerson(userid));
|
||||
model.addAttribute("pagedest", "_admin_privileges_userbased_" + userid);
|
||||
return "/admin/privileges/userbased";
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/delete/{id}/{pagedest}")
|
||||
public String deleteFromCampProfile(@PathVariable Integer id, @PathVariable String pagedest) {
|
||||
service.deleteFromCampProfile(id);
|
||||
return "redirect:" + pagedest.replace("_", "/");
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/add/{pagedest}")
|
||||
public String prepareAdd(Model model, @PathVariable String pagedest) {
|
||||
model.addAttribute("pagedest", pagedest);
|
||||
model.addAttribute("bean", new CampProfileBean());
|
||||
model.addAttribute("profiles", service.getProfiles());
|
||||
model.addAttribute("camps", service.getAllCamps());
|
||||
model.addAttribute("modules", service.getAllModules());
|
||||
return "/admin/privileges/add";
|
||||
}
|
||||
|
||||
@PostMapping("/admin/privileges/insert/{pagedest}")
|
||||
public String insertCampProfile(@Valid @ModelAttribute("bean") CampProfileBean bean, final BindingResult bindingResult, @PathVariable String pagedest, Model model) {
|
||||
if (bindingResult.hasErrors()) {
|
||||
model.addAttribute("pagedest", pagedest);
|
||||
model.addAttribute("profiles", service.getProfiles());
|
||||
model.addAttribute("camps", service.getAllCamps());
|
||||
model.addAttribute("modules", service.getAllModules());
|
||||
return "/admin/privileges/add";
|
||||
}
|
||||
service.insertIntoCampProfile(bean);
|
||||
return "redirect:" + pagedest.replace("_", "/");
|
||||
}
|
||||
|
||||
@GetMapping("/admin/privileges/abortinsert/{pagedest}")
|
||||
public String abortInsert(@PathVariable String pagedest) {
|
||||
return "redirect:" + pagedest.replace("_", "/");
|
||||
}
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampProfileBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.PrivilegesContainerBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class AdminPrivilegesService {
|
||||
|
||||
@Autowired
|
||||
private AdminRepository adminRepository;
|
||||
|
||||
/**
|
||||
* get all camp beans from the database
|
||||
*
|
||||
* @return all camp beans; an empty list at least
|
||||
*/
|
||||
public List<CampBean> getAllCamps() {
|
||||
return adminRepository.getAllCamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* get all profiles from the db
|
||||
*
|
||||
* @return the profiles
|
||||
*/
|
||||
public List<ProfileBean> getProfiles() {
|
||||
return adminRepository.getProfiles();
|
||||
}
|
||||
|
||||
/**
|
||||
* get all roles
|
||||
*
|
||||
* @return all roles
|
||||
*/
|
||||
public List<String> getAllModules() {
|
||||
return adminRepository.getAllModules();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected module
|
||||
*
|
||||
* @param module the module
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getPersonCampMappingByModule(EnumModule module) {
|
||||
return adminRepository.getPersonCampMappingByModule(module);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected camp
|
||||
*
|
||||
* @param camp the camp ID
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getPersonModuleMappingByCamp(Integer camp) {
|
||||
return adminRepository.getPersonModuleMappingByCamp(camp);
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected user
|
||||
*
|
||||
* @param user the user ID
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getModuleCampMappingByPerson(Integer user) {
|
||||
return adminRepository.getModuleCampMappingByPerson(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* delete from camp profile
|
||||
*
|
||||
* @param id the ID
|
||||
*/
|
||||
public void deleteFromCampProfile(Integer id) {
|
||||
adminRepository.deleteFromCampProfile(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* add the camp profile to the database
|
||||
*
|
||||
* @param bean the bean
|
||||
*/
|
||||
public void insertIntoCampProfile(CampProfileBean bean) {
|
||||
EnumModule m = bean.getModule() == null ? null : EnumModule.valueOf(bean.getModule());
|
||||
adminRepository.addToCampProfile(bean.getFkCamp(), bean.getFkProfile(), m);
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENTROLE;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
|
||||
@ -15,7 +16,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -31,6 +32,7 @@ import org.jooq.Record4;
|
||||
import org.jooq.Record5;
|
||||
import org.jooq.SelectConditionStep;
|
||||
import org.jooq.SelectSeekStep1;
|
||||
import org.jooq.SelectSeekStep2;
|
||||
import org.jooq.SelectWhereStep;
|
||||
import org.jooq.UpdateConditionStep;
|
||||
import org.jooq.UpdateSetMoreStep;
|
||||
@ -43,13 +45,21 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TCampprofileRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TDocumentroleRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TLocationRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TProfileRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.IntKeyValueBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.PrivilegesContainerBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -482,4 +492,160 @@ public class AdminRepository {
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* get all modules
|
||||
*
|
||||
* @return all modules
|
||||
*/
|
||||
public List<String> getAllModules() {
|
||||
List<String> list = new ArrayList<>();
|
||||
for (EnumModule r : EnumModule.values()) {
|
||||
list.add(r.getLiteral());
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected module
|
||||
*
|
||||
* @param module the module
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getPersonCampMappingByModule(EnumModule module) {
|
||||
SelectSeekStep2<Record4<Integer, String, LocalDateTime, String>, LocalDateTime, Integer> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_CAMPPROFILE.PK,
|
||||
T_CAMP.NAME,
|
||||
T_CAMP.ARRIVE,
|
||||
T_PROFILE.FORENAME.concat(" ").concat(T_PROFILE.SURNAME).as(T_PROFILE.USERNAME))
|
||||
.from(T_CAMPPROFILE)
|
||||
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
|
||||
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
|
||||
.where(T_CAMPPROFILE.MODULE.eq(module))
|
||||
.orderBy(T_CAMP.ARRIVE, T_PROFILE.PK);
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
|
||||
for (Record4<Integer, String, LocalDateTime, String> r : sql.fetch()) {
|
||||
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
|
||||
String username = r.get(T_PROFILE.USERNAME);
|
||||
String campname = r.get(T_CAMP.NAME);
|
||||
LocalDateTime ldt = r.get(T_CAMP.ARRIVE);
|
||||
String year = ldt != null ? String.valueOf(ldt.getYear()) : "?";
|
||||
campname = campname == null ? year : campname.concat(" ").concat(year);
|
||||
if (pcb.get(username) == null) {
|
||||
pcb.addKey(username);
|
||||
}
|
||||
pcb.add(username, IntKeyValueBean.of(fkCampProfile, campname));
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected user
|
||||
*
|
||||
* @param user the user ID
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getModuleCampMappingByPerson(Integer user) {
|
||||
SelectSeekStep1<Record4<Integer, String, LocalDateTime, EnumModule>, LocalDateTime> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_CAMPPROFILE.PK,
|
||||
T_CAMP.NAME,
|
||||
T_CAMP.ARRIVE,
|
||||
T_CAMPPROFILE.MODULE)
|
||||
.from(T_CAMPPROFILE)
|
||||
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
|
||||
.where(T_CAMPPROFILE.FK_PROFILE.eq(user))
|
||||
.orderBy(T_CAMP.ARRIVE);
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
|
||||
for (Record4<Integer, String, LocalDateTime, EnumModule> r : sql.fetch()) {
|
||||
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
|
||||
EnumModule moduleEnum = r.get(T_CAMPPROFILE.MODULE);
|
||||
String module = moduleEnum == null ? null : moduleEnum.getLiteral();
|
||||
String campname = r.get(T_CAMP.NAME);
|
||||
LocalDateTime ldt = r.get(T_CAMP.ARRIVE);
|
||||
String year = ldt != null ? String.valueOf(ldt.getYear()) : "?";
|
||||
campname = campname == null ? year : campname.concat(" ").concat(year);
|
||||
if (pcb.get(module) == null) {
|
||||
pcb.addKey(module);
|
||||
}
|
||||
pcb.add(module, IntKeyValueBean.of(fkCampProfile, campname));
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the mapping that contains the form bean for a selected camp
|
||||
*
|
||||
* @param camp the camp ID
|
||||
* @return the container
|
||||
*/
|
||||
public PrivilegesContainerBean getPersonModuleMappingByCamp(Integer camp) {
|
||||
SelectSeekStep2<Record4<Integer, String, String, EnumModule>, String, String> sql = jooq
|
||||
// @formatter:off
|
||||
.select(T_CAMPPROFILE.PK,
|
||||
T_PROFILE.FORENAME,
|
||||
T_PROFILE.SURNAME,
|
||||
T_CAMPPROFILE.MODULE)
|
||||
.from(T_CAMPPROFILE)
|
||||
.leftJoin(T_CAMP).on(T_CAMP.PK.eq(T_CAMPPROFILE.FK_CAMP))
|
||||
.leftJoin(T_PROFILE).on(T_PROFILE.PK.eq(T_CAMPPROFILE.FK_PROFILE))
|
||||
.where(T_CAMPPROFILE.FK_CAMP.eq(camp))
|
||||
.orderBy(T_PROFILE.SURNAME, T_PROFILE.FORENAME);
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
PrivilegesContainerBean pcb = new PrivilegesContainerBean();
|
||||
for (Record4<Integer, String, String, EnumModule> r : sql.fetch()) {
|
||||
Integer fkCampProfile = r.get(T_CAMPPROFILE.PK);
|
||||
EnumModule moduleEnum = r.get(T_CAMPPROFILE.MODULE);
|
||||
String forename = r.get(T_PROFILE.FORENAME);
|
||||
String surname = r.get(T_PROFILE.SURNAME);
|
||||
String person = new StringBuilder().append(forename).append(" ").append(surname).toString();
|
||||
String module = moduleEnum == null ? null : moduleEnum.getLiteral();
|
||||
if (pcb.get(person) == null) {
|
||||
pcb.addKey(person);
|
||||
}
|
||||
pcb.add(person, IntKeyValueBean.of(fkCampProfile, module));
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/**
|
||||
* delete entry from camp profile
|
||||
*
|
||||
* @param id the pk
|
||||
*/
|
||||
public void deleteFromCampProfile(Integer id) {
|
||||
DeleteConditionStep<TCampprofileRecord> sql = jooq.deleteFrom(T_CAMPPROFILE).where(T_CAMPPROFILE.PK.eq(id));
|
||||
LOGGER.debug(sql.toString());
|
||||
sql.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* add entry to database
|
||||
*
|
||||
* @param fkCamp the camp ID
|
||||
* @param fkProfile the profile ID
|
||||
* @param module the module
|
||||
*/
|
||||
public void addToCampProfile(Integer fkCamp, Integer fkProfile, EnumModule module) {
|
||||
InsertReturningStep<TCampprofileRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.insertInto(T_CAMPPROFILE,
|
||||
T_CAMPPROFILE.FK_CAMP,
|
||||
T_CAMPPROFILE.FK_PROFILE,
|
||||
T_CAMPPROFILE.MODULE)
|
||||
.values(fkCamp, fkProfile, module)
|
||||
.onConflict(T_CAMPPROFILE.FK_CAMP,
|
||||
T_CAMPPROFILE.FK_PROFILE,
|
||||
T_CAMPPROFILE.MODULE)
|
||||
.doNothing();
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql.toString());
|
||||
sql.execute();
|
||||
}
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ import static de.jottyfan.camporganizer.db.jooq.Tables.T_DOCUMENT;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -13,6 +13,10 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
|
||||
import de.jottyfan.camporganizer.module.admin.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.DocumentBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.LocationBean;
|
||||
import de.jottyfan.camporganizer.module.admin.model.ProfileBean;
|
||||
import de.jottyfan.camporganizer.module.mail.MailBean;
|
||||
import de.jottyfan.camporganizer.module.mail.MailRepository;
|
||||
|
||||
|
@ -1,13 +1,14 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
@ -73,6 +74,10 @@ public class CampBean implements Serializable {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public String getFullname() {
|
||||
return new StringBuilder().append(name).append(" ").append(arrive == null ? "?" : arrive.format(DateTimeFormatter.ofPattern("yyyy"))).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pk
|
||||
*/
|
@ -0,0 +1,80 @@
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public class CampProfileBean implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer pk;
|
||||
|
||||
@NotNull
|
||||
private Integer fkCamp;
|
||||
@NotNull
|
||||
private Integer fkProfile;
|
||||
@NotBlank
|
||||
private String module;
|
||||
|
||||
/**
|
||||
* @return the pk
|
||||
*/
|
||||
public Integer getPk() {
|
||||
return pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pk the pk to set
|
||||
*/
|
||||
public void setPk(Integer pk) {
|
||||
this.pk = pk;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fkCamp
|
||||
*/
|
||||
public Integer getFkCamp() {
|
||||
return fkCamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fkCamp the fkCamp to set
|
||||
*/
|
||||
public void setFkCamp(Integer fkCamp) {
|
||||
this.fkCamp = fkCamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the fkProfile
|
||||
*/
|
||||
public Integer getFkProfile() {
|
||||
return fkProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param fkProfile the fkProfile to set
|
||||
*/
|
||||
public void setFkProfile(Integer fkProfile) {
|
||||
this.fkProfile = fkProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the module
|
||||
*/
|
||||
public String getModule() {
|
||||
return module;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param module the module to set
|
||||
*/
|
||||
public void setModule(String module) {
|
||||
this.module = module;
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
@ -0,0 +1,50 @@
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public class IntKeyValueBean implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Integer key;
|
||||
private String value;
|
||||
|
||||
public static final IntKeyValueBean of(Integer key, String value) {
|
||||
IntKeyValueBean bean = new IntKeyValueBean();
|
||||
bean.setKey(key);
|
||||
bean.setValue(value);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the key
|
||||
*/
|
||||
public Integer getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key the key to set
|
||||
*/
|
||||
public void setKey(Integer key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the value
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value the value to set
|
||||
*/
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TLocationRecord;
|
||||
|
@ -0,0 +1,62 @@
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public class PrivilegesContainerBean implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private Map<String, List<IntKeyValueBean>> map;
|
||||
|
||||
public PrivilegesContainerBean() {
|
||||
map = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* get the content of key
|
||||
*
|
||||
* @param key the key
|
||||
* @return the value
|
||||
*/
|
||||
public List<IntKeyValueBean> get(String key) {
|
||||
return map == null ? null : map.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* add the value to the key
|
||||
*
|
||||
* @param key the key
|
||||
* @param value the value
|
||||
*/
|
||||
public void add(String key, IntKeyValueBean value) {
|
||||
if (get(key) != null) {
|
||||
map.get(key).add(value);
|
||||
} else {
|
||||
throw new NullPointerException("key not found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* add the key to this map
|
||||
*
|
||||
* @param key
|
||||
*/
|
||||
public void addKey(String key) {
|
||||
map.put(key, new ArrayList<>());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the map
|
||||
*/
|
||||
public Map<String, List<IntKeyValueBean>> getMap() {
|
||||
return map;
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.admin;
|
||||
package de.jottyfan.camporganizer.module.admin.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
@ -27,6 +27,10 @@ public class ProfileBean implements Serializable {
|
||||
return bean;
|
||||
}
|
||||
|
||||
public String getFullname() {
|
||||
return new StringBuilder().append(forename).append(" ").append(surname).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pk
|
||||
*/
|
@ -1,6 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -13,8 +13,8 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.bookings.impl.AddPaymentBean;
|
||||
import de.jottyfan.camporganizer.module.business.bookings.impl.BookerBean;
|
||||
import de.jottyfan.camporganizer.module.business.bookings.model.AddPaymentBean;
|
||||
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
|
||||
/**
|
||||
@ -27,7 +27,7 @@ public class BookingsController extends CommonController {
|
||||
private static final Logger LOGGER = LogManager.getLogger(BookingsController.class);
|
||||
|
||||
@Autowired
|
||||
private IBookingsService bookingsService;
|
||||
private BookingsService bookingsService;
|
||||
|
||||
@GetMapping("/business/bookings")
|
||||
@RolesAllowed({"business_booking"})
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings.impl;
|
||||
package de.jottyfan.camporganizer.module.business.bookings;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
|
||||
@ -27,6 +27,7 @@ import de.jottyfan.camporganizer.db.EnumConverter;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,11 +1,11 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings.impl;
|
||||
package de.jottyfan.camporganizer.module.business.bookings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
|
||||
import de.jottyfan.camporganizer.module.business.bookings.model.BookerBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -13,24 +13,20 @@ import de.jottyfan.camporganizer.module.business.bookings.IBookingsService;
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class BookingsService implements IBookingsService {
|
||||
public class BookingsService {
|
||||
|
||||
@Autowired
|
||||
private BookingsRepository bookingsGateway;
|
||||
|
||||
@Override
|
||||
public List<BookerBean> getBookers(String username) {
|
||||
return bookingsGateway.getBookings(username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BookerBean getBooker(Integer id, String username) {
|
||||
return bookingsGateway.getBooking(id, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer addPayment(Integer id, Double payment) {
|
||||
return bookingsGateway.addPayment(id, payment);
|
||||
}
|
||||
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.bookings.impl.BookerBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public interface IBookingsService {
|
||||
/**
|
||||
* get the bookers information
|
||||
*
|
||||
* @param username the name of the user in this session
|
||||
* @return the list of bookers; an empty one at least
|
||||
*/
|
||||
public List<BookerBean> getBookers(String username);
|
||||
|
||||
/**
|
||||
* get the booker referenced by id
|
||||
*
|
||||
* @param id the ID of the booker
|
||||
* @param username the name of the user in this session
|
||||
* @return the booker if found; null otherwise
|
||||
*/
|
||||
public BookerBean getBooker(Integer id, String username);
|
||||
|
||||
/**
|
||||
* add payment to the paid values of user with id
|
||||
*
|
||||
* @param id the ID of the booker
|
||||
* @param payment the payment (additional value)
|
||||
* @return number of affected database rows, should be 1
|
||||
*/
|
||||
public Integer addPayment(Integer id, Double payment);
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings.impl;
|
||||
package de.jottyfan.camporganizer.module.business.bookings.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.bookings.impl;
|
||||
package de.jottyfan.camporganizer.module.business.bookings.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,7 +1,5 @@
|
||||
package de.jottyfan.camporganizer.module.business.business;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -18,15 +16,12 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
public class BusinessController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private IBusinessService indexService;
|
||||
private BusinessService service;
|
||||
|
||||
@GetMapping("/business")
|
||||
public String getIndex(Model model) {
|
||||
String username = indexService.getCurrentUser(request);
|
||||
model.addAttribute("campBudgets", indexService.getCampBudgets(username));
|
||||
String username = super.getCurrentUser();
|
||||
model.addAttribute("campBudgets", service.getCampBudgets(username));
|
||||
return "business/business";
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.business.impl;
|
||||
package de.jottyfan.camporganizer.module.business.business;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
|
||||
@ -25,6 +25,8 @@ import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TPersonRecord;
|
||||
import de.jottyfan.camporganizer.module.business.business.model.BusinessBean;
|
||||
import de.jottyfan.camporganizer.module.business.business.model.CampBudgetBean;
|
||||
|
||||
/**
|
||||
*
|
@ -0,0 +1,24 @@
|
||||
package de.jottyfan.camporganizer.module.business.business;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.business.model.CampBudgetBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class BusinessService {
|
||||
|
||||
@Autowired
|
||||
private BusinessRepository gateway;
|
||||
|
||||
public List<CampBudgetBean> getCampBudgets(String username) {
|
||||
return gateway.getCampBudgets(username);
|
||||
}
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.business.business;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.business.impl.CampBudgetBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public interface IBusinessService {
|
||||
/**
|
||||
* get the user of this session
|
||||
*
|
||||
* @param request the request
|
||||
* @return the username of the current user
|
||||
*/
|
||||
public String getCurrentUser(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get a list of all camp budgets of all years
|
||||
*
|
||||
* @param username the name of the current user in this session
|
||||
* @return the list; an empty one at least
|
||||
*/
|
||||
public List<CampBudgetBean> getCampBudgets(String username);
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.business.business.impl;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.business.IBusinessService;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class BusinessService implements IBusinessService {
|
||||
@Autowired
|
||||
private BusinessRepository gateway;
|
||||
|
||||
@Override
|
||||
public String getCurrentUser(HttpServletRequest request) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
|
||||
.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
if (ksc == null) {
|
||||
throw new DataAccessException("no keycloak user in session");
|
||||
}
|
||||
return ksc.getIdToken().getPreferredUsername();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CampBudgetBean> getCampBudgets(String username) {
|
||||
return gateway.getCampBudgets(username);
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.business.impl;
|
||||
package de.jottyfan.camporganizer.module.business.business.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.business.impl;
|
||||
package de.jottyfan.camporganizer.module.business.business.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,16 +1,13 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.business.IBusinessService;
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -21,18 +18,12 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
public class CampController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private IBusinessService indexService;
|
||||
|
||||
@Autowired
|
||||
private ICampService campService;
|
||||
private CampService campService;
|
||||
|
||||
@GetMapping("/business/camp/{id}")
|
||||
@RolesAllowed({ "business" })
|
||||
public String getCamp(Model model, @PathVariable Integer id) {
|
||||
String username = indexService.getCurrentUser(request);
|
||||
String username = super.getCurrentUser();
|
||||
model.addAttribute("currentUser", username);
|
||||
model.addAttribute("campId", id);
|
||||
model.addAttribute("camp", campService.getCamp(id, username));
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
|
||||
@ -25,6 +25,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import de.jottyfan.camporganizer.db.EnumConverter;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumSex;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.PersonBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
@ -6,7 +6,9 @@ import java.util.List;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.camp.ICampService;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.PersonBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -14,17 +16,15 @@ import de.jottyfan.camporganizer.module.business.camp.ICampService;
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class CampService implements ICampService {
|
||||
public class CampService {
|
||||
|
||||
@Autowired
|
||||
private CampRepository campGateway;
|
||||
|
||||
@Override
|
||||
public CampBean getCamp(Integer id, String username) {
|
||||
return campGateway.getCamp(id, username);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BookingBean getBookings(Integer id, String username) {
|
||||
Integer approved = 0;
|
||||
Integer open = 0;
|
||||
@ -49,9 +49,7 @@ public class CampService implements ICampService {
|
||||
return bean;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<PersonBean> getBookers(Integer id, String username) {
|
||||
return campGateway.getBookings(id, username);
|
||||
}
|
||||
|
||||
}
|
@ -1,43 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.camp.impl.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.impl.CampBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.impl.PersonBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public interface ICampService {
|
||||
|
||||
/**
|
||||
* get the camp bean of id
|
||||
*
|
||||
* @param id the id of the camp
|
||||
* @param username the name of the user in this session
|
||||
* @return the camp bean if found; null otherwise
|
||||
*/
|
||||
public CampBean getCamp(Integer id, String username);
|
||||
|
||||
/**
|
||||
* get the booking information for camp with id
|
||||
*
|
||||
* @param id the id of the camp
|
||||
* @param username the name of the user in this session
|
||||
* @return a booking bean
|
||||
*/
|
||||
public BookingBean getBookings(Integer id, String username);
|
||||
|
||||
/**
|
||||
* get the bookers information for camp with id
|
||||
*
|
||||
* @param id the id of the camp
|
||||
* @param username the name of the user in this session
|
||||
* @return the list of bookers; an empty one at least
|
||||
*/
|
||||
public List<PersonBean> getBookers(Integer id, String username);
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,11 +1,11 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import de.jottyfan.camporganizer.module.business.privileges.impl.ProfileBean;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.camp.impl;
|
||||
package de.jottyfan.camporganizer.module.business.camp.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
@ -1,9 +1,5 @@
|
||||
package de.jottyfan.camporganizer.module.business.privileges;
|
||||
|
||||
import javax.annotation.security.RolesAllowed;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -12,10 +8,10 @@ import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.module.business.business.IBusinessService;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesBean;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.impl.PrivilegesService;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.PrivilegesBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import jakarta.annotation.security.RolesAllowed;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -25,19 +21,13 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
@Controller
|
||||
public class PrivilegesController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private PrivilegesService privilegesService;
|
||||
|
||||
@Autowired
|
||||
private IBusinessService indexService;
|
||||
|
||||
@GetMapping("/business/privileges")
|
||||
@RolesAllowed({ "admin" })
|
||||
public String getIndex(Model model) {
|
||||
String username = indexService.getCurrentUser(request);
|
||||
String username = super.getCurrentUser();
|
||||
model.addAttribute("currentUser", username);
|
||||
model.addAttribute("privileges", privilegesService.getPrivileges());
|
||||
model.addAttribute("profiles", privilegesService.getProfiles(EnumCamprole.director, EnumCamprole.teacher));
|
||||
@ -59,7 +49,7 @@ public class PrivilegesController extends CommonController {
|
||||
PrivilegesBean bean = new PrivilegesBean();
|
||||
bean.setFkCamp(fkCamp);
|
||||
bean.setFkProfile(fkProfile);
|
||||
privilegesService.remove(bean, indexService.getCurrentUser(request));
|
||||
privilegesService.remove(bean, super.getCurrentUser());
|
||||
return getIndex(model);
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.privileges.impl;
|
||||
package de.jottyfan.camporganizer.module.business.privileges;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PERSON;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_PROFILE;
|
||||
@ -24,6 +24,8 @@ import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.TSalesprofileRecord;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.PrivilegesBean;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.privileges.impl;
|
||||
package de.jottyfan.camporganizer.module.business.privileges;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@ -10,7 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.module.business.camp.impl.CampBean;
|
||||
import de.jottyfan.camporganizer.module.business.camp.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.PrivilegesBean;
|
||||
import de.jottyfan.camporganizer.module.business.privileges.model.ProfileBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.privileges.impl;
|
||||
package de.jottyfan.camporganizer.module.business.privileges.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.business.privileges.impl;
|
||||
package de.jottyfan.camporganizer.module.business.privileges.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
@ -1,7 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -12,7 +11,9 @@ import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.module.registration.KeycloakRepository;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -23,26 +24,19 @@ import de.jottyfan.camporganizer.module.registration.KeycloakRepository;
|
||||
public class CamplistController extends CommonController {
|
||||
private static final Logger LOGGER = LogManager.getLogger(CamplistController.class);
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private KeycloakRepository keycloak;
|
||||
|
||||
@Autowired
|
||||
private CamplistService service;
|
||||
|
||||
@GetMapping("/camplist")
|
||||
public String index(Model model) {
|
||||
public String index(Model model, Principal principal) {
|
||||
model.addAttribute("camps", service.getAllCamps(true));
|
||||
return super.isLoggedIn(request) ? dashboard(model) : "/camplist";
|
||||
return super.isLoggedIn(principal) ? dashboard(model) : "/camplist";
|
||||
}
|
||||
|
||||
@GetMapping("/dashboard")
|
||||
public String dashboard(Model model) {
|
||||
model.addAttribute("mybookings", service.getBookingsOf(super.getCurrentUser(request)));
|
||||
model.addAttribute("mybookings", service.getBookingsOf(super.getCurrentUser()));
|
||||
model.addAttribute("bookingBean", new BookingBean());
|
||||
model.addAttribute("keycloakProfileUrl", keycloak.getUserClientUrl());
|
||||
model.addAttribute("camps", service.getAllCamps(true));
|
||||
return "/dashboard";
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import org.jooq.Record2;
|
||||
import org.jooq.SelectOrderByStep;
|
||||
import org.jooq.SelectSeekStep1;
|
||||
import org.jooq.SelectSeekStep2;
|
||||
import org.jooq.impl.DSL;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -34,6 +35,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumDocument;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.TProfile;
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.DocumentBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -91,7 +94,7 @@ public class CamplistGateway {
|
||||
.leftJoin(T_PERSON).on(T_PERSON.FK_PROFILE.eq(T_PROFILE.PK))
|
||||
.leftJoin(REGISTRATOR).on(REGISTRATOR.PK.eq(T_PERSON.FK_REGISTRATOR))
|
||||
.leftJoin(V_CAMP).on(V_CAMP.PK.eq(T_PERSON.FK_CAMP))
|
||||
.where(T_PROFILE.USERNAME.eq(username))
|
||||
.where(DSL.trim(T_PROFILE.USERNAME).eq(username == null ? null : username.trim()))
|
||||
.and(T_PERSON.PK.isNotNull())
|
||||
.orderBy(V_CAMP.ARRIVE.desc(), T_PERSON.CREATED);
|
||||
// @formatter:on
|
||||
|
@ -13,6 +13,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.tables.records.VCampRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.dashboard.DashboardRepository;
|
||||
|
||||
/**
|
||||
|
@ -1,57 +1,87 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.security.Principal;
|
||||
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.user.OAuth2User;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
|
||||
import de.jottyfan.camporganizer.module.registration.KeycloakRepository;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public abstract class CommonController {
|
||||
private static final Logger LOGGER = LogManager.getLogger();
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
private KeycloakRepository keycloak;
|
||||
|
||||
/**
|
||||
* try to get current keycloak user
|
||||
*
|
||||
* @param request the request
|
||||
* @param principal the principal
|
||||
* @return the preferred username or null
|
||||
*/
|
||||
public String getCurrentUser(HttpServletRequest request) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
|
||||
.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
return ksc == null ? null : ksc.getIdToken().getPreferredUsername();
|
||||
public String getCurrentUser(Principal principal) {
|
||||
return principal == null ? null : principal.getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* try to get th currnt keycloak email
|
||||
*
|
||||
* @param request the request
|
||||
* @param principal the principal
|
||||
* @return the email or null
|
||||
*/
|
||||
public String getCurrentEmail(HttpServletRequest request) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
|
||||
.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
return ksc == null ? null : ksc.getIdToken().getEmail();
|
||||
public String getCurrentEmail(Principal principal) {
|
||||
if (principal instanceof OAuth2AuthenticationToken) {
|
||||
OAuth2AuthenticationToken token = (OAuth2AuthenticationToken) principal;
|
||||
if (token != null) {
|
||||
OAuth2User user = token.getPrincipal();
|
||||
if (user != null) {
|
||||
return user.getAttribute("email");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("could not find email for {}", principal);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ModelAttribute("currentUser")
|
||||
public String getCurrentUser() {
|
||||
return getCurrentUser(request);
|
||||
SecurityContext context = SecurityContextHolder.getContext();
|
||||
if (context != null) {
|
||||
Authentication authentication = context.getAuthentication();
|
||||
if (authentication != null) {
|
||||
DefaultOidcUser dou = (DefaultOidcUser) authentication.getPrincipal();
|
||||
return dou == null ? null : dou.getName();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@ModelAttribute("keycloakProfileUrl")
|
||||
public String getKeycloakProfileUrl() {
|
||||
return keycloak.getUserClientUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the user has a valid keycloak session token
|
||||
*
|
||||
* @param request the request
|
||||
* @param principal the principal
|
||||
* @return true or false
|
||||
*/
|
||||
public boolean isLoggedIn(HttpServletRequest request) {
|
||||
return getCurrentUser(request) != null;
|
||||
public boolean isLoggedIn(Principal principal) {
|
||||
return getCurrentUser(principal) != null;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
package de.jottyfan.camporganizer.module.camplist.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
package de.jottyfan.camporganizer.module.camplist.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
package de.jottyfan.camporganizer.module.camplist.model;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.camplist;
|
||||
package de.jottyfan.camporganizer.module.camplist.model;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.info.BuildProperties;
|
@ -3,15 +3,13 @@ package de.jottyfan.camporganizer.module.confirmation.confirmation;
|
||||
import java.time.LocalDate;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverviewBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -22,14 +20,11 @@ import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverv
|
||||
public class ConfirmationController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private IConfirmationService indexService;
|
||||
private ConfirmationService indexService;
|
||||
|
||||
@GetMapping("/confirmation")
|
||||
public String getIndex(Model model) {
|
||||
List<CampOverviewBean> campoverview = indexService.getCampOverview(request);
|
||||
List<CampOverviewBean> campoverview = indexService.getCampOverview(super.getCurrentUser());
|
||||
CampOverviewBean campoverviewsummary = new CampOverviewBean(LocalDate.now(), "summary");
|
||||
for (CampOverviewBean bean : campoverview) {
|
||||
campoverviewsummary.setApproved(bean.getApproved() + campoverviewsummary.getApproved());
|
||||
@ -38,9 +33,9 @@ public class ConfirmationController extends CommonController {
|
||||
}
|
||||
model.addAttribute("campoverview", campoverview);
|
||||
model.addAttribute("campoverviewsummary", campoverviewsummary);
|
||||
model.addAttribute("untouched", indexService.getUntouched(request));
|
||||
model.addAttribute("approved", indexService.getApproved(request));
|
||||
model.addAttribute("rejected", indexService.getRejected(request));
|
||||
model.addAttribute("untouched", indexService.getUntouched(super.getCurrentUser()));
|
||||
model.addAttribute("approved", indexService.getApproved(super.getCurrentUser()));
|
||||
model.addAttribute("rejected", indexService.getRejected(super.getCurrentUser()));
|
||||
return "confirmation/confirmation";
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
|
||||
@ -30,6 +30,8 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumCamprole;
|
||||
import de.jottyfan.camporganizer.db.jooq.enums.EnumModule;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
|
||||
|
||||
/**
|
||||
*
|
@ -1,15 +1,16 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.jooq.exception.DataAccessException;
|
||||
import org.keycloak.KeycloakSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationService;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.model.CampOverviewBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -17,45 +18,30 @@ import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationS
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class ConfirmationService implements IConfirmationService {
|
||||
public class ConfirmationService {
|
||||
@Autowired
|
||||
private ConfirmationRepository gateway;
|
||||
|
||||
@Override
|
||||
public String getCurrentUser(HttpServletRequest request) {
|
||||
KeycloakSecurityContext ksc = (KeycloakSecurityContext) request
|
||||
.getAttribute(KeycloakSecurityContext.class.getName());
|
||||
if (ksc == null) {
|
||||
throw new DataAccessException("no keycloak user in session");
|
||||
}
|
||||
return ksc.getIdToken().getPreferredUsername();
|
||||
public List<CampOverviewBean> getCampOverview(String currentUser) {
|
||||
return gateway.getCampOverviewBeans(currentUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<CampOverviewBean> getCampOverview(HttpServletRequest request) {
|
||||
return gateway.getCampOverviewBeans(getCurrentUser(request));
|
||||
public List<BookingBean> getUntouched(String currentUser) {
|
||||
return gateway.getUntouched(currentUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookingBean> getUntouched(HttpServletRequest request) {
|
||||
return gateway.getUntouched(getCurrentUser(request));
|
||||
public List<BookingBean> getApproved(String currentUser) {
|
||||
return gateway.getApproved(currentUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookingBean> getApproved(HttpServletRequest request) {
|
||||
return gateway.getApproved(getCurrentUser(request));
|
||||
public List<BookingBean> getRejected(String currentUser) {
|
||||
return gateway.getRejected(currentUser);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BookingBean> getRejected(HttpServletRequest request) {
|
||||
return gateway.getRejected(getCurrentUser(request));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String search(String needle, String linkURL, HttpServletRequest request) {
|
||||
public String search(String needle, String linkURL, String currentUser) {
|
||||
StringBuilder buf = new StringBuilder(
|
||||
"<table class=\"table table-striped\"><thead><tr><th>Dabei</th><th>Name</th><th>Freizeit</th><th>Rolle</th></tr><tbody>");
|
||||
for (BookingBean bean : gateway.getSearchResult(needle, getCurrentUser(request))) {
|
||||
for (BookingBean bean : gateway.getSearchResult(needle, currentUser)) {
|
||||
String acceptHtml = "";
|
||||
if (bean.getAccept() == null) {
|
||||
acceptHtml = "<i class=\"fas fa-question framed framed-orange\"></i>";
|
@ -1,65 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.impl.CampOverviewBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public interface IConfirmationService {
|
||||
/**
|
||||
* get the user of this session
|
||||
*
|
||||
* @param request the request
|
||||
* @return the username of the current user
|
||||
*/
|
||||
public String getCurrentUser(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get a list of the camps and its booking status
|
||||
*
|
||||
* @param request the request
|
||||
* @return the camp overview beans
|
||||
*/
|
||||
public List<CampOverviewBean> getCampOverview(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get a list of bookings that have not yet been worked on
|
||||
*
|
||||
* @param request the request
|
||||
* @return the list of untouched bookings
|
||||
*/
|
||||
public List<BookingBean> getUntouched(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get a list of approved bookings
|
||||
*
|
||||
* @param request the request
|
||||
* @return the list of approved bookings
|
||||
*/
|
||||
public List<BookingBean> getApproved(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get a list of rejected bookings
|
||||
*
|
||||
* @param request the request
|
||||
* @return the list of rejected bookings
|
||||
*/
|
||||
public List<BookingBean> getRejected(HttpServletRequest request);
|
||||
|
||||
/**
|
||||
* get the result of a search for needle in the database
|
||||
*
|
||||
* @param needle the needle; may be a name of anything
|
||||
* @param linkURL the URL of the link for clicking on the found entity
|
||||
* @param request the request
|
||||
* @return the result in html format (for now)
|
||||
*/
|
||||
public String search(String needle, String linkURL, HttpServletRequest request);
|
||||
}
|
@ -1,31 +1,32 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.websocket.server.PathParam;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.websocket.server.PathParam;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
@Controller
|
||||
public class SearchController {
|
||||
public class SearchController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private IConfirmationService service;
|
||||
private ConfirmationService service;
|
||||
|
||||
@GetMapping("/confirmation/search")
|
||||
@ResponseBody
|
||||
public String search(@PathParam(value = "needle") String needle, Model model) {
|
||||
return service.search(needle, request.getRequestURI().replace("search", "person"), request);
|
||||
return service.search(needle, request.getRequestURI().replace("search", "person"), super.getCurrentUser());
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.confirmation.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,7 +1,5 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.person;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
@ -11,9 +9,9 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.IConfirmationService;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonService;
|
||||
import de.jottyfan.camporganizer.module.confirmation.confirmation.ConfirmationService;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -23,18 +21,12 @@ import de.jottyfan.camporganizer.module.confirmation.person.impl.PersonService;
|
||||
@Controller
|
||||
public class PersonController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private HttpServletRequest request;
|
||||
|
||||
@Autowired
|
||||
private IConfirmationService confirmationService;
|
||||
|
||||
@Autowired
|
||||
private PersonService personService;
|
||||
|
||||
@GetMapping("/confirmation/person/{pk}")
|
||||
public String getIndex(Model model, @PathVariable Integer pk) {
|
||||
String username = confirmationService.getCurrentUser(request);
|
||||
String username = super.getCurrentUser();
|
||||
model.addAttribute("currentUser", username);
|
||||
model.addAttribute("person", personService.getPerson(username, pk));
|
||||
model.addAttribute("camps", personService.getCamps(username));
|
||||
@ -44,7 +36,7 @@ public class PersonController extends CommonController {
|
||||
|
||||
@PostMapping("/confirmation/person/update")
|
||||
public String doUpdate(@ModelAttribute PersonBean bean, Model model) {
|
||||
String username = confirmationService.getCurrentUser(request);
|
||||
String username = super.getCurrentUser();
|
||||
personService.updatePerson(bean, username);
|
||||
return "redirect:/confirmation";
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.person;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMPPROFILE;
|
||||
@ -36,7 +36,9 @@ 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.db.jooq.tables.records.TRssRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
|
||||
import de.jottyfan.camporganizer.module.mail.MailBean;
|
||||
import de.jottyfan.camporganizer.module.mail.MailRepository;
|
||||
|
@ -1,10 +1,13 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.person;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.confirmation.person.model.PersonBean;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.impl;
|
||||
package de.jottyfan.camporganizer.module.confirmation.person.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
@ -21,8 +21,8 @@ import de.jottyfan.camporganizer.db.jooq.enums.EnumFiletype;
|
||||
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.TRssRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -4,7 +4,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.servlet.http.Part;
|
||||
import jakarta.servlet.http.Part;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
@ -2,7 +2,7 @@ package de.jottyfan.camporganizer.module.document;
|
||||
|
||||
import java.util.Base64;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.io.ByteArrayResource;
|
||||
|
@ -2,7 +2,7 @@ package de.jottyfan.camporganizer.module.ical;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -19,7 +19,7 @@ import de.jottyfan.camporganizer.module.camplist.CommonController;
|
||||
public class ICalController extends CommonController {
|
||||
|
||||
@Autowired
|
||||
private IICalService service;
|
||||
private ICalService service;
|
||||
|
||||
/**
|
||||
* generate the ical response stream
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.ical.impl;
|
||||
package de.jottyfan.camporganizer.module.ical;
|
||||
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_CAMP;
|
||||
import static de.jottyfan.camporganizer.db.jooq.Tables.T_LOCATION;
|
@ -1,15 +1,13 @@
|
||||
package de.jottyfan.camporganizer.module.ical.impl;
|
||||
package de.jottyfan.camporganizer.module.ical;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import biweekly.Biweekly;
|
||||
import biweekly.ICalendar;
|
||||
import de.jottyfan.camporganizer.module.ical.IICalService;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -17,12 +15,11 @@ import de.jottyfan.camporganizer.module.ical.IICalService;
|
||||
*
|
||||
*/
|
||||
@Service
|
||||
public class ICalService implements IICalService {
|
||||
public class ICalService {
|
||||
|
||||
@Autowired
|
||||
private ICalRepository gateway;
|
||||
|
||||
@Override
|
||||
public Boolean generate(HttpServletResponse response) throws IOException {
|
||||
ICalendar ical = gateway.getIcal();
|
||||
String content = Biweekly.write(ical).go();
|
||||
@ -37,5 +34,4 @@ public class ICalService implements IICalService {
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
package de.jottyfan.camporganizer.module.ical;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jotty
|
||||
*
|
||||
*/
|
||||
public interface IICalService {
|
||||
|
||||
/**
|
||||
* generate the ical
|
||||
*
|
||||
* @param response the response for the output stream
|
||||
*
|
||||
* @return true if successful, false otherwise
|
||||
* @throws IOException on io errors
|
||||
*/
|
||||
public Boolean generate(HttpServletResponse response) throws IOException;
|
||||
}
|
@ -5,8 +5,8 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -3,8 +3,8 @@ package de.jottyfan.camporganizer.module.mail;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import jakarta.mail.MessagingException;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -2,8 +2,8 @@ package de.jottyfan.camporganizer.module.migration;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
|
||||
import org.jasypt.exceptions.EncryptionOperationNotPossibleException;
|
||||
import org.jasypt.util.password.StrongPasswordEncryptor;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.migration;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.migration;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
@ -3,8 +3,8 @@ package de.jottyfan.camporganizer.module.registration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import jakarta.ws.rs.core.Response;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@ -27,7 +27,7 @@ import org.springframework.stereotype.Repository;
|
||||
public class KeycloakRepository {
|
||||
private final static Logger LOGGER = LogManager.getLogger(KeycloakRepository.class);
|
||||
|
||||
@Value("${keycloak.resource}")
|
||||
@Value("${keycloak.client-id}")
|
||||
private String keycloakClientId;
|
||||
|
||||
@Value("${keycloak.auth-server-url}")
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.registration;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
@ -13,6 +13,8 @@ import org.springframework.web.bind.annotation.PostMapping;
|
||||
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -42,6 +44,18 @@ public class RegistrationController extends CommonController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* userlogin is protected and leads the request to the keycloak login mask if not yet logged in
|
||||
*
|
||||
* @param fkCamp the ID of the camp
|
||||
* @param model the model
|
||||
* @return hen registration page
|
||||
*/
|
||||
@GetMapping("/userlogin/registration/{fkCamp}")
|
||||
public String loginIndex(@PathVariable(name = "fkCamp", required = true) Integer fkCamp, Model model) {
|
||||
return index(fkCamp, model);
|
||||
}
|
||||
|
||||
@PostMapping("/registration/register")
|
||||
public String register(@Valid @ModelAttribute("bean") RegistrationBean bean, final BindingResult bindingResult,
|
||||
Model model) {
|
||||
|
@ -43,8 +43,11 @@ 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.db.jooq.tables.records.TRssRecord;
|
||||
import de.jottyfan.camporganizer.module.camplist.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.LambdaResultWrapper;
|
||||
import de.jottyfan.camporganizer.module.registration.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.registration.model.ProfileBean;
|
||||
import de.jottyfan.camporganizer.module.registration.model.RegistrationBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -91,7 +94,7 @@ public class RegistrationRepository {
|
||||
SelectConditionStep<TProfileRecord> sql = jooq
|
||||
// @formatter:off
|
||||
.selectFrom(T_PROFILE)
|
||||
.where(T_PROFILE.USERNAME.eq(login));
|
||||
.where(DSL.lower(T_PROFILE.USERNAME).eq(login));
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql);
|
||||
return sql.fetch().size() < 1;
|
||||
@ -108,9 +111,9 @@ public class RegistrationRepository {
|
||||
LambdaResultWrapper lrw = new LambdaResultWrapper();
|
||||
jooq.transaction(t -> {
|
||||
if (bean.getLogin() != null && !bean.getLogin().isEmpty()) {
|
||||
Boolean loginNotYetInUse = isLoginNotYetInUse(bean.getLogin());
|
||||
Boolean loginNotYetInUse = isLoginNotYetInUse(bean.getLogin().toLowerCase());
|
||||
if (bean.getRegisterInKeycloak() && !loginNotYetInUse) {
|
||||
throw new DataAccessException("login already in use: " + bean.getLogin());
|
||||
throw new DataAccessException("login already in use: " + bean.getLogin().toLowerCase());
|
||||
}
|
||||
Integer fkProfile = null;
|
||||
if (loginNotYetInUse) {
|
||||
@ -124,7 +127,7 @@ public class RegistrationRepository {
|
||||
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())
|
||||
.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());
|
||||
@ -144,7 +147,7 @@ public class RegistrationRepository {
|
||||
// @formatter:off
|
||||
.select(T_PROFILE.PK)
|
||||
.from(T_PROFILE)
|
||||
.where(T_PROFILE.USERNAME.eq(bean.getLogin()));
|
||||
.where(DSL.lower(T_PROFILE.USERNAME).eq(bean.getLogin().toLowerCase()));
|
||||
// @formatter:on
|
||||
LOGGER.debug(sql1.toString());
|
||||
fkProfile = sql1.fetchOne().get(T_PROFILE.PK);
|
||||
|
@ -3,7 +3,9 @@ package de.jottyfan.camporganizer.module.registration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import de.jottyfan.camporganizer.module.camplist.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.camplist.model.BookingBean;
|
||||
import de.jottyfan.camporganizer.module.registration.model.CampBean;
|
||||
import de.jottyfan.camporganizer.module.registration.model.RegistrationBean;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -52,7 +54,7 @@ public class RegistrationService {
|
||||
}
|
||||
Boolean result = gateway.register(bean);
|
||||
if (result && bean.getRegisterInKeycloak()) {
|
||||
keycloak.register(bean.getForename(), bean.getSurname(), bean.getLogin(), bean.getPassword(), bean.getEmail());
|
||||
keycloak.register(bean.getKcForename(), bean.getKcSurname(), bean.getLogin(), bean.getPassword(), bean.getKcEmail());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.registration;
|
||||
package de.jottyfan.camporganizer.module.registration.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package de.jottyfan.camporganizer.module.registration;
|
||||
package de.jottyfan.camporganizer.module.registration.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
@ -1,11 +1,11 @@
|
||||
package de.jottyfan.camporganizer.module.registration;
|
||||
package de.jottyfan.camporganizer.module.registration.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDate;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import jakarta.validation.constraints.Email;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
@ -21,6 +21,7 @@ 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
|
||||
public class RegistrationBean implements Serializable {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ -50,6 +51,9 @@ public class RegistrationBean implements Serializable {
|
||||
private Boolean registerInKeycloak;
|
||||
private String login;
|
||||
private String password;
|
||||
private String kcForename;
|
||||
private String kcSurname;
|
||||
private String kcEmail;
|
||||
|
||||
/**
|
||||
* @return forename + surname, separated by a space
|
||||
@ -267,4 +271,46 @@ public class RegistrationBean implements Serializable {
|
||||
public void setCampRole(EnumCamprole campRole) {
|
||||
this.campRole = campRole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kcForename
|
||||
*/
|
||||
public String getKcForename() {
|
||||
return kcForename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param kcForename the kcForename to set
|
||||
*/
|
||||
public void setKcForename(String kcForename) {
|
||||
this.kcForename = kcForename;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kcSurname
|
||||
*/
|
||||
public String getKcSurname() {
|
||||
return kcSurname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param kcSurname the kcSurname to set
|
||||
*/
|
||||
public void setKcSurname(String kcSurname) {
|
||||
this.kcSurname = kcSurname;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the kcEmail
|
||||
*/
|
||||
public String getKcEmail() {
|
||||
return kcEmail;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param kcEmail the kcEmail to set
|
||||
*/
|
||||
public void setKcEmail(String kcEmail) {
|
||||
this.kcEmail = kcEmail;
|
||||
}
|
||||
}
|
@ -6,8 +6,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -2,8 +2,8 @@ package de.jottyfan.camporganizer.module.registration.validate;
|
||||
|
||||
import java.time.LocalDate;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -6,8 +6,8 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import javax.validation.Constraint;
|
||||
import javax.validation.Payload;
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -1,7 +1,7 @@
|
||||
package de.jottyfan.camporganizer.module.registration.validate;
|
||||
|
||||
import javax.validation.ConstraintValidator;
|
||||
import javax.validation.ConstraintValidatorContext;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -1,6 +1,6 @@
|
||||
package de.jottyfan.camporganizer.module.rss;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
|
@ -5,7 +5,7 @@ import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
@ -9,11 +9,19 @@ spring.datasource.password = ${spring.datasource.password}
|
||||
|
||||
server.servlet.context-path = ${server.servlet.context-path:/CampOrganizer2}
|
||||
|
||||
# security
|
||||
keycloak.auth-server-url = ${keycloak.auth-server-url}
|
||||
keycloak.realm = ${keycloak.realm:ow}
|
||||
keycloak.resource = ${keycloak.resource:biblecamp}
|
||||
keycloak.public-client = ${keycloak.public-client}
|
||||
keycloak.use-resource-role-mappings = ${keycloak.use-resource-role-mappings}
|
||||
keycloak.realm = ${keycloak.realm}
|
||||
spring.security.oauth2.client.registration.keycloak.client-id = ${keycloak.client-id}
|
||||
spring.security.oauth2.client.registration.keycloak.scope = openid
|
||||
spring.security.oauth2.client.registration.keycloak.authorization-grant-type = authorization_code
|
||||
spring.security.oauth2.client.registration.keycloak.redirect-uri = ${keycloak.redirect-uri}
|
||||
spring.security.oauth2.client.provider.keycloak.issuer-uri = ${keycloak.issuer-uri}
|
||||
spring.security.oauth2.client.provider.keycloak.authorization-uri = ${keycloak.openid-url}/auth
|
||||
spring.security.oauth2.client.provider.keycloak.token-uri = ${keycloak.openid-url}/token
|
||||
spring.security.oauth2.client.provider.keycloak.user-info-uri = ${keycloak.openid-url}/userinfo
|
||||
spring.security.oauth2.client.provider.keycloak.jwk-set-uri = ${keycloak.openid-url}/certs
|
||||
spring.security.oauth2.client.provider.keycloak.user-name-attribute = preferred_username
|
||||
|
||||
ow.keycloak.admin.name = ${ow.keycloak.admin.name}
|
||||
ow.keycloak.admin.password = ${ow.keycloak.admin.password}
|
||||
|
@ -433,3 +433,12 @@ div {
|
||||
box-shadow: 0px 0px 7px 4px #ddd;
|
||||
border-radius: 40px;
|
||||
}
|
||||
|
||||
.beforetext {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.visibledropdown {
|
||||
max-height: 80vh;
|
||||
overflow: auto;
|
||||
}
|
||||
|
37
src/main/resources/static/images/Icon_Bett.svg
Normal file
37
src/main/resources/static/images/Icon_Bett.svg
Normal file
@ -0,0 +1,37 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg id="Ebene_2" data-name="Ebene 2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 236.23 143.81">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
stroke-linecap: round;
|
||||
stroke-linejoin: round;
|
||||
stroke-width: 2px;
|
||||
}
|
||||
|
||||
.cls-1, .cls-2 {
|
||||
fill: none;
|
||||
stroke: #313122;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
stroke-miterlimit: 10;
|
||||
stroke-width: 5px;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Ebene_1-2" data-name="Ebene 1">
|
||||
<g>
|
||||
<path class="cls-2" d="m30.26,60.8c0-11.68,9.59-19.43,21.41-19.43h7.14c11.83,0,21.41,7.75,21.41,19.43v2.78"/>
|
||||
<path class="cls-2" d="m91.34,46.92c-8.79,9.48-22.21,33.31-22.21,33.31l44.42,44.42h11.1l61.07-44.42h48v-16.66c0-9.2-7.46-16.66-16.66-16.66,0,0-54.25-11.1-81.32-11.1s-35.92,1.94-44.42,11.1Z"/>
|
||||
<polyline class="cls-2" points="233.73 80.23 233.73 141.31 217.07 141.31 205.96 113.55 141.31 113.55"/>
|
||||
<polyline class="cls-2" points="102.44 113.55 30.26 113.55 19.16 141.31 2.5 141.31 2.5 2.5 30.26 2.5 30.26 80.23 69.13 80.23"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="cls-1" d="m182.39,82.77c.11.2,4.21-2.74,4.34-2.51,1.03,1.79-19.11,31.45-18.07,33.25,1.64,2.84,55.85-36.31,57.61-33.26,1.14,1.97-25.49,31.64-24.56,33.26.88,1.52,31.09-20.02,31.99-18.47.97,1.69-22.64,31.89-21.72,33.49.57.99,21.05-13.73,21.73-12.55.62,1.07-5.44,24.08-4.74,25.29.13.22,4.62-2.98,4.76-2.75"/>
|
||||
<g>
|
||||
<path class="cls-1" d="m31.23,113.53c1.4,2.42,43.71-28.47,45.11-26.04.72,1.24-11.09,24.92-10.44,26.03s22.5-14.43,23.13-13.35c.36.62,3.12,12.7,3.49,13.35.19.32,6.09-3.89,6.25-3.61"/>
|
||||
<path class="cls-1" d="m2.53,3.11s.98-.62,1-.58c.51.88-1.44,17.86-1,18.62.79,1.37,26.89-17.41,27.7-15.99C31.46,7.28,1.41,43.16,2.53,45.1c.85,1.47,26.87-17.45,27.71-16,1.15,1.99-28.78,36.07-27.71,37.92.72,1.25,26.93-17.37,27.72-16,1.26,2.19-28.81,35.35-27.72,37.24.82,1.42,26.87-17.49,27.73-16.01,1.32,2.29-28.82,37.88-27.73,39.77,1.56,2.7,53.39-34.59,55.02-31.77,1.78,3.09-56.85,47.45-55.02,50.61.71,1.23,26.28-16.85,27.01-15.59s-12.02,24.9-11.38,26c.04.07,1.26-.82,1.3-.75"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
@ -6,3 +6,17 @@ class MyToggle {
|
||||
$("[id='" + divid + "']").toggle();
|
||||
}
|
||||
}
|
||||
|
||||
filterAllOfClass = function(filterselector, haystackselector) {
|
||||
$(haystackselector).each(function() {
|
||||
var t = $($(this).children()[0]).text();
|
||||
var filter = $(filterselector).val();
|
||||
if (filter == '' || filter == '*') {
|
||||
$(this).show();
|
||||
} else if (t.toUpperCase().indexOf(filter.toUpperCase()) > -1) {
|
||||
$(this).show();
|
||||
} else {
|
||||
$(this).hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -14,17 +14,17 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="c : ${camps}">
|
||||
<td><a th:href="@{/admin/camp/edit/{id}(id=${c.pk})}"><span th:text="${c.name}"></span></a></td>
|
||||
<td><a th:href="@{/admin/camp/edit/{id}(id=${c.pk})}"><i class="fas fa-pen beforetext"></i><span th:text="${c.name}"></span></a></td>
|
||||
<td><th:block th:each="l : ${locations}">
|
||||
<span th:if="${l.pk == c.fkLocation}" th:text="${l.name}"></span>
|
||||
</th:block></td>
|
||||
<td><span th:text="${#temporals.format(c.arrive, 'dd.MM.')}"></span> - <span th:text="${#temporals.format(c.depart, 'dd.MM.yyyy')}"></span></td>
|
||||
<td><a th:href="@{/document/{id}(id=${c.fkDocument})}"><i class="fas fa-download"></i></a></td>
|
||||
<td><a th:href="@{/document/{id}(id=${c.fkDocument})}"><i class="fas fa-download beforetext"></i>anzeigen</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" style="text-align: center"><a th:href="@{/admin/camp/add}" class="btn btn-outline-primary">neue Freizeit anlegen</a></td>
|
||||
<td colspan="4" style="text-align: center"><a th:href="@{/admin/camp/add}" class="btn btn-outline-primary">neue Freizeit anlegen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
@ -10,12 +10,11 @@
|
||||
<td>Dokumententyp</td>
|
||||
<td>Zielgruppe</td>
|
||||
<th>Inhalt</th>
|
||||
<th>Dateityp</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="d : ${documents}">
|
||||
<td><a th:href="@{/admin/document/edit/{id}(id=${d.pk})}"><span th:text="${d.name}"></span></a></td>
|
||||
<td><a th:href="@{/admin/document/edit/{id}(id=${d.pk})}"><i class="fas fa-pen beforetext"></i><span th:text="${d.name}"></span></a></td>
|
||||
<td><span th:if="${d.doctype.literal == 'location'}">Wegbeschreibung</span> <span th:if="${d.doctype.literal == 'camp'}">Bestätigung</span><span
|
||||
th:if="${d.doctype.literal == 'camppass'}">Freizeitpass</span></td>
|
||||
<td><th:block th:each="r : ${d.roles}">
|
||||
@ -25,13 +24,12 @@
|
||||
<span th:if="${r.literal == 'feeder'}" class="roleflag">Küche</span>
|
||||
<span th:if="${r.literal == 'observer'}" class="roleflag">Mitarbeiterkind</span>
|
||||
</th:block></td>
|
||||
<td><a th:href="@{/document/{id}(id=${d.pk})}"><i class="fas fa-download"></i></a></td>
|
||||
<td><span th:text="${d.filetype.literal}" th:if="${d.filetype}"></span></td>
|
||||
<td><a th:href="@{/document/{id}(id=${d.pk})}"><i class="fas fa-download beforetext"></i><span th:text="${d.filetype.literal}" th:if="${d.filetype}"></span> anzeigen</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" style="text-align: center"><a th:href="@{/admin/document/add}" class="btn btn-outline-primary">neues Dokument anlegen</a></td>
|
||||
<td colspan="4" style="text-align: center"><a th:href="@{/admin/document/add}" class="btn btn-outline-primary">neues Dokument anlegen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
@ -13,14 +13,14 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="l : ${locations}">
|
||||
<td><a th:href="@{/admin/location/edit/{id}(id=${l.pk})}"><span th:text="${l.name}"></span></a></td>
|
||||
<td th:text="${l.url}"></td>
|
||||
<td><a th:href="@{/document/{id}(id=${l.fkDocument})}"><i class="fas fa-download"></i></a></td>
|
||||
<td><a th:href="@{/admin/location/edit/{id}(id=${l.pk})}"><i class="fas fa-pen beforetext"></i><span th:text="${l.name}"></span></a></td>
|
||||
<td><a th:href="${l.url}" target="_blank"><i class="fas fa-external-link-alt beforetext"></i><span th:text="${l.url}"></span></a></td>
|
||||
<td><a th:href="@{/document/{id}(id=${l.fkDocument})}"><i class="fas fa-download beforetext"></i>anzeigen</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="6" style="text-align: center"><a th:href="@{/admin/location/add}" class="btn btn-outline-primary">neues Freizeitheim anlegen</a></td>
|
||||
<td colspan="3" style="text-align: center"><a th:href="@{/admin/location/add}" class="btn btn-outline-primary">neues Freizeitheim anlegen</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
66
src/main/resources/templates/admin/privileges/add.html
Normal file
66
src/main/resources/templates/admin/privileges/add.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!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">
|
||||
<body>
|
||||
<th:block layout:fragment="content">
|
||||
<div sec:authorize="hasRole('admin')">
|
||||
<form th:action="@{/admin/privileges/insert/{d}(d=${pagedest})}" th:object="${bean}" method="post" enctype="multipart/form-data">
|
||||
<div class="tablebox">
|
||||
<div class="container">
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-12">
|
||||
<div class="alert alter-danger" th:if="${error}" th:text="${error}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputPerson" class="col-sm-2 col-form-label">Person</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('fkProfile')}">[[${error}]]<br /></span> <select id="inputPerson" th:field="*{fkProfile}"
|
||||
th:class="${'form-select ' + (#fields.hasErrors('fkProfile') ? 'inputerror' : '')}">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option th:each="l : ${profiles}" th:value="${l.pk}" th:text="${l.fullname}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#inputPerson").select2();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputCamp" class="col-sm-2 col-form-label">Freizeit</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('fkCamp')}">[[${error}]]<br /></span> <select id="inputCamp" th:field="*{fkCamp}"
|
||||
th:class="${'form-select ' + (#fields.hasErrors('fkCamp') ? 'inputerror' : '')}">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option th:each="l : ${camps}" th:value="${l.pk}" th:text="${l.name}"></option>
|
||||
</select>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function() {
|
||||
$("#inputCamp").select2();
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label for="inputModule" class="col-sm-2 col-form-label">Modul</label>
|
||||
<div class="col-sm-10">
|
||||
<span class="error" th:each="error : ${#fields.errors('module')}">[[${error}]]<br /></span> <select id="inputModule" th:field="*{module}"
|
||||
th:class="${'form-select ' + (#fields.hasErrors('module') ? 'inputerror' : '')}">
|
||||
<option value="">--- bitte wählen ---</option>
|
||||
<option th:each="l : ${modules}" th:value="${l}" th:text="${l}"></option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-sm-2"></div>
|
||||
<div class="col-sm-10">
|
||||
<input type="submit" class="btn btn-success" value="Ok" /> <a th:href="@{/admin/privileges/abortinsert/{d}(d=${pagedest})}" class="btn btn-outline-secondary">Abbrechen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
71
src/main/resources/templates/admin/privileges/campbased.html
Normal file
71
src/main/resources/templates/admin/privileges/campbased.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!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 Privileges</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<th:block layout:fragment="content">
|
||||
<div sec:authorize="hasRole('admin')">
|
||||
<div class="tablebox">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<span th:text="${selected}" th:if="${selected}"></span> <span th:unless="${selected}">-- bitte wählen --</span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li style="padding: 8px"><input type="text" id="needle" onkeyup="filterAllOfClass('#needle', '.haystack')" placeholder="Filter" class="form-control" /></li>
|
||||
<li th:each="e : ${list}" class="haystack"><a class="dropdown-item" th:href="@{/admin/privileges/campbased/{r}(r=${e.pk})}" th:text="${e.fullname}"></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="card" th:if="${selected}">
|
||||
<div class="card-header">
|
||||
<h1 th:text="${selected}"></h1>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Person</th>
|
||||
<th>Modul</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr th:each="m : ${container.map}">
|
||||
<td th:text="${m.key}"></td>
|
||||
<td>
|
||||
<div class="btn-toolbar" role="toolbar">
|
||||
<div class="btn-group beforetext" role="group" th:each="v : ${m.value}" th:if="${m.value}">
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-danger dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fas fa-trash-alt"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" th:href="@{/admin/privileges/delete/{id}/{d}(id=${v.key}, d=${pagedest})}">endgültig löschen</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-secondary" th:text="${v.value}" disabled></button>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="2" style="text-align: center"><a th:href="@{/admin/privileges/add/{d}(d=${pagedest})}" class="btn btn-outline-primary">neue Berechtigung vergeben</a></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$("#table").DataTable({
|
||||
language : locale_de
|
||||
});
|
||||
});
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
</body>
|
||||
</html>
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user