migrated shared-account into own project, updated license heaaders
This commit is contained in:
189
.gitignore
vendored
189
.gitignore
vendored
@ -1,8 +1,183 @@
|
||||
/**/.settings/
|
||||
**/target/
|
||||
.classpath
|
||||
.project
|
||||
**/nbproject/
|
||||
*.dump
|
||||
**/_dump
|
||||
# ---> NetBeans
|
||||
nbproject/private/
|
||||
build/
|
||||
nbbuild/
|
||||
dist/
|
||||
nbdist/
|
||||
nbactions.xml
|
||||
**/nb-configuration.xml
|
||||
.nb-gradle/
|
||||
|
||||
# ---> Eclipse
|
||||
.project
|
||||
.settings/
|
||||
.classpath
|
||||
|
||||
# ---> Maven
|
||||
target/
|
||||
pom.xml.tag
|
||||
pom.xml.releaseBackup
|
||||
pom.xml.versionsBackup
|
||||
pom.xml.next
|
||||
release.properties
|
||||
dependency-reduced-pom.xml
|
||||
buildNumber.properties
|
||||
.mvn/timing.properties
|
||||
|
||||
# ---> Java
|
||||
*.class
|
||||
|
||||
# Mobile Tools for Java (J2ME)
|
||||
.mtj.tmp/
|
||||
|
||||
# Package Files #
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
# ---> TeX
|
||||
## Core latex/pdflatex auxiliary files:
|
||||
*.aux
|
||||
*.lof
|
||||
*.log
|
||||
*.lot
|
||||
*.fls
|
||||
*.out
|
||||
*.toc
|
||||
|
||||
## Intermediate documents:
|
||||
*.dvi
|
||||
*-converted-to.*
|
||||
# these rules might exclude image files for figures etc.
|
||||
# *.ps
|
||||
# *.eps
|
||||
# *.pdf
|
||||
|
||||
## Bibliography auxiliary files (bibtex/biblatex/biber):
|
||||
*.bbl
|
||||
*.bcf
|
||||
*.blg
|
||||
*-blx.aux
|
||||
*-blx.bib
|
||||
*.brf
|
||||
*.run.xml
|
||||
|
||||
## Build tool auxiliary files:
|
||||
*.fdb_latexmk
|
||||
*.synctex
|
||||
*.synctex.gz
|
||||
*.synctex.gz(busy)
|
||||
*.pdfsync
|
||||
|
||||
## Auxiliary and intermediate files from other packages:
|
||||
|
||||
|
||||
# algorithms
|
||||
*.alg
|
||||
*.loa
|
||||
|
||||
# achemso
|
||||
acs-*.bib
|
||||
|
||||
# amsthm
|
||||
*.thm
|
||||
|
||||
# beamer
|
||||
*.nav
|
||||
*.snm
|
||||
*.vrb
|
||||
|
||||
#(e)ledmac/(e)ledpar
|
||||
*.end
|
||||
*.[1-9]
|
||||
*.[1-9][0-9]
|
||||
*.[1-9][0-9][0-9]
|
||||
*.[1-9]R
|
||||
*.[1-9][0-9]R
|
||||
*.[1-9][0-9][0-9]R
|
||||
*.eledsec[1-9]
|
||||
*.eledsec[1-9]R
|
||||
*.eledsec[1-9][0-9]
|
||||
*.eledsec[1-9][0-9]R
|
||||
*.eledsec[1-9][0-9][0-9]
|
||||
*.eledsec[1-9][0-9][0-9]R
|
||||
|
||||
# glossaries
|
||||
*.acn
|
||||
*.acr
|
||||
*.glg
|
||||
*.glo
|
||||
*.gls
|
||||
|
||||
# gnuplottex
|
||||
*-gnuplottex-*
|
||||
|
||||
# hyperref
|
||||
*.brf
|
||||
|
||||
# knitr
|
||||
*-concordance.tex
|
||||
*.tikz
|
||||
*-tikzDictionary
|
||||
|
||||
# listings
|
||||
*.lol
|
||||
|
||||
# makeidx
|
||||
*.idx
|
||||
*.ilg
|
||||
*.ind
|
||||
*.ist
|
||||
|
||||
# minitoc
|
||||
*.maf
|
||||
*.mtc
|
||||
*.mtc[0-9]
|
||||
*.mtc[1-9][0-9]
|
||||
|
||||
# minted
|
||||
_minted*
|
||||
*.pyg
|
||||
|
||||
# morewrites
|
||||
*.mw
|
||||
|
||||
# mylatexformat
|
||||
*.fmt
|
||||
|
||||
# nomencl
|
||||
*.nlo
|
||||
|
||||
# sagetex
|
||||
*.sagetex.sage
|
||||
*.sagetex.py
|
||||
*.sagetex.scmd
|
||||
|
||||
# sympy
|
||||
*.sout
|
||||
*.sympy
|
||||
sympy-plots-for-*.tex/
|
||||
|
||||
# TikZ & PGF
|
||||
*.dpth
|
||||
*.md5
|
||||
*.auxlock
|
||||
|
||||
# todonotes
|
||||
*.tdo
|
||||
|
||||
# xindy
|
||||
*.xdy
|
||||
|
||||
# WinEdt
|
||||
*.bak
|
||||
*.sav
|
||||
|
||||
# localized versions of JBOSS command line interface
|
||||
*.local.cli
|
||||
/source/office-parent/office-web/faces-config.NavData
|
||||
/source/vvh-access-import/src/main/resources/hibernate.cfg.xml
|
||||
/source/office-parent/office-entities/src/main/resources/META-INF/persistence.xml
|
||||
|
||||
@ -1,53 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
<artifactId>shared</artifactId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account-dao</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<name>shared-account-dao</name>
|
||||
|
||||
<dependencies>
|
||||
<!-- TODO - remove dependencies from GSON and Jackson -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<version>5.3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@ -1,104 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.dao;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.google.gson.annotations.Expose;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public class ApiKeyObject implements Serializable {
|
||||
|
||||
@Expose
|
||||
private String userName;
|
||||
@Expose
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, locale = "en_US", timezone = "UTC", pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||
private Date issuedOn;
|
||||
@Expose
|
||||
@JsonFormat(shape = JsonFormat.Shape.STRING, locale = "en_US", timezone = "UTC", pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
|
||||
private Date expiresOn;
|
||||
@Expose
|
||||
private String authToken;
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public Date getIssuedOn() {
|
||||
return issuedOn;
|
||||
}
|
||||
|
||||
public void setIssuedOn(Date issuedOn) {
|
||||
this.issuedOn = issuedOn;
|
||||
}
|
||||
|
||||
public Date getExpiresOn() {
|
||||
return expiresOn;
|
||||
}
|
||||
|
||||
public void setExpiresOn(Date expiresOn) {
|
||||
this.expiresOn = expiresOn;
|
||||
}
|
||||
|
||||
public String getAuthToken() {
|
||||
return authToken;
|
||||
}
|
||||
|
||||
public void setAuthToken(String authToken) {
|
||||
this.authToken = authToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 3;
|
||||
hash = 53 * hash + Objects.hashCode(this.userName);
|
||||
hash = 53 * hash + Objects.hashCode(this.issuedOn);
|
||||
hash = 53 * hash + Objects.hashCode(this.expiresOn);
|
||||
hash = 53 * hash + Objects.hashCode(this.authToken);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj == null) {
|
||||
return false;
|
||||
}
|
||||
if (getClass() != obj.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final ApiKeyObject other = (ApiKeyObject) obj;
|
||||
if (!Objects.equals(this.userName, other.userName)) {
|
||||
return false;
|
||||
}
|
||||
if (!Objects.equals(this.authToken, other.authToken)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.dao;
|
||||
|
||||
import de.muehlencord.shared.util.DateUtil;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public abstract class ApiKeyUtil {
|
||||
|
||||
private ApiKeyUtil() {
|
||||
// hide constructor for abstract class - only static methods are used
|
||||
}
|
||||
|
||||
public static boolean isValid(ApiKeyObject apiKeyObject) {
|
||||
if (apiKeyObject == null) {
|
||||
return false;
|
||||
}
|
||||
Date validToDate = apiKeyObject.getExpiresOn();
|
||||
if (validToDate == null) {
|
||||
return false;
|
||||
}
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
return validToDate.after(now);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,30 +0,0 @@
|
||||
package de.muehlencord.shared.account.dao;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
public abstract class JacksonConfig {
|
||||
|
||||
private static ObjectMapper objectMapper = null;
|
||||
|
||||
private JacksonConfig() {
|
||||
// hide public constructor for static only class
|
||||
}
|
||||
|
||||
public static ObjectMapper getInstance() {
|
||||
if (objectMapper == null) {
|
||||
objectMapper = new ObjectMapper();
|
||||
objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"));
|
||||
objectMapper.configure(SerializationFeature.INDENT_OUTPUT, true);
|
||||
objectMapper.configure(SerializationFeature.WRAP_ROOT_VALUE, true);
|
||||
objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
|
||||
}
|
||||
return objectMapper;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* To change this license header, choose License Headers in Project Properties.
|
||||
* To change this template file, choose Tools | Templates
|
||||
* and open the template in the editor.
|
||||
*/
|
||||
package de.muehlencord.shared.account.dao;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public class ApiKeyObjectTest {
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testJackson() throws JsonProcessingException, IOException {
|
||||
ApiKeyObject apiKeyObject = new ApiKeyObject();
|
||||
apiKeyObject.setUserName("web");
|
||||
apiKeyObject.setIssuedOn(new Date());
|
||||
apiKeyObject.setExpiresOn(new Date());
|
||||
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
String json = mapper.writeValueAsString(apiKeyObject);
|
||||
|
||||
System.out.println(json);
|
||||
|
||||
|
||||
ApiKeyObject apiKeyObject2 = mapper.readValue (json, ApiKeyObject.class);
|
||||
assertTrue (apiKeyObject.equals(apiKeyObject2));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scene Scope="Project" version="2">
|
||||
<Scope Scope="Faces Configuration Only"/>
|
||||
<Scope Scope="Project"/>
|
||||
<Scope Scope="All Faces Configurations"/>
|
||||
</Scene>
|
||||
@ -1,22 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project-shared-configuration>
|
||||
<!--
|
||||
This file contains additional configuration written by modules in the NetBeans IDE.
|
||||
The configuration is intended to be shared among all the users of project and
|
||||
therefore it is assumed to be part of version control checkout.
|
||||
Without this configuration present, some functionality in the IDE may be limited or fail altogether.
|
||||
-->
|
||||
<libraries xmlns="http://www.netbeans.org/ns/cdnjs-libraries/1"/>
|
||||
<properties xmlns="http://www.netbeans.org/ns/maven-properties-data/1">
|
||||
<!--
|
||||
Properties that influence various parts of the IDE, especially code formatting and the like.
|
||||
You can copy and paste the single properties, into the pom.xml file and the IDE will pick them up.
|
||||
That way multiple projects can share the same settings (useful for formatting rules for example).
|
||||
Any value defined here will override the pom.xml file value but is only applicable to the current project.
|
||||
-->
|
||||
<org-netbeans-modules-projectapi.jsf_2e_language>Facelets</org-netbeans-modules-projectapi.jsf_2e_language>
|
||||
<org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>WildFly</org-netbeans-modules-maven-j2ee.netbeans_2e_hint_2e_deploy_2e_server>
|
||||
<netbeans.hint.license>apache20</netbeans.hint.license>
|
||||
<org-netbeans-modules-web-clientproject-api.js_2e_libs_2e_folder>js/libs</org-netbeans-modules-web-clientproject-api.js_2e_libs_2e_folder>
|
||||
</properties>
|
||||
</project-shared-configuration>
|
||||
@ -1,152 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>shared</artifactId>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account-ui</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<name>shared-account-ui</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<timestamp>${maven.build.timestamp}</timestamp>
|
||||
<!-- default filter if not selected via profile -->
|
||||
<applicationUuid>143a2bd3-7e0b-4162-a76e-3031331c7dfe</applicationUuid>
|
||||
<filter.name>development</filter.name>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.primefaces</groupId>
|
||||
<artifactId>primefaces</artifactId>
|
||||
</dependency>
|
||||
<!-- Admin faces template -->
|
||||
<dependency>
|
||||
<groupId>com.github.adminfaces</groupId>
|
||||
<artifactId>admin-template</artifactId>
|
||||
</dependency>
|
||||
<!-- Omnifaces, faces utils -->
|
||||
<dependency>
|
||||
<groupId>org.omnifaces</groupId>
|
||||
<artifactId>omnifaces</artifactId>
|
||||
</dependency>
|
||||
<!-- Apache Shiro, Security API -->
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-shiro-faces</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account</artifactId>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-jeeutil</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.muehlencord.sf</groupId>
|
||||
<artifactId>filter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-web-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<filters>
|
||||
<filter>${basedir}/src/main/filters/${filter.name}.properties</filter>
|
||||
</filters>
|
||||
|
||||
<resources>
|
||||
<!-- fill buildinformation file -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/*.properties</include>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<finalName>account</finalName>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<version>3.2.2</version>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>${basedir}/src/main/webapp</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>WEB-INF/web.xml</include>
|
||||
<include>WEB-INF/jboss-web.xml</include>
|
||||
<include>WEB-INF/shiro.ini</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>development</id>
|
||||
<properties>
|
||||
<filter.name>development</filter.name>
|
||||
</properties>
|
||||
</profile>
|
||||
|
||||
<profile>
|
||||
<id>production</id>
|
||||
<properties>
|
||||
<filter.name>production</filter.name>
|
||||
</properties>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
@ -1,8 +0,0 @@
|
||||
jsf.projectStage=Development
|
||||
context.root=account
|
||||
|
||||
shiro.contextFactory = # not defined
|
||||
shiro.passwordMatcher= passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher${line.separator}passwordMatcher.passwordService = $passwordService
|
||||
shiro.ldapRealm = # not defined
|
||||
shiro.authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy
|
||||
shiro.realms = $jdbcRealm
|
||||
@ -1,18 +0,0 @@
|
||||
jsf.projectStage=Production
|
||||
context.root=account
|
||||
|
||||
ldap.url = ldaps://host:port
|
||||
## we will use provided username / password from webapplication
|
||||
ldap.user = user
|
||||
ldap.password = secret
|
||||
ldap.principalSuffix = @primarySuffix
|
||||
ldap.fallbackPrincipalSuffixes = @fallback1, @fallback2
|
||||
ldap.searchBase = dc=domain,dc=com
|
||||
ldap.searchFilter = (&(objectClass=*)(mail={0}))
|
||||
|
||||
## NO CHANGES BEHIND THIS LINE REQUIRED
|
||||
shiro.contextFactory = contextFactory = org.apache.shiro.realm.ldap.JndiLdapContextFactory${line.separator}contextFactory.url = ${ldap.url}${line.separator}contextFactory.systemUsername = ${ldap.user}${line.separator}contextFactory.systemPassword = ${ldap.password}${line.separator}contextFactory.environment[java.naming.security.protocol] = ssl
|
||||
shiro.passwordMatcher= passwordMatcher=org.apache.shiro.authc.credential.AllowAllCredentialsMatcher
|
||||
shiro.ldapRealm = ldapRealm = de.muehlencord.shared.account.shiro.realm.UserNameActiveDirectoryRealm${line.separator}ldapRealm.principalSuffix = ${ldap.principalSuffix}${line.separator}ldapRealm.fallbackPrincipalSuffixes = ${ldap.fallbackPrincipalSuffixes}${line.separator}ldapRealm.ldapContextFactory = $contextFactory${line.separator}ldapRealm.searchBase = ${ldap.searchBase}${line.separator}ldapRealm.searchFilter = ${ldap.searchFilter}${line.separator}ldapRealm.permissionsLookupEnabled=false
|
||||
shiro.authcStrategy = org.apache.shiro.authc.pam.AllSuccessfulStrategy
|
||||
shiro.realms=$jdbcRealm,$ldapRealm
|
||||
@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.boundary.AccountPermissions;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationPermissionControl;
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationRoleControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
|
||||
import java.util.Arrays;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.context.Initialized;
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class EnsurePermissionsBean {
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
@Inject
|
||||
ApplicationPermissionControl applicationPermissionControl;
|
||||
|
||||
@Inject
|
||||
ApplicationRoleControl applicationRoleControl;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(EnsurePermissionsBean.class);
|
||||
|
||||
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Ensure all permissions for {} are available", application.getApplicationName());
|
||||
}
|
||||
applicationPermissionControl.setupPermissions(Arrays.asList(ApplicationPermissions.values()));
|
||||
applicationPermissionControl.setupPermissions(Arrays.asList(AccountPermissions.values()));
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("All permissions added to application", application.getApplicationName());
|
||||
}
|
||||
|
||||
// all permissions available - ensure permission is assigned to Admin role
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Ensuring Admin role for {} has all permissions", application.getApplicationName());
|
||||
}
|
||||
try {
|
||||
applicationRoleControl.setupRolePermission(Arrays.asList(ApplicationPermissions.values()), "Admin"); // NOI18N
|
||||
applicationRoleControl.setupRolePermission(Arrays.asList(AccountPermissions.values()), "Admin"); // NOI18N
|
||||
} catch (AccountException ex) {
|
||||
LOGGER.error("Error adding permission to Admin role. Reason={}", ex.getMessage());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
|
||||
}
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("All permissions added to Admin role of {}", application.getApplicationName());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web;
|
||||
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.context.ContextNotActiveException;
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.faces.context.FacesContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class FacesContextProducer {
|
||||
|
||||
@Produces
|
||||
@RequestScoped
|
||||
public FacesContext getFacesContext() {
|
||||
FacesContext ctx = FacesContext.getCurrentInstance();
|
||||
if (ctx == null) {
|
||||
throw new ContextNotActiveException("FacesContext is not active");
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
}
|
||||
@ -1,86 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web;
|
||||
|
||||
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
* TODO replace with omnifaces:importConstants currently problems with Netbeans
|
||||
* to import omnifaces taglib
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Named(value = "permissionConstants")
|
||||
@ApplicationScoped
|
||||
public class PermissionConstants {
|
||||
|
||||
public String getApplicationListAll() {
|
||||
return ApplicationPermissions.APP_LIST.getName();
|
||||
}
|
||||
|
||||
public String getPermissionsCombined() {
|
||||
return ApplicationPermissions.PERMISSION_ADD.getName() + ","
|
||||
+ ApplicationPermissions.PERMISSION_EDIT.getName() + ","
|
||||
+ ApplicationPermissions.PERMISSION_DELETE.getName();
|
||||
}
|
||||
|
||||
public String getRolesCombined() {
|
||||
return ApplicationPermissions.ROLE_ADD.getName() + ","
|
||||
+ ApplicationPermissions.ROLE_EDIT.getName() + ","
|
||||
+ ApplicationPermissions.ROLE_DELETE.getName();
|
||||
}
|
||||
|
||||
public String getAccountsCombined() {
|
||||
return ApplicationPermissions.ACCOUNT_ADD.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_DELETE.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_EDIT.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_LIST.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_LOGIN_ADD.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_LOGIN_DELETE.getName() + ","
|
||||
+ ApplicationPermissions.ACCOUNT_LOGIN_EDIT.getName();
|
||||
}
|
||||
|
||||
public String getAccountAdd() {
|
||||
return ApplicationPermissions.ACCOUNT_ADD.getName();
|
||||
}
|
||||
|
||||
public String getAccountDelete() {
|
||||
return ApplicationPermissions.ACCOUNT_DELETE.getName();
|
||||
}
|
||||
|
||||
public String getAccountEdit() {
|
||||
return ApplicationPermissions.ACCOUNT_EDIT.getName();
|
||||
}
|
||||
|
||||
public String getAccountList() {
|
||||
return ApplicationPermissions.ACCOUNT_LIST.getName();
|
||||
}
|
||||
|
||||
public String getAccountLoginAdd() {
|
||||
return ApplicationPermissions.ACCOUNT_LOGIN_ADD.getName();
|
||||
}
|
||||
|
||||
public String getAccountLoginDelete() {
|
||||
return ApplicationPermissions.ACCOUNT_LOGIN_DELETE.getName();
|
||||
}
|
||||
|
||||
public String getAccountLoginEdit() {
|
||||
return ApplicationPermissions.ACCOUNT_LOGIN_EDIT.getName();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
package de.muehlencord.shared.account.web;
|
||||
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.db.ApplicationPU;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.enterprise.inject.Disposes;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.EntityManagerFactory;
|
||||
import javax.persistence.PersistenceUnit;
|
||||
import javax.persistence.SynchronizationType;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class PersistenceContextFactory {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PersistenceContextFactory.class);
|
||||
|
||||
// need to define 2nd database as TransactionJoinInterceptor requires it
|
||||
// account UI is the only application where application and account is the same database
|
||||
// account UI does not call this as it references all database access via accountPu
|
||||
@PersistenceUnit (unitName = "accountPu")
|
||||
EntityManagerFactory entityManagerFactory;
|
||||
|
||||
|
||||
@Produces
|
||||
@RequestScoped
|
||||
@ApplicationPU
|
||||
public EntityManager getPcdEntityManager() {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("getting entityManager for application");
|
||||
}
|
||||
EntityManager em = entityManagerFactory.createEntityManager(SynchronizationType.UNSYNCHRONIZED);
|
||||
return em;
|
||||
}
|
||||
|
||||
public void closePcdEntityManager (@Disposes @ApplicationPU EntityManager em) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("closing entityManager application database");
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
|
||||
@Produces
|
||||
@RequestScoped
|
||||
@AccountPU
|
||||
public EntityManager getAccountEntityManager() {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("getting entityManager for account database");
|
||||
}
|
||||
EntityManager em = entityManagerFactory.createEntityManager(SynchronizationType.UNSYNCHRONIZED);
|
||||
return em;
|
||||
}
|
||||
|
||||
public void closeAccountEntityManager (@Disposes @AccountPU EntityManager em) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("closing entityManager for account database");
|
||||
}
|
||||
em.close();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.ResourceBundle;
|
||||
import javax.enterprise.context.RequestScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@RequestScoped
|
||||
public class ResourceBundleProducer implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceBundleProducer.class);
|
||||
|
||||
private static final long serialVersionUID = 3764096270387408239L;
|
||||
|
||||
@Inject
|
||||
private Locale locale;
|
||||
|
||||
@Inject
|
||||
private FacesContext facesContext;
|
||||
|
||||
@Produces
|
||||
public ResourceBundle getResourceBundle() {
|
||||
ResourceBundle rb = ResourceBundle.getBundle("de.muehlencord.shared.account.web.presentation.messages", facesContext.getViewRoot().getLocale());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("ResourceBundle = "+rb);
|
||||
}
|
||||
return rb;
|
||||
}
|
||||
}
|
||||
@ -1,296 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountLoginEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountStatus;
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationRoleControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.primefaces.event.SelectEvent;
|
||||
import org.primefaces.event.UnselectEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
@ViewScoped
|
||||
@Named("accountView")
|
||||
public class AccountView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8050582392249849438L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AccountView.class);
|
||||
|
||||
@Inject
|
||||
private ApplicationView applicationView;
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
@EJB
|
||||
private ApplicationRoleControl appliationRoleService;
|
||||
|
||||
/**
|
||||
* boolean flag to determine wether disabled accounts should be shown
|
||||
* accounts are not deleted but disabled and can be activated in case
|
||||
*/
|
||||
private boolean showDisabledAccounts = false;
|
||||
|
||||
// cached accounts
|
||||
private List<AccountEntity> accountList = null;
|
||||
// cached application roles
|
||||
private List<ApplicationRoleEntity> applicationRoles = null;
|
||||
|
||||
// account currently on edit
|
||||
private AccountEntity currentAccount;
|
||||
private List<ApplicationRoleEntity> currentAccountRoles = null;
|
||||
private AccountLoginEntity currentAccountLogin;
|
||||
private String password = null;
|
||||
private String repeatPassword = null;
|
||||
|
||||
public List<AccountEntity> getAccounts() {
|
||||
if (accountList == null) {
|
||||
accountList = accountService.getAllAccounts(showDisabledAccounts);
|
||||
}
|
||||
return accountList;
|
||||
}
|
||||
|
||||
public List<ApplicationRoleEntity> getAllApplicationRoles() {
|
||||
if (applicationRoles == null) {
|
||||
ApplicationEntity application = applicationView.getCurrentApplication();
|
||||
applicationRoles = appliationRoleService.getAllRoles(application);
|
||||
}
|
||||
return applicationRoles;
|
||||
}
|
||||
|
||||
public void selectAccount(SelectEvent event) {
|
||||
// nothing to do, currentAccountRoles are loaded before dialog is shown
|
||||
}
|
||||
|
||||
public void unselectAccount(UnselectEvent event) {
|
||||
applicationRoles = null;
|
||||
currentAccountRoles = null;
|
||||
}
|
||||
|
||||
public boolean getAccountSelected() {
|
||||
return currentAccount != null;
|
||||
}
|
||||
|
||||
public void newAccount() {
|
||||
currentAccount = new AccountEntity();
|
||||
currentAccount.setStatus("NEW"); // TODO add status enum
|
||||
currentAccountRoles = new ArrayList<>();
|
||||
}
|
||||
|
||||
public void editAccount() {
|
||||
// function called by webpage
|
||||
if (currentAccount == null) {
|
||||
currentAccountRoles = null;
|
||||
} else {
|
||||
currentAccount = accountService.getAccountEntity(currentAccount.getUsername(), true);
|
||||
this.currentAccountRoles = new ArrayList<>();
|
||||
if (currentAccount.getApplicationRoleList() != null) {
|
||||
currentAccountRoles.addAll(currentAccount.getApplicationRoleList());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelEditAccount() {
|
||||
currentAccount = null;
|
||||
currentAccountRoles = null;
|
||||
}
|
||||
|
||||
public void saveEditAccount() {
|
||||
String username = currentAccount.getUsername();
|
||||
AccountEntity existingEntity = accountService.getAccountEntity(username, true);
|
||||
// check if it is a new user (createdBy == null) but a user with same name already exists
|
||||
if ((currentAccount.getCreatedBy() == null) && (existingEntity != null)) {
|
||||
FacesUtil.addErrorMessage("editDialogMessaegs", "Create new account failed", "Account with username " + username + " already exists");
|
||||
} else {
|
||||
accountService.saveAccount(currentAccount, applicationView.getCurrentApplication(), currentAccountRoles);
|
||||
// force accounts to be loaded from database again
|
||||
accountList = null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAccount() {
|
||||
try {
|
||||
accountService.deleteAccount(currentAccount);
|
||||
accountList.remove(currentAccount);
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Account " + currentAccount.getUsername() + " deleted");
|
||||
currentAccount = null;
|
||||
currentAccountRoles = null;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Error deleting account", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void showDisabledAccountsChange() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("show diabled accounts changed to {}", showDisabledAccounts);
|
||||
}
|
||||
this.accountList = null;
|
||||
}
|
||||
|
||||
public List<String> getStatusList() {
|
||||
return AccountStatus.getAllStatusNames();
|
||||
}
|
||||
|
||||
/* **** account login methods **** */
|
||||
public boolean validatePasswords(FacesContext context, List<UIInput> components, List<Object> values) {
|
||||
String currentPassword = components.get(0).getSubmittedValue().toString();
|
||||
String currentPasswordRepeat = components.get(1).getSubmittedValue().toString();
|
||||
|
||||
if ((currentPassword == null) || (currentPasswordRepeat == null)) {
|
||||
return false;
|
||||
}
|
||||
boolean returnValue = currentPassword.equals(currentPasswordRepeat);
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
public void addAccountLogin() {
|
||||
if (currentAccount == null) {
|
||||
// TODO add error handling
|
||||
} else {
|
||||
this.currentAccountLogin = accountService.createLoginWithRandomPassword();
|
||||
}
|
||||
}
|
||||
|
||||
public void editAccountLogin() {
|
||||
if (currentAccount == null) {
|
||||
// TODO add error handling
|
||||
} else {
|
||||
this.currentAccountLogin = currentAccount.getAccountLogin();
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteAccountLogin() {
|
||||
if (currentAccount == null) {
|
||||
// TODO add error handling
|
||||
} else {
|
||||
accountService.deleteLogin(currentAccount);
|
||||
currentAccount.setAccountLogin(null);
|
||||
currentAccountLogin = null;
|
||||
accountList = null; // force reload
|
||||
FacesUtil.addGlobalInfoMessage("Account saved", "Login removed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void saveEditAccountLogin() {
|
||||
// TODO move to account control - to much logic for the view
|
||||
if ((currentAccountLogin == null) || (currentAccount == null)) {
|
||||
// TODO add error handling
|
||||
} else {
|
||||
|
||||
// overwrite password if provided
|
||||
if ((password != null) && (!password.trim().equals(""))) {
|
||||
// password has been specified
|
||||
if (password.equals(repeatPassword)) {
|
||||
currentAccountLogin.setAccountPassword(accountService.getHashedPassword(password));
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Password updated");
|
||||
} else {
|
||||
// TODO connect to IPRS
|
||||
// frontend does validate passwords do match
|
||||
// someone is trying to cheat
|
||||
}
|
||||
}
|
||||
|
||||
if (currentAccountLogin.getId() == null) {
|
||||
accountService.addLogin(currentAccount, currentAccountLogin);
|
||||
currentAccount.setAccountLogin(currentAccountLogin);
|
||||
accountList = null; // force reload of accounts
|
||||
} else {
|
||||
accountService.updateLogin(currentAccountLogin);
|
||||
}
|
||||
currentAccountLogin = null;
|
||||
FacesUtil.addGlobalInfoMessage("Account saved", "Login data updated");
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelEditAccountLogin() {
|
||||
this.currentAccountLogin = null;
|
||||
}
|
||||
|
||||
public boolean getCurrentLoggedInUser() {
|
||||
if (currentAccount == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
if (currentUser == null) {
|
||||
// TODO - connect to IPRS - how can this method be called if no user is logged in
|
||||
return false;
|
||||
}
|
||||
String currentUserName = currentUser.getPrincipal().toString();
|
||||
return currentUserName.equals(currentAccount.getUsername());
|
||||
}
|
||||
|
||||
/* **** getter / setter **** */
|
||||
/**
|
||||
* setter for managed property applicationView
|
||||
*
|
||||
* @param applicationView the applicaton view to inject
|
||||
*/
|
||||
public void setApplicationView(ApplicationView applicationView) {
|
||||
this.applicationView = applicationView;
|
||||
}
|
||||
|
||||
public AccountEntity getCurrentAccount() {
|
||||
return currentAccount;
|
||||
}
|
||||
|
||||
public void setCurrentAccount(AccountEntity currentAccount) {
|
||||
this.currentAccount = currentAccount;
|
||||
}
|
||||
|
||||
public boolean isShowDisabledAccounts() {
|
||||
return showDisabledAccounts;
|
||||
}
|
||||
|
||||
public void setShowDisabledAccounts(boolean showDisabledAccounts) {
|
||||
this.showDisabledAccounts = showDisabledAccounts;
|
||||
}
|
||||
|
||||
public List<ApplicationRoleEntity> getCurrentAccountRoles() {
|
||||
return currentAccountRoles;
|
||||
}
|
||||
|
||||
public void setCurrentAccountRoles(List<ApplicationRoleEntity> currentAccountRoles) {
|
||||
this.currentAccountRoles = currentAccountRoles;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
public String getRepeatPassword() {
|
||||
return repeatPassword;
|
||||
}
|
||||
|
||||
public void setRepeatPassword(String repeatPassword) {
|
||||
this.repeatPassword = repeatPassword;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.util.AccountSecurityException;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.enterprise.context.SessionScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@SessionScoped
|
||||
@Named("applicationView")
|
||||
public class ApplicationView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -5515249316880163539L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationView.class);
|
||||
|
||||
@Inject
|
||||
ApplicationControl applicationService;
|
||||
|
||||
@Inject
|
||||
InstanceView instanceView;
|
||||
|
||||
@Inject
|
||||
Locale locale;
|
||||
|
||||
private ApplicationEntity currentApplication = null;
|
||||
private ApplicationEntity editApplication = null;
|
||||
private List<ApplicationEntity> applicationList = null;
|
||||
|
||||
@PostConstruct
|
||||
public void selectDefaultCurrentApplication() {
|
||||
// force applications to be loaded from database
|
||||
getAllApplications();
|
||||
if ((applicationList != null) && (!applicationList.isEmpty())) {
|
||||
currentApplication = applicationList.get(0);
|
||||
}
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("post construct executed");
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void predestroy() {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Predestroy executed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public List<ApplicationEntity> getAllApplications() {
|
||||
if (applicationList == null) {
|
||||
try {
|
||||
applicationList = applicationService.getAllApplications();
|
||||
|
||||
// if no role is assigned to user, ensure that at least current application is added
|
||||
if ((applicationList == null) || (applicationList.isEmpty())) {
|
||||
applicationList = new ArrayList<>();
|
||||
applicationList.add(instanceView.getInstanceApplication());
|
||||
}
|
||||
|
||||
return applicationList;
|
||||
} catch (AccountSecurityException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Error " + ex.getErrorCode(), ex.getLocalizedMessage(locale));
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
return applicationList;
|
||||
}
|
||||
|
||||
public void selectApplication() {
|
||||
if (currentApplication != null) {
|
||||
LOGGER.info("selected application: {}", currentApplication.getApplicationName());
|
||||
FacesUtil.addGlobalInfoMessage("Success", "Selected application " + currentApplication.getApplicationName());
|
||||
}
|
||||
}
|
||||
|
||||
public void startEditApplication() {
|
||||
this.editApplication = currentApplication;
|
||||
}
|
||||
|
||||
public void newApplication() {
|
||||
this.editApplication = new ApplicationEntity();
|
||||
}
|
||||
|
||||
public void cancelEditApplication() {
|
||||
this.editApplication = null;
|
||||
}
|
||||
|
||||
public void saveEditApplication() {
|
||||
if (editApplication == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Need to provide data");
|
||||
} else if ((editApplication.getApplicationName() == null) || (editApplication.getApplicationName().trim().equals(""))) {
|
||||
String hint;
|
||||
if (editApplication.getId() == null) {
|
||||
hint = "Cannot create application";
|
||||
} else {
|
||||
hint = "Cannot save application";
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage(hint, "Application name must not be empty");
|
||||
} else {
|
||||
currentApplication = applicationService.createOrUpdate(editApplication);
|
||||
// force reload of to update view
|
||||
applicationList = null;
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Application saved");
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteApplication() {
|
||||
if (currentApplication == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Need to provide data");
|
||||
} else if (currentApplication.getId() == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Cannot delete non persistent data");
|
||||
} else {
|
||||
String applicationName = currentApplication.getApplicationName();
|
||||
applicationService.delete(currentApplication);
|
||||
applicationList = null; // force reload to update view
|
||||
currentApplication = null;
|
||||
selectDefaultCurrentApplication();
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Application " + applicationName + " deleted");
|
||||
}
|
||||
}
|
||||
|
||||
/* *** getter / setter *** */
|
||||
public ApplicationEntity getCurrentApplication() {
|
||||
return currentApplication;
|
||||
}
|
||||
|
||||
public void setCurrentApplication(ApplicationEntity currentApplication) {
|
||||
this.currentApplication = currentApplication;
|
||||
}
|
||||
|
||||
public ApplicationEntity getEditApplication() {
|
||||
return editApplication;
|
||||
}
|
||||
|
||||
public void setEditApplication(ApplicationEntity editApplication) {
|
||||
this.editApplication = editApplication;
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.business.instance.control.ApplicationController;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* TODO - move to shared-account and remove from all applications and archetype
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Named(value = "instanceView")
|
||||
@ApplicationScoped
|
||||
public class InstanceView {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(InstanceView.class);
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
@Inject
|
||||
ApplicationController applicationController;
|
||||
|
||||
public boolean isDevelopmentVersion() {
|
||||
String instanceName = getInstanceName();
|
||||
return !instanceName.equals("Production");
|
||||
}
|
||||
|
||||
public String getInstanceName() {
|
||||
String instanceName;
|
||||
try {
|
||||
instanceName = configService.getConfigValue("base.instance");
|
||||
} catch (ConfigException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
instanceName = "unknown (" + ex.toString() + ")";
|
||||
}
|
||||
if (instanceName == null) {
|
||||
return "unknown";
|
||||
} else {
|
||||
return instanceName;
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationEntity getInstanceApplication() {
|
||||
return applicationController.getApplication();
|
||||
}
|
||||
}
|
||||
@ -1,143 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationPermissionControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ViewScoped
|
||||
@Named("permissionView")
|
||||
public class PermissionView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1469453490360990772L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(PermissionView.class);
|
||||
|
||||
@Inject
|
||||
private ApplicationView applicationView;
|
||||
|
||||
@EJB
|
||||
ApplicationPermissionControl applicationPermissionService;
|
||||
private ApplicationPermissionEntity currentPermission;
|
||||
|
||||
public List<ApplicationPermissionEntity> getAppPermissions() {
|
||||
return applicationPermissionService.getApplicationPermissions(applicationView.getCurrentApplication());
|
||||
}
|
||||
|
||||
public void saveEditPermission() throws AccountException {
|
||||
if (currentPermission != null) {
|
||||
String newPermissionName = currentPermission.getPermissionName();
|
||||
String newPermissionDescription = currentPermission.getPermissionDescription();
|
||||
if ((newPermissionName == null) || (newPermissionName.trim().length() == 0)) {
|
||||
FacesUtil.addErrorMessage("editDialogMessages", "Error", "Permission name must not be null");
|
||||
} else if ((newPermissionDescription == null) || (newPermissionDescription.trim().length() == 0)) {
|
||||
FacesUtil.addErrorMessage("editDialogMessages", "Error", "Permission name must not be null");
|
||||
} else {
|
||||
if (currentPermission.getId() == null) {
|
||||
applicationPermissionService.create(applicationView.getCurrentApplication(), newPermissionName, newPermissionDescription);
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Permission " + newPermissionName + " created");
|
||||
} else {
|
||||
applicationPermissionService.update(currentPermission);
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Permission " + newPermissionName + " updated");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationEntity getCurrentApplication() {
|
||||
if (applicationView.getCurrentApplication() == null) {
|
||||
return null;
|
||||
} else {
|
||||
return applicationView.getCurrentApplication();
|
||||
}
|
||||
}
|
||||
|
||||
public void cancelEditPermission() {
|
||||
this.currentPermission = null;
|
||||
}
|
||||
|
||||
public void newPermission() {
|
||||
this.currentPermission = new ApplicationPermissionEntity();
|
||||
}
|
||||
|
||||
public void editPermission() {
|
||||
if (currentPermission == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Please select a permission to edit");
|
||||
}
|
||||
}
|
||||
|
||||
public void deletePermission() {
|
||||
if (currentPermission == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Please select a permission to edit");
|
||||
} else {
|
||||
try {
|
||||
applicationPermissionService.delete(currentPermission);
|
||||
currentPermission = null;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Error while deleting permission.", ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getCanEdit() {
|
||||
return isPermissionSelected();
|
||||
}
|
||||
|
||||
public boolean getCanDelete() {
|
||||
return isPermissionSelected();
|
||||
}
|
||||
|
||||
/* *** getter / setter *** */
|
||||
/**
|
||||
* required setter for managedProperty
|
||||
*
|
||||
*
|
||||
* @param applicationView the injected applicationView
|
||||
*/
|
||||
public void setApplicationView(ApplicationView applicationView) {
|
||||
this.applicationView = applicationView;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity getCurrentPermission() {
|
||||
return currentPermission;
|
||||
}
|
||||
|
||||
public void setCurrentPermission(ApplicationPermissionEntity newCurrentPermission) {
|
||||
this.currentPermission = newCurrentPermission;
|
||||
|
||||
}
|
||||
|
||||
public boolean isPermissionSelected() {
|
||||
return currentPermission != null;
|
||||
}
|
||||
}
|
||||
@ -1,236 +0,0 @@
|
||||
/*
|
||||
* Copyright 2017 Joern Muehlencord <joern at muehlencord.de>.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationRoleControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import org.primefaces.event.SelectEvent;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ViewScoped
|
||||
@Named("roleView")
|
||||
public class RoleView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1669321020398119007L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(RoleView.class);
|
||||
|
||||
@Inject
|
||||
private ApplicationView applicationView;
|
||||
|
||||
@EJB
|
||||
ApplicationRoleControl applicationRoleControl;
|
||||
|
||||
private List<ApplicationRoleEntity> allRoles = null;
|
||||
private List<ApplicationPermissionEntity> currentRolePermissions = null;
|
||||
private List<ApplicationPermissionEntity> missingApplicationsPermissions = null;
|
||||
|
||||
private ApplicationRoleEntity currentRole;
|
||||
private ApplicationPermissionEntity currentPermission;
|
||||
private ApplicationPermissionEntity newPermission;
|
||||
|
||||
public ApplicationEntity getCurrentApplication() {
|
||||
return applicationView.getCurrentApplication();
|
||||
}
|
||||
|
||||
public List<ApplicationRoleEntity> getAllRoles() {
|
||||
if (allRoles == null) {
|
||||
allRoles = applicationRoleControl.getAllRoles(applicationView.getCurrentApplication());
|
||||
}
|
||||
return allRoles;
|
||||
}
|
||||
|
||||
public void startNewRole() {
|
||||
this.currentRole = new ApplicationRoleEntity(applicationView.getCurrentApplication());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Created new current role: {}", currentRole.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void cancelEditRole() {
|
||||
this.currentRole = null;
|
||||
}
|
||||
|
||||
public void saveEditRole() {
|
||||
if ((currentRole == null) || (currentRole.getRoleName() == null) || (currentRole.getRoleName().trim().length() == 0)) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Permission name must not be null");
|
||||
} else if (currentRole.getId() == null) {
|
||||
applicationRoleControl.create(currentRole);
|
||||
allRoles = null; // force reload
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Role " + currentRole.getRoleName() + " created");
|
||||
} else {
|
||||
applicationRoleControl.update(currentRole);
|
||||
allRoles = null; // force reload
|
||||
FacesUtil.addGlobalInfoMessage("Info", "Role " + currentRole.getRoleName() + " updated");
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteRole() {
|
||||
if (currentRole == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Please select a permission to edit");
|
||||
} else {
|
||||
try {
|
||||
applicationRoleControl.delete(currentRole);
|
||||
allRoles = null; // force reload
|
||||
currentRole = null;
|
||||
currentRolePermissions = null;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
|
||||
FacesUtil.addGlobalErrorMessage("Error while deleting permission.", ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean getRoleSelected() {
|
||||
return currentRole != null;
|
||||
}
|
||||
|
||||
public boolean getPermissionSelected() {
|
||||
return currentPermission != null;
|
||||
}
|
||||
|
||||
public boolean getMissingPermissionAvailable() {
|
||||
return ((missingApplicationsPermissions != null) && (!missingApplicationsPermissions.isEmpty()));
|
||||
}
|
||||
|
||||
public void onRoleSelect(SelectEvent event) {
|
||||
currentRolePermissions = null;
|
||||
currentRolePermissions = getRolePermissions();
|
||||
missingApplicationsPermissions = null;
|
||||
missingApplicationsPermissions = getMissingPermissions();
|
||||
}
|
||||
|
||||
public List<ApplicationPermissionEntity> getRolePermissions() {
|
||||
if (currentRole == null) {
|
||||
currentRolePermissions = new ArrayList<>();
|
||||
return currentRolePermissions;
|
||||
} else {
|
||||
if (currentRolePermissions == null) {
|
||||
try {
|
||||
currentRolePermissions = applicationRoleControl.getRolePermissions(currentRole);
|
||||
} catch (AccountException ex) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
|
||||
FacesUtil.addGlobalErrorMessage("Error while fetching role permissions", "see log for details");
|
||||
currentRolePermissions = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
return currentRolePermissions;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApplicationPermissionEntity> getMissingPermissions() {
|
||||
if (currentRole == null) {
|
||||
missingApplicationsPermissions = new ArrayList<>();
|
||||
return missingApplicationsPermissions;
|
||||
} else {
|
||||
if (missingApplicationsPermissions == null) {
|
||||
missingApplicationsPermissions = applicationRoleControl.getNotAssignedApplicationPermissions(currentRole);
|
||||
|
||||
}
|
||||
return missingApplicationsPermissions;
|
||||
}
|
||||
}
|
||||
|
||||
public void addRolePermission() {
|
||||
if (newPermission == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Please select a new permission first");
|
||||
} else {
|
||||
try {
|
||||
applicationRoleControl.addPermission(currentRole, newPermission);
|
||||
currentRolePermissions = null;
|
||||
missingApplicationsPermissions = null;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
|
||||
FacesUtil.addGlobalErrorMessage("Error while adding permission", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void removeRolePermission() {
|
||||
if (currentPermission == null) {
|
||||
FacesUtil.addGlobalErrorMessage("Error", "Please select a permission first");
|
||||
} else {
|
||||
try {
|
||||
applicationRoleControl.removePermission(currentRole, currentPermission);
|
||||
currentRolePermissions = null;
|
||||
missingApplicationsPermissions = null;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Error while adding permission", ex.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* *** getter / setter *** */
|
||||
public void setApplicationView(ApplicationView applicationView) {
|
||||
this.applicationView = applicationView;
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity getCurrentRole() {
|
||||
return currentRole;
|
||||
}
|
||||
|
||||
public void setCurrentRole(ApplicationRoleEntity currentRole) {
|
||||
this.currentRole = currentRole;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity getCurrentPermission() {
|
||||
return currentPermission;
|
||||
}
|
||||
|
||||
public void setCurrentPermission(ApplicationPermissionEntity currentPermission) {
|
||||
this.currentPermission = currentPermission;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity getNewPermission() {
|
||||
return newPermission;
|
||||
}
|
||||
|
||||
public void setNewPermission(ApplicationPermissionEntity newPermission) {
|
||||
this.newPermission = newPermission;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationRoleControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import java.io.Serializable;
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.validator.FacesValidator;
|
||||
import javax.faces.validator.Validator;
|
||||
import javax.faces.validator.ValidatorException;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@FacesValidator("uniqueApplicationRoleNameValidator")
|
||||
public class UniqueApplicationRoleNameValidator implements Validator, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8165013107453616719L;
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
ApplicationRoleControl applicationRoleControl;
|
||||
|
||||
@Override
|
||||
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
|
||||
|
||||
Object oldRoleNameObj = ((UIInput) component).getValue();
|
||||
String oldRoleName = "";
|
||||
if (oldRoleNameObj != null) {
|
||||
oldRoleName = oldRoleNameObj.toString();
|
||||
}
|
||||
|
||||
Object applicationObj = component.getAttributes().get("application");
|
||||
if ((applicationObj != null) && (applicationObj instanceof ApplicationEntity)) {
|
||||
ApplicationEntity application = (ApplicationEntity) applicationObj;
|
||||
if (value == null) {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Role name invalid", "Role name must not be empty"));
|
||||
}
|
||||
if (value instanceof String) {
|
||||
String roleName = (String) value;
|
||||
ApplicationRoleEntity existingRole = applicationRoleControl.findByName(application, roleName);
|
||||
if (existingRole != null) {
|
||||
if (!oldRoleName.equals(roleName)) {
|
||||
// name of role changed and there is another role with the new name already --> this must not happen
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Role name invalid", "Role already exists"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Role name invalid", "Role name must be a string value"));
|
||||
// TODO add IPRS logger - someone is trying to cheat
|
||||
}
|
||||
} else {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Application not set", "Permission name cannot be set if application is unknown"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,60 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import java.io.Serializable;
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.validator.FacesValidator;
|
||||
import javax.faces.validator.Validator;
|
||||
import javax.faces.validator.ValidatorException;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@FacesValidator("uniqueApplicationValidator")
|
||||
public class UniqueApplicationValidator implements Validator, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2526409681909574670L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(UniqueApplicationValidator.class);
|
||||
|
||||
@Inject
|
||||
ApplicationControl applicationService;
|
||||
|
||||
@Override
|
||||
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
|
||||
|
||||
Object oldAppNameObj = ((UIInput) component).getValue();
|
||||
String oldAppName = "";
|
||||
if (oldAppNameObj != null) {
|
||||
oldAppName = oldAppNameObj.toString();
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Application name invalid", "Application name must not be empty"));
|
||||
}
|
||||
if (value instanceof String) {
|
||||
String applicationname = (String) value;
|
||||
ApplicationEntity existingApplication = applicationService.findByApplicationName(applicationname);
|
||||
if (existingApplication != null) {
|
||||
if (!oldAppName.equals(applicationname)) {
|
||||
// name of application changed and there is another application with the new
|
||||
// name already --> this must not happen
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Application name invalid", "Application already exists"));
|
||||
}
|
||||
}
|
||||
LOGGER.info("Name = {}", applicationname);
|
||||
} else {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Application name invalid", "Application name must be a string value"));
|
||||
// TODO add IPRS logger - someone is trying to cheat
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
package de.muehlencord.shared.account.web.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationPermissionControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import java.io.Serializable;
|
||||
import javax.faces.application.FacesMessage;
|
||||
import javax.faces.component.UIComponent;
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.validator.FacesValidator;
|
||||
import javax.faces.validator.Validator;
|
||||
import javax.faces.validator.ValidatorException;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@FacesValidator("uniquePermissionNameValidator")
|
||||
public class UniquePermissionNameValidator implements Validator, Serializable {
|
||||
|
||||
private static final long serialVersionUID = 2526409681909574670L;
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
ApplicationPermissionControl applicationPermissionControl;
|
||||
|
||||
@Override
|
||||
public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
|
||||
|
||||
Object oldPermissionNameObj = ((UIInput) component).getValue();
|
||||
String oldPermissionName = "";
|
||||
if (oldPermissionNameObj != null) {
|
||||
oldPermissionName = oldPermissionNameObj.toString();
|
||||
}
|
||||
|
||||
Object applicationObj = component.getAttributes().get("application");
|
||||
if ((applicationObj != null) && (applicationObj instanceof ApplicationEntity)) {
|
||||
ApplicationEntity application = (ApplicationEntity) applicationObj;
|
||||
if (value == null) {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Permission name invalid", "Permission name must not be empty"));
|
||||
}
|
||||
if (value instanceof String) {
|
||||
String permissionName = (String) value;
|
||||
ApplicationPermissionEntity existingPermission = applicationPermissionControl.findPermissionByName(application, permissionName);
|
||||
if (existingPermission != null) {
|
||||
if ((!oldPermissionName.equals (permissionName))) {
|
||||
// name of permission changed and there is another permission with the new
|
||||
// name already --> this must not happen
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Permission name invalid", "Permission already exists"));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Permission name invalid", "Permission name must be a string value"));
|
||||
// TODO add IPRS logger - someone is trying to cheat
|
||||
}
|
||||
} else {
|
||||
throw new ValidatorException(new FacesMessage(FacesMessage.SEVERITY_ERROR, "Application not set", "Permission name cannot be set if application is unknown"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
|
||||
<persistence-unit name="accountPu" transaction-type="JTA">
|
||||
<provider>org.hibernate.ejb.HibernatePersistence</provider>
|
||||
<jta-data-source>java:/jboss/accountDs</jta-data-source>
|
||||
<class>de.muehlencord.shared.account.business.account.entity.AccountEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.account.entity.AccountHistoryEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.account.entity.AccountLoginEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.account.entity.ApiKeyEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.application.entity.ApplicationEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.config.entity.ConfigEntity</class>
|
||||
<class>de.muehlencord.shared.account.business.mail.entity.MailTemplateEntity</class>
|
||||
<exclude-unlisted-classes>true</exclude-unlisted-classes>
|
||||
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
|
||||
<validation-mode>NONE</validation-mode>
|
||||
<properties>
|
||||
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL94Dialect"/>
|
||||
<property name="hibernate.show_sql" value="false"/>
|
||||
<property name="hibernate.cache.use_second_level_cache" value="true"/>
|
||||
<property name="hibernate.cache.use_query_cache" value="true"/>
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
@ -1,38 +0,0 @@
|
||||
admin.loginPage=login.xhtml
|
||||
admin.indexPage=web/index.xhtml
|
||||
#admin.dateFormat=
|
||||
#admin.breadcrumbSize=5
|
||||
admin.renderMessages=true
|
||||
admin.renderAjaxStatus=false
|
||||
admin.disableFilter=true
|
||||
admin.renderBreadCrumb=false
|
||||
#admin.extensionLessUrls=false
|
||||
#admin.enableSlideMenu=true
|
||||
#admin.enableRipple=true
|
||||
#admin.rippleMobileOnly=true
|
||||
admin.renderMenuSearch=false
|
||||
#admin.renderControlSidebar=false
|
||||
#admin.controlSidebar.showOnMobile=false
|
||||
#admin.controlSidebar.leftMenuTemplate=true
|
||||
#admin.controlSidebar.fixedLayout=false
|
||||
#admin.controlSidebar.boxedLayout=false
|
||||
#admin.controlSidebar.sidebarCollapsed=false
|
||||
#admin.controlSidebar.expandOnHover=false
|
||||
#admin.controlSidebar.fixed=false
|
||||
admin.controlSidebar.darkSkin=false
|
||||
admin.autoHideMessages=false
|
||||
admin.renderFormAsterisks=true
|
||||
#admin.enableMobileHeader=true
|
||||
#admin.closableLoading=true
|
||||
#admin.messagesHideTimeout=2500
|
||||
admin.skin=skin-purple-light
|
||||
#admin.autoShowNavbar=true
|
||||
#admin.loadingImage=ajaxloadingbar.gif
|
||||
#admin.iconsEffect=true
|
||||
#admin.rippleElements=.ripplelink,button.ui-button:not([class*=ui-picklist]):not([class*=ui-orderlist]),li.ui-selectlistbox-item,li.ui-multiselectlistbox-item,.ui-selectonemenu-label,.ui-selectcheckboxmenu,\
|
||||
# .ui-autocomplete-dropdown, .ui-autocomplete-item, .ui-splitbutton-menubutton, .ui-splitbutton button.ui-button,.input-group, .ui-selectbooleanbutton, \
|
||||
# div.ui-button,.ui-chkbox-icon, .ui-link, .form-control, .btn, .ui-sortable-column,.ui-link, .ui-tabs-nav > li,.ui-selectonemenu-trigger, \
|
||||
# .ui-accordion-header, .treeview, .sidebar-toggle, .ui-radiobutton-icon, td[role="gridcell"], .ui-selectcheckboxmenu-trigger,.ui-paginator-page, \
|
||||
# .ui-panelmenu-header > a, a#layout-setup, .control-sidebar div#restore-defaults > a, .control-sidebar div.ui-selectbooleancheckbox .ui-chkbox, \
|
||||
# .control-sidebar span.control-sidebar-subheading > label, .control-sidebar a.skin-link, button.navbar-toggle, li.dropdown > a
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
build.version=${project.version}
|
||||
build.timestamp=${timestamp}
|
||||
application.uuid=${applicationUuid}
|
||||
@ -1,133 +0,0 @@
|
||||
header_login=Login
|
||||
header_reset_password=Reset password
|
||||
message_username_password=Please enter your user name and a new password
|
||||
button_login=Login
|
||||
button_cancel=Cancel
|
||||
button_password_lost=Password lost?
|
||||
label_username=Username
|
||||
label_password=Password
|
||||
label_new_password=New Password
|
||||
button_password_reset=Reset password
|
||||
header_passwort_lost=Lost password
|
||||
message_start_password_reset=Please enter your username to start the password recovery procedure
|
||||
menu_dashboard=Dashboard
|
||||
menu_events=Events
|
||||
menu_administration=Administration
|
||||
menu_overview=Overview
|
||||
menu_emails=Emails
|
||||
menu_account=Account
|
||||
menu_config=Config
|
||||
menu_logout=Logout
|
||||
button_new=New
|
||||
button_delete=Delete
|
||||
button_edit=Edit
|
||||
button_reload=Reload
|
||||
label_name=Name
|
||||
label_description=Description
|
||||
label_event_date=Event Date
|
||||
label_reservation=Reservation
|
||||
label_reservation_from_to=Reservation from/to
|
||||
label_actions=Actions
|
||||
message_confirm=Are you sure?
|
||||
button_setup=Setup
|
||||
button_reservations=Reservations
|
||||
label_event_name=Event Name
|
||||
label_event_item_desc=Event Item Description
|
||||
label_timezone=Timezone
|
||||
label_event_start=Event Start
|
||||
label_event_end=Event End
|
||||
label_reservation_autostart=Reservation start
|
||||
label_reservation_autoend=Reservation end
|
||||
label_reservation_active=Reservation active
|
||||
label_reservation_max_items=Max Items
|
||||
label_booking_deadline=Booking deadline
|
||||
label_template_validation=Email validation mail template
|
||||
label_template_confirmation=Event confirmation mail template
|
||||
label_template_waitlist=Event waitlist mail template
|
||||
message_event_not_found=Event not found
|
||||
label_items=Items
|
||||
label_costs=Costs
|
||||
label_all=All
|
||||
label_yes=Yes
|
||||
label_no=No
|
||||
label_status=Status
|
||||
label_firstname=Firstname
|
||||
label_lastname=Lastname
|
||||
label_emailaddress=Emailaddress
|
||||
label_comment=Comment
|
||||
label_email_confirmed=Email confirmed
|
||||
label_booking_number=Booking Number
|
||||
label_booking_executed=booking executed
|
||||
tt_log_entries=Show log entries
|
||||
tt_cancel_reservation=Cancel the current reservation
|
||||
tt_send_email_again=Send email again
|
||||
tt_move_from_wl=Move from waitlist
|
||||
tt_fix_reservation=Try to fix the current reservation
|
||||
tt_edit_reservation=Edit the reservation
|
||||
button_refresh_free=Refresh free
|
||||
button_manual_reserve=Reserve
|
||||
button_export=Export
|
||||
label_amount=Amount
|
||||
label_select=Select
|
||||
label_created_by=Created by
|
||||
label_ip=IP
|
||||
label_ip_forwarded=IP (forwarded)
|
||||
label_value=Value
|
||||
label_useragent=Useragent
|
||||
button_ok=Ok
|
||||
message_comment=Please add a comment
|
||||
menu_help=Help
|
||||
label_event=Event
|
||||
label_active=Active
|
||||
label_waitlist=Waitlist
|
||||
label_is_waitlist=Is waitlist
|
||||
label_order=Order
|
||||
message_dynamic_numbering=dynamic numbering (put %n as placeholder)
|
||||
label_start_number=Start Number
|
||||
label_end_number=End Number
|
||||
header_item_def=Define items for event
|
||||
message_no_event_items=No event item defined
|
||||
button_overview=Overview
|
||||
label_reservation_auto_start=Automatically switch on/off
|
||||
label_item_public=Item public?
|
||||
label_is_publicitem=Is public
|
||||
label_customer_comment=Customer comment
|
||||
label_change_comment=Change comment
|
||||
label_existing_items=current items
|
||||
label_new_items=new items
|
||||
label_available_items=available items
|
||||
label_no_records=No records found.
|
||||
button_mail=Mail
|
||||
header_email_distribution=Email distribution
|
||||
label_template=Template
|
||||
label_demomode=Demo mode
|
||||
message_invalid_email=Please provide a valid email address
|
||||
menu_permissions=Permissions
|
||||
button_save=Save
|
||||
menu_groups=Groups
|
||||
message_email_sent=email sent
|
||||
message_email_with_error=emails with error
|
||||
message_no_email=no email address defined
|
||||
message_email_not_sent=Error while sending emails
|
||||
label_seating=Seating
|
||||
label_attachments=Attachments
|
||||
label_language=Language
|
||||
label_subject=Subject
|
||||
label_bytes=Bytes
|
||||
label_upload=Upload
|
||||
header_export=Export
|
||||
label_export_type=Export Type
|
||||
label_filtered=Filtered
|
||||
label_include_deleted=Include deleted
|
||||
label_include_log=Include Logs
|
||||
label_template_booking_executed=Booking executed template
|
||||
label_street=Street
|
||||
label_zipCode=ZIP Code
|
||||
label_city=City
|
||||
label_groupName=Groupname
|
||||
label_phoneNumber=Phone Number
|
||||
label_template_waitlist_cancelled=Waitlist cancelled mail template
|
||||
msgs_menu_status=Status
|
||||
menu_status=Status
|
||||
button_add=Add
|
||||
passwords_different=Passwords do not match, please check input
|
||||
@ -1,134 +0,0 @@
|
||||
|
||||
header_login=Anmeldung
|
||||
header_reset_password=Passwort zur\u00fccksetzten
|
||||
message_username_password=Bitte geben Deinen Benutzernamen und dein Passwort ein
|
||||
button_login=Anmelden
|
||||
button_cancel=Abbruch
|
||||
button_password_lost=Passwort vergessen?
|
||||
label_username=Benutzername
|
||||
label_password=Passwort
|
||||
label_new_password=Neues Passwort
|
||||
button_password_reset=Passwort zur\u00fccksetzten
|
||||
header_passwort_lost=Passwort vergessen
|
||||
message_start_password_reset=Bitte gib deinen Benutzernamen ein um das Zur\u00fccksetzten des Passworts zu starten.
|
||||
menu_dashboard=Dashbaord
|
||||
menu_events=Veranstaltungen
|
||||
menu_administration=Administration
|
||||
menu_overview=\u00dcbersicht
|
||||
menu_emails=E-Mails
|
||||
menu_account=Benutzer
|
||||
menu_config=Konfiguration
|
||||
menu_logout=Abmelden
|
||||
button_new=Neu
|
||||
button_delete=L\u00f6schen
|
||||
button_edit=Bearbeiten
|
||||
button_reload=Aktualisieren
|
||||
label_name=Name
|
||||
label_description=Beschreibung
|
||||
label_event_date=Veranstaltungsdatum
|
||||
label_reservation=Reservierung
|
||||
label_reservation_from_to=Reservierung von/bis
|
||||
label_actions=Aktionen
|
||||
message_confirm=Bist du sicher?
|
||||
button_setup=Setup
|
||||
button_reservations=Reservierungen
|
||||
label_event_name=Veranstaltungsname
|
||||
label_event_item_desc=Veranstaltungsobjekte
|
||||
label_timezone=Zeitzone
|
||||
label_event_start=Veranstaltungsbeginn
|
||||
label_event_end=Veranstaltungsende
|
||||
label_reservation_autostart=Reservierung von
|
||||
label_reservation_autoend=Reservierung bis
|
||||
label_reservation_active=Reservierung aktiv
|
||||
label_reservation_max_items=Maximale Objekte
|
||||
label_booking_deadline=Buchungsfrist
|
||||
label_template_validation=Vorlage Emailvalidierung
|
||||
label_template_confirmation=Vorlage Reservierungsbest\u00e4tigung
|
||||
label_template_waitlist=Vorlage Wartelist
|
||||
message_event_not_found=Veranstaltung nicht gefunden
|
||||
label_items=Objekte
|
||||
label_costs=Kosten
|
||||
label_all=Alle
|
||||
label_yes=Ja
|
||||
label_no=Nein
|
||||
label_status=Status
|
||||
label_firstname=Vorname
|
||||
label_lastname=Nachname
|
||||
label_emailaddress=E-Mail-Adresse
|
||||
label_comment=Kommentar
|
||||
label_email_confirmed=E-Mail best\u00e4tigt
|
||||
label_booking_number=Buchungsnummer
|
||||
label_booking_executed=Buchungs ausgef\u00fchrt
|
||||
tt_log_entries=Logbucheintr\u00e4ge
|
||||
tt_cancel_reservation=Storniere die Reservierung
|
||||
tt_send_email_again=Sende E-Mail erneut
|
||||
tt_move_from_wl=Schiebe von Warteliste
|
||||
tt_fix_reservation=Versuche den Fehler zu beheben
|
||||
tt_edit_reservation=Bearbeite die Reservierung
|
||||
button_refresh_free=Frei aktualisieren
|
||||
button_manual_reserve=Reservieren
|
||||
button_export=Exportieren
|
||||
label_amount=Anzahl
|
||||
label_select=W\u00e4hlen
|
||||
label_created_by=Erzeugt durch
|
||||
label_ip=IP
|
||||
label_ip_forwarded=IP (forwarded)
|
||||
label_value=Wert
|
||||
label_useragent=Useragent
|
||||
button_ok=Ok
|
||||
message_comment=Bitte geben Sie einen Kommentar an
|
||||
menu_help=Hilfe
|
||||
label_event=Veranstaltung
|
||||
label_active=Aktiv
|
||||
label_waitlist=Warteliste
|
||||
label_is_waitlist=Ist Warteliste
|
||||
label_order=Reihenfolge
|
||||
message_dynamic_numbering=Dynamische Nummerierung (%n als Platzhalter)
|
||||
label_start_number=Startnummer
|
||||
label_end_number=Endnummer
|
||||
header_item_def=Objekte f\u00fcr Veranstaltung
|
||||
message_no_event_items=Keine Objekte definiert
|
||||
button_overview=\u00dcbersicht
|
||||
label_reservation_auto_start=Automatisch ein/ausschalten
|
||||
label_item_public=\u00d6ffentlich verf\u00fcgar?
|
||||
label_is_publicitem=\u00d6ffentlich
|
||||
label_customer_comment=Kundenkommentar
|
||||
label_change_comment=\u00c4nderungskommentar
|
||||
label_existing_items=aktuelle Objekte
|
||||
label_new_items=neue Objekte
|
||||
label_available_items=verf\u00fcgbare Objekte
|
||||
label_no_records=Keine Daten gefunden.
|
||||
button_mail=E-Mail
|
||||
header_email_distribution=Emailversand
|
||||
label_template=Vorlage
|
||||
label_demomode=Demomodus
|
||||
message_invalid_email=Bitte geben Sie eine g\u00fcltige Emailadresse an
|
||||
menu_permissions=Berechtigungen
|
||||
button_save=Speichern
|
||||
menu_groups=Gruppen
|
||||
message_email_sent=Email gesendet
|
||||
message_email_with_error=Emails mit Fehler
|
||||
message_no_email=keine Emailadresse verf\u00fcgbar
|
||||
message_email_not_sent=Fehler beim Versenden der Email
|
||||
label_seating=Saalplan Platz
|
||||
label_attachments=Attachments
|
||||
label_language=Sprache
|
||||
label_subject=Betreff
|
||||
label_bytes=Bytes
|
||||
label_upload=Upload
|
||||
header_export=Exportieren
|
||||
label_export_type=Export Art
|
||||
label_filtered=Gefiltert
|
||||
label_include_deleted=Einschlie\u00dflich gel\u00f6scht
|
||||
label_include_log=mit Logbuch
|
||||
label_template_booking_executed=Vorlage Buchung durchgef\u00fchrt
|
||||
label_street=Stra\u00dfe
|
||||
label_zipCode=PLZ
|
||||
label_city=Ort
|
||||
label_groupName=Gruppenname
|
||||
label_phoneNumber=Telefonnummer
|
||||
label_template_waitlist_cancelled=Vorlage Warteliste Abbruch
|
||||
msgs_menu_status=Status
|
||||
menu_status=Status
|
||||
button_add=Hinzuf\u00fcgen
|
||||
passwords_different=Passw\u00f6rter stimmen \u00fcberein, bitte \u00fcberpr\u00fcfen Sie ihre Eingabe
|
||||
@ -1,134 +0,0 @@
|
||||
|
||||
header_login=Login
|
||||
header_reset_password=Reset password
|
||||
message_username_password=Please enter your user name and a new password
|
||||
button_login=Login
|
||||
button_cancel=Cancel
|
||||
button_password_lost=Password lost?
|
||||
label_username=Username
|
||||
label_password=Password
|
||||
label_new_password=New Password
|
||||
button_password_reset=Reset password
|
||||
header_passwort_lost=Lost password
|
||||
message_start_password_reset=Please enter your username to start the password recovery procedure
|
||||
menu_dashboard=Dashboard
|
||||
menu_events=Events
|
||||
menu_administration=Administration
|
||||
menu_overview=Overview
|
||||
menu_emails=Emails
|
||||
menu_account=Account
|
||||
menu_config=Config
|
||||
menu_logout=Logout
|
||||
button_new=New
|
||||
button_delete=Delete
|
||||
button_edit=Edit
|
||||
button_reload=Reload
|
||||
label_name=Name
|
||||
label_description=Description
|
||||
label_event_date=Event Date
|
||||
label_reservation=Reservation
|
||||
label_reservation_from_to=Reservation from/to
|
||||
label_actions=Actions
|
||||
message_confirm=Are you sure?
|
||||
button_setup=Setup
|
||||
button_reservations=Reservations
|
||||
label_event_name=Event Name
|
||||
label_event_item_desc=Event Item Description
|
||||
label_timezone=Timezone
|
||||
label_event_start=Event Start
|
||||
label_event_end=Event End
|
||||
label_reservation_autostart=Reservation Start
|
||||
label_reservation_autoend=Reservation End
|
||||
label_reservation_active=Reservation active
|
||||
label_reservation_max_items=Max Items
|
||||
label_booking_deadline=Booking deadline
|
||||
label_template_validation=Email validation mail template
|
||||
label_template_confirmation=Event confirmation mail template
|
||||
label_template_waitlist=Event waitlist mail template
|
||||
message_event_not_found=Event not found
|
||||
label_items=Items
|
||||
label_costs=Costs
|
||||
label_all=All
|
||||
label_yes=Yes
|
||||
label_no=No
|
||||
label_status=Status
|
||||
label_firstname=Firstname
|
||||
label_lastname=Lastname
|
||||
label_emailaddress=Emailaddress
|
||||
label_comment=Comment
|
||||
label_email_confirmed=Email confirmed
|
||||
label_booking_number=Booking Number
|
||||
label_booking_executed=booking executed
|
||||
tt_log_entries=Show log entries
|
||||
tt_cancel_reservation=Cancel the current reservation
|
||||
tt_send_email_again=Send email again
|
||||
tt_move_from_wl=Move from waitlist
|
||||
tt_fix_reservation=Try to fix the current reservation
|
||||
tt_edit_reservation=Edit the reservation
|
||||
button_refresh_free=Refresh free
|
||||
button_manual_reserve=Reserve
|
||||
button_export=Export
|
||||
label_amount=Amount
|
||||
label_select=Select
|
||||
label_created_by=Created by
|
||||
label_ip=IP
|
||||
label_ip_forwarded=IP (forwarded)
|
||||
label_value=Value
|
||||
label_useragent=Useragent
|
||||
button_ok=Ok
|
||||
message_comment=Please add a comment
|
||||
menu_help=Help
|
||||
label_event=Event
|
||||
label_active=Active
|
||||
label_waitlist=Waitlist
|
||||
label_is_waitlist=Is waitlist
|
||||
label_order=Reservation Order
|
||||
message_dynamic_numbering=dynamic numbering (put %n as placeholder)
|
||||
label_start_number=Start Number
|
||||
label_end_number=End Number
|
||||
header_item_def=Define items for event
|
||||
message_no_event_items=No event item defined
|
||||
button_overview=Overview
|
||||
label_reservation_auto_start=Automatically switch on/off
|
||||
label_item_public=Item public?
|
||||
label_is_publicitem=Is public
|
||||
label_customer_comment=Customer comment
|
||||
label_change_comment=Change comment
|
||||
label_existing_items=current items
|
||||
label_new_items=new items
|
||||
label_available_items=available items
|
||||
label_no_records=No records found.
|
||||
button_mail=Mail
|
||||
header_email_distribution=Email distribution
|
||||
label_template=Template
|
||||
label_demomode=Demo mode
|
||||
message_invalid_email=Please provide a valid email address
|
||||
menu_permissions=Permissions
|
||||
button_save=Save
|
||||
menu_groups=Groups
|
||||
message_email_sent=email sent
|
||||
message_email_with_error=emails with error
|
||||
message_no_email=no email address defined
|
||||
message_email_not_sent=Error while sending emails
|
||||
label_seating=Seating
|
||||
label_attachments=Anh\u00e4nge
|
||||
label_language=Language
|
||||
label_subject=Subject
|
||||
label_bytes=Bytes
|
||||
label_upload=Hochladen
|
||||
header_export=Export
|
||||
label_export_type=Export Type
|
||||
label_filtered=Filtered
|
||||
label_include_deleted=Include deleted
|
||||
label_include_log=Include Logs
|
||||
label_template_booking_executed=Booking executed template
|
||||
label_street=Street
|
||||
label_zipCode=ZIP Code
|
||||
label_city=City
|
||||
label_groupName=Groupname
|
||||
label_phoneNumber=Phone Number
|
||||
label_template_waitlist_cancelled=Waitlist cancelled mail template
|
||||
msgs_menu_status=Status
|
||||
menu_status=Status
|
||||
button_add=Add
|
||||
passwords_different=Passwords do not match, please check input
|
||||
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
|
||||
version="1.1"
|
||||
bean-discovery-mode="all">
|
||||
</beans>
|
||||
@ -1,22 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<faces-config version="2.2"
|
||||
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-facesconfig_2_2.xsd">
|
||||
|
||||
<application>
|
||||
<el-resolver>org.primefaces.application.exceptionhandler.PrimeExceptionHandlerELResolver</el-resolver>
|
||||
|
||||
<locale-config>
|
||||
<default-locale>en</default-locale>
|
||||
<supported-locale>en</supported-locale>
|
||||
<supported-locale>de</supported-locale>
|
||||
</locale-config>
|
||||
<!-- register own messages for general i18n support -->
|
||||
<resource-bundle>
|
||||
<base-name>de.muehlencord.shared.account.web.presentation.messages</base-name>
|
||||
<var>msgs</var>
|
||||
</resource-bundle>
|
||||
</application>
|
||||
|
||||
</faces-config>
|
||||
@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jboss-web version="10.0"
|
||||
xmlns="http://www.jboss.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee http://www.jboss.org/j2ee/schema/jboss-web_7_2.xsd">
|
||||
<context-root>${context.root}</context-root>
|
||||
</jboss-web>
|
||||
@ -1,59 +0,0 @@
|
||||
[main]
|
||||
|
||||
# Context factory required for LDAP
|
||||
${shiro.contextFactory}
|
||||
|
||||
cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager
|
||||
securityManager.cacheManager = $cacheManager
|
||||
|
||||
# DataSource Setup
|
||||
datasource = org.apache.shiro.jndi.JndiObjectFactory
|
||||
datasource.resourceName = java:/jboss/accountDs
|
||||
datasource.resourceRef = true
|
||||
|
||||
# HashService
|
||||
hashService = org.apache.shiro.crypto.hash.DefaultHashService
|
||||
hashService.hashIterations = 500000
|
||||
hashService.hashAlgorithmName = SHA-512
|
||||
hashService.generatePublicSalt = true
|
||||
|
||||
# Password service
|
||||
passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
|
||||
passwordService.hashService = $hashService
|
||||
|
||||
# Required password matcher
|
||||
${shiro.passwordMatcher}
|
||||
|
||||
# LDAP Realm setup
|
||||
${shiro.ldapRealm}
|
||||
|
||||
# JDBC Realm setup
|
||||
jdbcRealm = de.muehlencord.shared.account.shiro.realm.AccountRealm
|
||||
jdbcRealm.applicationId = ${applicationUuid}
|
||||
jdbcRealm.credentialsMatcher = $passwordMatcher
|
||||
jdbcRealm.dataSource = $datasource
|
||||
|
||||
# Activate realms
|
||||
authcStrategy = ${shiro.authcStrategy}
|
||||
securityManager.realms = ${shiro.realms}
|
||||
securityManager.authenticator.authenticationStrategy = $authcStrategy
|
||||
|
||||
# Setup authentication filter
|
||||
authc = de.muehlencord.shirofaces.filter.FacesAjaxAwarePassThruAuthenticationFilter
|
||||
authc.loginUrl = /login.xhtml
|
||||
authc.successUrl = /web/index.xhtml
|
||||
|
||||
roles.unauthorizedUrl = /error/accessDenied.xhtml
|
||||
|
||||
#
|
||||
# filter setup
|
||||
#
|
||||
[urls]
|
||||
/public/**=anon
|
||||
/resources/**=anon
|
||||
/fonts/**=anon
|
||||
/javax.faces.resource/**=anon
|
||||
/login.xhtml=authc
|
||||
/logout.xhtml=logout
|
||||
/**=authc
|
||||
# /web/**=authc
|
||||
@ -1,123 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
|
||||
<display-name>reservation-system-backed</display-name>
|
||||
<context-param>
|
||||
<param-name>javax.faces.PROJECT_STAGE</param-name>
|
||||
<param-value>${jsf.projectStage}</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>javax.faces.FACELETS_BUFFER_SIZE</param-name>
|
||||
<param-value>1048576</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>primefaces.THEME</param-name>
|
||||
<param-value>admin</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>primefaces.FONT_AWESOME</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
<context-param>
|
||||
<param-name>primefaces.MOVE_SCRIPTS_TO_BOTTOM</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
<servlet>
|
||||
<servlet-name>FacesServlet</servlet-name>
|
||||
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet-mapping>
|
||||
<servlet-name>FacesServlet</servlet-name>
|
||||
<url-pattern>*.xhtml</url-pattern>
|
||||
</servlet-mapping>
|
||||
<session-config>
|
||||
<session-timeout>
|
||||
30
|
||||
</session-timeout>
|
||||
</session-config>
|
||||
<welcome-file-list>
|
||||
<welcome-file>index.xhtml</welcome-file>
|
||||
</welcome-file-list>
|
||||
<!-- Shiro Web Environment -->
|
||||
<listener>
|
||||
<listener-class>org.apache.shiro.web.env.EnvironmentLoaderListener</listener-class>
|
||||
</listener>
|
||||
<filter>
|
||||
<display-name>ShiroFilter</display-name>
|
||||
<filter-name>shiroFilter</filter-name>
|
||||
<filter-class>org.apache.shiro.web.servlet.ShiroFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>shiroFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>INCLUDE</dispatcher>
|
||||
<dispatcher>ERROR</dispatcher>
|
||||
</filter-mapping>
|
||||
<!-- Faces Exception Filter -->
|
||||
<filter>
|
||||
<display-name>FacesExceptionFilter</display-name>
|
||||
<filter-name>facesExceptionFilter</filter-name>
|
||||
<filter-class>org.omnifaces.filter.FacesExceptionFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>facesExceptionFilter</filter-name>
|
||||
<servlet-name>FacesServlet</servlet-name>
|
||||
</filter-mapping>
|
||||
<!-- Content Security Policy headers -->
|
||||
<filter>
|
||||
<filter-name>contentSecurityFilter</filter-name>
|
||||
<filter-class>de.muehlencord.sf.filter.ContentSecurityPolicyFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>report-only</param-name>
|
||||
<param-value>false</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>default-src</param-name>
|
||||
<param-value>'none'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>img-src</param-name>
|
||||
<param-value>'self'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>script-src</param-name>
|
||||
<param-value>'self' 'unsafe-inline' 'unsafe-eval'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>style-src</param-name>
|
||||
<param-value>'self' 'unsafe-inline'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>connect-src</param-name>
|
||||
<param-value>'self'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>font-src</param-name>
|
||||
<param-value>'self'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>object-src</param-name>
|
||||
<param-value>'none'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>media-src</param-name>
|
||||
<param-value>'none'</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>child-src</param-name>
|
||||
<param-value>'none'</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
<!-- Security related headers -->
|
||||
<filter>
|
||||
<display-name>OwaspStandardFilter</display-name>
|
||||
<filter-name>owaspStandardFilter</filter-name>
|
||||
<filter-class>de.muehlencord.sf.filter.OwaspStandardFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>owaspStandardFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
</web-app>
|
||||
@ -1,23 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:shiro="http://shiro.apache.org/tags">
|
||||
|
||||
<ui:define name="head">
|
||||
<meta http-equiv="refresh" content="0; URL=web/index.xhtml" />
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body">
|
||||
<p:panel id = "redirectPanel" header="Redirect" styleClass="card box-info">
|
||||
<h:form id="redirectForm">
|
||||
<p:link href="web/index.xhtml" value="Home" />
|
||||
</h:form>
|
||||
</p:panel>
|
||||
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@ -1,96 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8' ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:f="http://java.sun.com/jsf/core"
|
||||
xmlns:p="http://primefaces.org/ui">
|
||||
<h:head>
|
||||
<title>Login Page</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link rel="shortcut icon" href="#{resource['images/favicon/favicon.ico']}" />
|
||||
<h:outputStylesheet name="css/admin.css" />
|
||||
|
||||
<style type="text/css">
|
||||
/* below css hides growls in small screens and makes messages visible */
|
||||
@media (max-width: 768px) {
|
||||
|
||||
body div.ui-growl {
|
||||
display: none;
|
||||
}
|
||||
|
||||
body div.ui-messages {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
/* below css hides messages in medium/big devices and makes growl visible in such devices */
|
||||
@media (min-width: 769px) {
|
||||
body div.ui-growl {
|
||||
display: block;
|
||||
}
|
||||
body div.ui-messages {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
body.login-page {
|
||||
background-color: transparent;
|
||||
}
|
||||
html {
|
||||
background: url(#{resource[ 'images:login-bg.png' ]}) no-repeat center center fixed;
|
||||
-webkit-background-size: cover;
|
||||
-moz-background-size: cover;
|
||||
-o-background-size: cover;
|
||||
background-size: cover;
|
||||
}
|
||||
</style>
|
||||
|
||||
</h:head>
|
||||
<h:body styleClass="hold-transition login-page">
|
||||
<p:growl sticky="true">
|
||||
<p:autoUpdate />
|
||||
</p:growl>
|
||||
<div id="loader" class="load-bar" style="display: none">
|
||||
<div class="bar"></div>
|
||||
<div class="bar"></div>
|
||||
<div class="bar"></div>
|
||||
</div>
|
||||
|
||||
<div class="login-box">
|
||||
<div class="login-logo">
|
||||
<p:link href="/web/accounts.xhtml"><b>Account </b>Management</p:link>
|
||||
<h:outputLabel rendered="#{instanceView.developmentVersion}" value="#{instanceView.instanceName}" />
|
||||
</div>
|
||||
<!-- /.login-logo -->
|
||||
<div class="box login-box-body">
|
||||
<h:form>
|
||||
<p:focus context="panel" for="username" />
|
||||
|
||||
<p class="login-box-msg">Sign in to start your session</p>
|
||||
<p:messages closable="true" />
|
||||
|
||||
|
||||
<div id="panel" class="form-group has-feedback">
|
||||
<p:inputText id="username" value="#{loginView.username}" styleClass="form-control" placeholder="Username"
|
||||
required="true" autocomplete="off"
|
||||
requiredMessage="Username is required."/>
|
||||
<i class="fa fa-user form-control-feedback"></i>
|
||||
</div>
|
||||
<div class="form-group has-feedback">
|
||||
<p:inputText value="#{loginView.password}" type="password" styleClass="form-control"
|
||||
placeholder="Password" required="true" autocomplete="off" size="40"
|
||||
requiredMessage="Password is required."/>
|
||||
<i class="fa fa-lock form-control-feedback" style="font-size: 18px" ></i>
|
||||
</div>
|
||||
<div class="row">
|
||||
<p:spacer height="10"/>
|
||||
<div class="col-xs-12">
|
||||
<p:commandButton styleClass="btn btn-success btn-block" onclick="showBar()"
|
||||
action="#{loginView.authenticate}" oncomplete="if(args.validationFailed) { hideBar()}"
|
||||
value="Sign In" process="@form" update="@form" icon="fa fa-sign-in" iconPos="left"/>
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</div>
|
||||
<!-- /.login-box-body -->
|
||||
</div>
|
||||
</h:body>
|
||||
</html>
|
||||
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml">
|
||||
|
||||
<ui:define name="title">
|
||||
Logout
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body">
|
||||
<h2>You are logged out. </h2>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
To change this license header, choose License Headers in Project Properties.
|
||||
To change this template file, choose Tools | Templates
|
||||
and open the template in the editor.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:composite="http://java.sun.com/jsf/composite"
|
||||
xmlns:p="http://primefaces.org/ui">
|
||||
<composite:interface />
|
||||
|
||||
<composite:implementation>
|
||||
<p:confirmDialog global="true" showEffect="fade" hideEffect="fade" styleClass="box-solid box-danger">
|
||||
<p:commandButton value="Yes" type="button" styleClass="btn-material btn-primary ui-confirmdialog-yes"
|
||||
icon="fa fa-check"/>
|
||||
<p:commandButton value="No" type="button" styleClass="btn-material btn-danger ui-confirmdialog-no"
|
||||
icon="fa fa-close"/>
|
||||
</p:confirmDialog>
|
||||
</composite:implementation>
|
||||
</html>
|
||||
@ -1,18 +0,0 @@
|
||||
/*
|
||||
To change this license header, choose License Headers in Project Properties.
|
||||
To change this template file, choose Tools | Templates
|
||||
and open the template in the editor.
|
||||
*/
|
||||
/*
|
||||
Created on : 24.10.2018, 19:31:57
|
||||
Author : Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
|
||||
.watermark {
|
||||
position: absolute;
|
||||
opacity: 0.25;
|
||||
font-size: 3em;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
z-index: 1000;
|
||||
}
|
||||
@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="ISO-8859-1" ?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:h="http://java.sun.com/jsf/html"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
|
||||
<title>Account Management</title>
|
||||
</head>
|
||||
<body>
|
||||
<ui:composition>
|
||||
© Joern Muehlencord - Account Management - version ${applicationController.version} - build date ${applicationController.buildDate}
|
||||
</ui:composition>
|
||||
</body>
|
||||
</html>
|
||||
@ -1,62 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:shiro="http://shiro.apache.org/tags">
|
||||
|
||||
|
||||
<shiro:authenticated>
|
||||
<h:form id="menuform">
|
||||
<ul class="sidebar-menu tree" data-widget="tree">
|
||||
|
||||
<li>
|
||||
<p:link outcome="/web/index.xhtml">
|
||||
<i class="fa fa-home"></i>
|
||||
<span>Home</span>
|
||||
</p:link>
|
||||
</li>
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.applicationListAll}">
|
||||
<li>
|
||||
<p:link outcome="/web/applications.xhtml">
|
||||
<i class="fa fa-tablet"></i>
|
||||
<span>Applications</span>
|
||||
</p:link>
|
||||
</li>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<shiro:hasAnyPermission name="#{permissionConstants.permissionsCombined}">
|
||||
<li>
|
||||
<p:link outcome="/web/permissions.xhtml">
|
||||
<i class="fa fa-list-ul"></i>
|
||||
<span>Permissions</span>
|
||||
</p:link>
|
||||
</li>
|
||||
</shiro:hasAnyPermission>
|
||||
|
||||
<shiro:hasAnyPermission name="#{permissionConstants.rolesCombined}">
|
||||
<li>
|
||||
<p:link outcome="/web/roles.xhtml">
|
||||
<i class="fa fa-circle"></i>
|
||||
<span>Roles</span>
|
||||
</p:link>
|
||||
</li>
|
||||
</shiro:hasAnyPermission>
|
||||
|
||||
<li>
|
||||
<p:link outcome="/web/accounts.xhtml">
|
||||
<i class="fa fa-user"></i>
|
||||
<span>Accounts</span>
|
||||
</p:link>
|
||||
</li>
|
||||
<li>
|
||||
<p:commandLink target="/logout.xhtml" actionListener="#{loginView.logout}">
|
||||
<i class="fa fa-sign-out"></i>
|
||||
<span>Logout</span>
|
||||
</p:commandLink>
|
||||
</li>
|
||||
</ul>
|
||||
</h:form>
|
||||
</shiro:authenticated>
|
||||
</ui:composition>
|
||||
@ -1,50 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
Copyright 2018 joern@muehlencord.de
|
||||
|
||||
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
|
||||
|
||||
http://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.
|
||||
-->
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/admin.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html">
|
||||
|
||||
<ui:define name="head">
|
||||
<title>Account UI</title>
|
||||
<link rel="shortcut icon" href="#{resource['images/favicon/favicon.ico']}" />
|
||||
<h:outputStylesheet name="css/admin.css" />
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="logo-lg">
|
||||
Account Management
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="logo-mini">
|
||||
AM
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="menu">
|
||||
<ui:include src="/resources/template/leftmenu.xhtml"/>
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="footer">
|
||||
<ui:include src="/resources/template/footer.xhtml"/>
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="content-end">
|
||||
<h:outputLabel styleClass="watermark" rendered="#{instanceView.developmentVersion}" value="#{instanceView.instanceName}" />
|
||||
</ui:define>
|
||||
|
||||
|
||||
</ui:composition>
|
||||
@ -1,341 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:co="http://java.sun.com/jsf/composite/composite"
|
||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:o="http://omnifaces.org/ui"
|
||||
xmlns:composite="http://xmlns.jcp.org/jsf/composite/composite"
|
||||
xmlns:shiro="http://shiro.apache.org/tags">
|
||||
|
||||
<ui:define name="title">
|
||||
Account Overview
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="description">
|
||||
for #{applicationView.currentApplication.applicationName}
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body">
|
||||
<p:panel styleClass="box-solid" rendered="#{! empty applicationView.currentApplication}">
|
||||
<h:form id="accountForm" prependId="false">
|
||||
<p:dataTable id="accountTable" value="#{accountView.accounts}" var="account" rowKey="#{account.username}" selectionMode="single" selection="#{accountView.currentAccount}"
|
||||
styleClass="box-primary">
|
||||
<p:ajax event="rowSelect" update="buttonPanel" listener="#{accountView.selectAccount}" />
|
||||
<p:ajax event="rowUnselect" update="buttonPanel" listener="#{accountView.unselectAccount}" />
|
||||
<p:column headerText="Username">
|
||||
<h:outputText value="#{account.username}" />
|
||||
</p:column>
|
||||
<p:column headerText="Lastname">
|
||||
<h:outputText value="#{account.lastname}" />
|
||||
</p:column>
|
||||
<p:column headerText="Firstname">
|
||||
<h:outputText value="#{account.firstname}" />
|
||||
</p:column>
|
||||
<p:column headerText="Email">
|
||||
<h:outputText value="#{account.emailaddress}" />
|
||||
</p:column>
|
||||
<p:column headerText="Status">
|
||||
<h:outputText value="#{account.status}" />
|
||||
</p:column>
|
||||
<p:column headerText="Can login" >
|
||||
<p:selectBooleanCheckbox id="canLogin" disabled="true" value="#{!empty account.accountLogin}" />
|
||||
</p:column>
|
||||
<p:column headerText="CreatedOn">
|
||||
<h:outputText value="#{account.createdOn}" >
|
||||
<f:convertDateTime type="both" dateStyle="full" timeStyle="short" timeZone="Europe/Berlin"/>
|
||||
</h:outputText>
|
||||
</p:column>
|
||||
<p:column headerText="CreatedBy">
|
||||
<h:outputText value="#{account.createdBy}" />
|
||||
</p:column>
|
||||
<p:column headerText="LastUpdatedOn">
|
||||
<h:outputText value="#{account.lastUpdatedOn}">
|
||||
<f:convertDateTime type="both" dateStyle="full" timeStyle="short" timeZone="Europe/Berlin"/>
|
||||
</h:outputText>
|
||||
</p:column>
|
||||
<p:column headerText="LastUpdatedBy">
|
||||
<h:outputText value="#{account.lastUpdatedBy}" />
|
||||
</p:column>
|
||||
</p:dataTable>
|
||||
|
||||
<p:spacer height="10px" />
|
||||
<p:panel id="buttonPanel" styleClass="box-primary" style="margin-bottom:20px">
|
||||
<div class="ui-g ui-fluid">
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountDelete}">
|
||||
<div class="col-sm-12 col-md-4" style="margin-top:10px">
|
||||
<div class="ui-inputgroup" >
|
||||
<h:outputLabel for="includeDisabledCheckbox" value="Include disabled accounts?" />
|
||||
<p:inputSwitch id="includeDisabledCheckbox" value="#{accountView.showDisabledAccounts}" styleClass="btn-teal btn-block" >
|
||||
<p:ajax listener="#{accountView.showDisabledAccountsChange}" update="accountTable" />
|
||||
</p:inputSwitch>
|
||||
</div>
|
||||
</div>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountAdd}">
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="New" id="newButton" icon="fa fa-plus"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();"
|
||||
actionListener="#{accountView.newAccount}" styleClass="btn-primary btn-block" />
|
||||
</div>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountEdit}">
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="Edit" id="editButton" icon="fa fa-pencil"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();"
|
||||
actionListener="#{accountView.editAccount}" disabled="#{!accountView.accountSelected}" styleClass="btn-teal btn-block" />
|
||||
</div>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountDelete}">
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="Delete" id="deleteButton" icon="fa fa-trash-o"
|
||||
update=":accountForm:accountTable" action="#{accountView.deleteAccount}" disabled="#{accountView.accountSelected eq false or accountView.currentLoggedInUser eq true}" styleClass="btn-danger btn-block">
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<shiro:hasAnyPermission name="#{permissionConstants.accountsCombined}">
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<shiro:hasPermission name="#{permissionConstants.accountLoginAdd}">
|
||||
<c:if test="#{empty accountView.currentAccount.accountLogin}">
|
||||
<p:commandButton value="Add login" id="addLoginButton" icon="fa fa-plus" disabled="#{!accountView.accountSelected}"
|
||||
update="editLoginDialog" oncomplete="PF('editLoginDialogVar').show();"
|
||||
action="#{accountView.addAccountLogin}" styleClass="btn-teal btn-block">
|
||||
</p:commandButton>
|
||||
</c:if>
|
||||
</shiro:hasPermission>
|
||||
|
||||
<c:if test="#{!empty accountView.currentAccount.accountLogin}">
|
||||
<p:splitButton value="Edit login" id="editLoginButton" icon="fa fa-pencil" disabled="#{!accountView.accountSelected}" styleClass="btn-success btn-block">
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountLoginEdit}">
|
||||
<p:menuitem value="Edit login" icon="fa fa-pencil" disabled="#{!accountView.accountSelected}"
|
||||
update="editLoginDialog" oncomplete="PF('editLoginDialogVar').show();"
|
||||
action="#{accountView.editAccountLogin}" >
|
||||
</p:menuitem>
|
||||
</shiro:hasPermission>
|
||||
|
||||
|
||||
<shiro:hasPermission name="#{permissionConstants.accountLoginDelete}">
|
||||
<p:menuitem value="Delete login" icon="fa fa-trash-o" disabled="#{accountView.currentLoggedInUser}"
|
||||
update="accountTable,buttonPanel" styleClass="btn-danger btn-block"
|
||||
action="#{accountView.deleteAccountLogin}" >
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:menuitem>
|
||||
</shiro:hasPermission>
|
||||
|
||||
</p:splitButton>
|
||||
</c:if>
|
||||
</div>
|
||||
</shiro:hasAnyPermission>
|
||||
</div>
|
||||
</p:panel>
|
||||
|
||||
|
||||
|
||||
<composite:confirmationDialog />
|
||||
</h:form>
|
||||
</p:panel>
|
||||
|
||||
|
||||
<p:dialog id="editDialog" widgetVar="editDialogVar" header="Edit account" width="600"
|
||||
modal="true" appendTo="@(body)" showEffect="fade" hideEffect="fade" styleClass="box-solid box-primary" >
|
||||
<h:form id="editDialogForm">
|
||||
<p:messages id="editDialogMessages" showDetail="true" showIcon="true" showSummary="true">
|
||||
<p:autoUpdate />
|
||||
</p:messages>
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="username" value="Username" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<c:if test="#{accountView.currentAccount.createdBy != null}">
|
||||
<h:outputText id="username" value="#{accountView.currentAccount.username}" />
|
||||
</c:if>
|
||||
<c:if test="#{accountView.currentAccount.createdBy == null}">
|
||||
<p:inputText id="username" value="#{accountView.currentAccount.username}" />
|
||||
</c:if>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="username"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="lastname" value="Lastname" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:inputText id="lastname" value="#{accountView.currentAccount.lastname}" size="40" maxlength="100"/>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3 ">
|
||||
<p:message for="lastname"> <p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="firstname" value="Firstname" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:inputText id="firstname" value="#{accountView.currentAccount.firstname}" size="40" maxlength="100" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="firstname"> <p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="emailaddress" value="emailaddress" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:inputText id="emailaddress" value="#{accountView.currentAccount.emailaddress}" size="40" maxlength="200">
|
||||
<f:validator validatorId="de.muehlencord.shared.jeeutil.validator.EmailValidator" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="emailaddress"> <p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<c:if test="#{accountView.currentAccount.username != null}">
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="status" value="Status" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:selectOneMenu id="status" value="#{accountView.currentAccount.status}" >
|
||||
<f:selectItems value="#{accountView.statusList}" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="status" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="createdon" value="Created on" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<h:outputText id="createdon" value="#{accountView.currentAccount.createdOn}" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="createdon" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="createdby" value="Created by" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<h:outputText id="createdby" value="#{accountView.currentAccount.createdBy}" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="createdby" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="lastupdatedon" value="Last updated on" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<h:outputText id="lastupdatedon" value="#{accountView.currentAccount.lastUpdatedOn}" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="lastupdatedon" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="lastupdatedby" value="Last updated by" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<h:outputText id="lastupdatedby" value="#{accountView.currentAccount.lastUpdatedBy}" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="lastupdatedby" />
|
||||
</div>
|
||||
</c:if>
|
||||
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="roles" value="Roles" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:selectManyMenu id="roles" var="role" label="#{role.roleName}" value="#{accountView.currentAccountRoles}" converter="omnifaces.SelectItemsConverter" required="false" >
|
||||
<f:selectItems value="#{accountView.allApplicationRoles}" var="roleItem" itemValue="#{roleItem}" />
|
||||
<p:column>
|
||||
<h:outputText value="#{role.application.applicationName}-#{role.roleName}"/>
|
||||
</p:column>
|
||||
</p:selectManyMenu>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="roles" />
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Save" action="#{accountView.saveEditAccount}" styleClass="btn-primary btn-block"
|
||||
oncomplete="if (args && !args.validationFailed) PF('editDialogVar').hide();" update=":accountForm:accountTable" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Cancel" action="#{accountView.cancelEditAccount}" immediate="true" styleClass="btn-teal btn-block"
|
||||
oncomplete="PF('editDialogVar').hide();" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
<p:dialog id="editLoginDialog" widgetVar="editLoginDialogVar" header="Edit account login" width="600"
|
||||
modal="true" appendTo="@(body)" showEffect="fade" hideEffect="fade" styleClass="box-solid box-primary" >
|
||||
<h:form id="editLoginDialogForm">
|
||||
<p:messages id="editLoginDialogMessages" showDetail="true" showIcon="true" showSummary="true">
|
||||
<p:autoUpdate />
|
||||
</p:messages>
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<o:validateMultiple id="myId" components="password repeatPassword"
|
||||
validator="#{accountView.validatePasswords}" message="#{msgs.passwords_different}" />
|
||||
|
||||
<div class="col-sm-12">
|
||||
<p:outputLabel value="Enter a new password or keep values empty to keep existing / autogenrated value" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="password" value="Password" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:password id="password" value="#{accountView.password}" maxlength="32" size="32" required="false"/>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="password" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="repeatPassword" value="repeat Password" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:password id="repeatPassword" value="#{accountView.repeatPassword}" maxlength="32" size="32" required="false"/>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="repeatPassword" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Save" action="#{accountView.saveEditAccountLogin}" styleClass="btn-primary btn-block"
|
||||
oncomplete="if (args && !args.validationFailed) PF('editLoginDialogVar').hide();" update=":accountForm:accountTable,:accountForm:buttonPanel" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Cancel" action="#{accountView.cancelEditAccountLogin}" immediate="true" styleClass="btn-teal btn-block"
|
||||
oncomplete="PF('editLoginDialogVar').hide();" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@ -1,101 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:co="http://java.sun.com/jsf/composite/composite"
|
||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:composite="http://xmlns.jcp.org/jsf/composite/composite">
|
||||
|
||||
<ui:define name="title">
|
||||
Applications
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body" >
|
||||
|
||||
<p:panel styleClass="box-solid" rendered="#{! empty applicationView.currentApplication}">
|
||||
<h:form id="applicationForm" prependId="false">
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="col-sm-12 col-md-4">
|
||||
<p:selectOneMenu id="applicationSelect" value="#{applicationView.currentApplication}" converter="omnifaces.SelectItemsConverter" required="true">
|
||||
<f:selectItems value="#{applicationView.allApplications}" var="app" itemLabel="#{app.applicationName}" itemValue="#{app}" />
|
||||
</p:selectOneMenu>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="Select" styleClass="btn-primary btn-solid}" icon="fa fa-refresh" actionListener="#{applicationView.selectApplication}" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="Edit" id="editButton" icon="fa fa-edit"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();"
|
||||
actionListener="#{applicationView.startEditApplication}" styleClass="btn-teal btn-block" />
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton value="New" id="newButton" icon="fa fa-plus"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();"
|
||||
actionListener="#{applicationView.newApplication}" styleClass="btn-teal btn-block" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2">
|
||||
<p:commandButton id="deletePermissionButton" icon="fa fa-trash-o" value="#{msgs.button_delete}" actionListener="#{applicationView.deleteApplication}"
|
||||
update="applicationSelect" styleClass="btn-danger btn-block" >
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<composite:confirmationDialog />
|
||||
</h:form>
|
||||
</p:panel>
|
||||
|
||||
<p:dialog id="editDialog" widgetVar="editDialogVar" header="Edit account" width="600"
|
||||
modal="true" appendTo="@(body)" showEffect="fade" hideEffect="fade" styleClass="box-solid box-primary" >
|
||||
<h:form id="editDialogForm">
|
||||
<p:messages id="editDialogMessages" showDetail="true" showIcon="true" showSummary="true">
|
||||
<p:autoUpdate />
|
||||
</p:messages>
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="applicationId" value="ID" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-9">
|
||||
<c:if test="#{empty applicationView.editApplication.id}">
|
||||
<p:inputText id="applicationId" value="#{applicationView.editApplication.id}" required="false"/>
|
||||
</c:if>
|
||||
<c:if test="#{!empty applicationView.editApplication.id}">
|
||||
<p:outputLabel id="applicationId" value="#{applicationView.editApplication.id}" />
|
||||
</c:if>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="applicationName" value="Application name" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-9">
|
||||
<p:inputText id="applicationName" value="#{applicationView.editApplication.applicationName}" required="true">
|
||||
<f:validator validatorId="uniqueApplicationValidator"/>
|
||||
</p:inputText>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="applicationName"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Save" action="#{applicationView.saveEditApplication}" styleClass="btn-primary btn-block"
|
||||
oncomplete="if (args && !args.validationFailed) PF('editDialogVar').hide();" update=":applicationForm" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Cancel" action="#{applicationView.cancelEditApplication}" immediate="true" styleClass="btn-teal btn-block"
|
||||
oncomplete="PF('editDialogVar').hide();" />
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@ -1,13 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
template="/resources/template/template.xhtml">
|
||||
|
||||
<ui:define name="title">
|
||||
Home
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body" >
|
||||
Home
|
||||
</ui:define>
|
||||
</ui:composition>
|
||||
@ -1,108 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:co="http://java.sun.com/jsf/composite/composite"
|
||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||
xmlns:composite="http://xmlns.jcp.org/jsf/composite/composite">
|
||||
|
||||
<ui:define name="title">
|
||||
Permissions
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="description">
|
||||
for #{applicationView.currentApplication.applicationName}
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body">
|
||||
<p:panel styleClass="box-solid" rendered="#{! empty applicationView.currentApplication}">
|
||||
<h:form id="permissionForm">
|
||||
<p:dataTable id="permissionTable" value="#{permissionView.appPermissions}" var="permission" rowKey="#{permission.id}"
|
||||
selectionMode="single" selection="#{permissionView.currentPermission}" styleClass="box-primary">
|
||||
<p:ajax event="rowSelect" update=":permissionForm:permissionTable:editPermissionButton,:permissionForm:permissionTable:deletePermissionButton" />
|
||||
<p:ajax event="rowUnselect" update=":permissionForm:permissionTable:editPermissionButton,:permissionForm:permissionTable:deletePermissionButton" />
|
||||
|
||||
<p:column headerText="Permission name">
|
||||
<h:outputText value="#{permission.permissionName}" />
|
||||
</p:column>
|
||||
<p:column headerText="Permission description">
|
||||
<h:outputText value="#{permission.permissionDescription}" />
|
||||
</p:column>
|
||||
|
||||
<f:facet name="footer">
|
||||
<div class="ui-g-12 ui-md-2">
|
||||
<p:commandButton id="newPermissionButton" icon="fa fa-plus" value="#{msgs.button_new}" action="#{permissionView.newPermission}"
|
||||
oncomplete="PF('editDialogVar').show();" update="editDialog" styleClass="btn-primary btn-block" />
|
||||
</div>
|
||||
<div class="ui-g-12 ui-md-2">
|
||||
<p:commandButton id="editPermissionButton" icon="fa fa-pencil" value="#{msgs.button_edit}" action="#{permissionView.editPermission}"
|
||||
oncomplete="PF('editDialogVar').show();" update="editDialog" styleClass="btn-teal btn-block" disabled="#{!permissionView.canEdit}" />
|
||||
</div>
|
||||
<div class="ui-g-12 ui-md-2">
|
||||
<p:commandButton id="deletePermissionButton" icon="fa fa-trash-o" value="#{msgs.button_delete}" actionListener="#{permissionView.deletePermission}"
|
||||
update="permissionForm" styleClass="btn-danger btn-block" disabled="#{!permissionView.canDelete}">
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</f:facet>
|
||||
</p:dataTable>
|
||||
|
||||
<composite:confirmationDialog />
|
||||
</h:form>
|
||||
</p:panel>
|
||||
|
||||
|
||||
<p:dialog id="editDialog" widgetVar="editDialogVar" header="Edit permission" width="600"
|
||||
modal="true" appendTo="@(body)" showEffect="fade" hideEffect="fade" styleClass="box-solid box-primary" >
|
||||
<h:form id="editDialogForm">
|
||||
<p:messages id="editDialogMessages" showDetail="true" showIcon="true" showSummary="true">
|
||||
<p:autoUpdate />
|
||||
</p:messages>
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="ui-g-12 ui-md-3">
|
||||
<div class="ui-inputgroup">
|
||||
<span class="ui-inputgroup-addon"><i style="font-size: 20px" class="fa fa-edit"></i></span>
|
||||
<p:inputText id="newName" value="#{permissionView.currentPermission.permissionName}" maxlength="80" size="30" placeholder="#{msgs.label_name}" >
|
||||
<f:validator validatorId="uniquePermissionNameValidator"/>
|
||||
<f:attribute name="application" value="#{permissionView.currentApplication}" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-9">
|
||||
<p:message for="newName"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="ui-g-12 ui-md-3">
|
||||
<div class="ui-inputgroup">
|
||||
<span class="ui-inputgroup-addon"><i style="font-size: 20px" class="fa fa-edit"></i></span>
|
||||
<p:inputText id="newDescription" value="#{permissionView.currentPermission.permissionDescription}" maxlength="200" size="30" placeholder="#{msgs.label_description}" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-9">
|
||||
<p:message for="newDescription"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Save" action="#{permissionView.saveEditPermission}" styleClass="btn-primary btn-block"
|
||||
oncomplete="if (args && !args.validationFailed) PF('editDialogVar').hide();" update=":permissionForm:permissionTable" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Cancel" action="#{permissionView.cancelEditPermission}" immediate="true" styleClass="btn-teal btn-block"
|
||||
oncomplete="PF('editDialogVar').hide();" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
|
||||
|
||||
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
@ -1,135 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui:composition xmlns="http://www.w3.org/1999/xhtml"
|
||||
xmlns:ui="http://java.sun.com/jsf/facelets"
|
||||
xmlns:p="http://primefaces.org/ui"
|
||||
template="/resources/template/template.xhtml"
|
||||
xmlns:h="http://xmlns.jcp.org/jsf/html"
|
||||
xmlns:co="http://java.sun.com/jsf/composite/composite"
|
||||
xmlns:f="http://xmlns.jcp.org/jsf/core"
|
||||
xmlns:composite="http://xmlns.jcp.org/jsf/composite/composite">
|
||||
|
||||
<ui:define name="title">
|
||||
Roles Overview
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="description">
|
||||
for #{applicationView.currentApplication.applicationName}
|
||||
</ui:define>
|
||||
|
||||
<ui:define name="body">
|
||||
<p:panel styleClass="box-solid" rendered="#{! empty applicationView.currentApplication}">
|
||||
<h:form id="roleForm">
|
||||
<p:dataTable id="roleTable" value="#{roleView.allRoles}" var="role" rowKey="#{role.id}" styleClass="box-primary"
|
||||
selectionMode="single" selection="#{roleView.currentRole}">
|
||||
<p:ajax event="rowSelect" update=":roleForm:permissionTable, editRoleButton, deleteRoleButton" listener="#{roleView.onRoleSelect}"/>
|
||||
<p:ajax event="rowUnselect" update=":roleForm:permissionTable, editRoleButton, deleteRoleButton" />
|
||||
|
||||
<p:column headerText="Role name">
|
||||
<h:outputText value="#{role.roleName}" />
|
||||
</p:column>
|
||||
<p:column headerText="Role description">
|
||||
<h:outputText value="#{role.roleDescription}" />
|
||||
</p:column>
|
||||
|
||||
|
||||
<f:facet name="footer">
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="col-sm-12 col-md-2" style="margin-top:10px">
|
||||
<p:commandButton id="newRoleButton" icon="fa fa-plus" value="#{msgs.button_new}" actionListener="#{roleView.startNewRole}"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();" styleClass="btn-primary btn-block"/>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2" style="margin-top:10px">
|
||||
<p:commandButton id="editRoleButton" icon="fa fa-pencil" value="#{msgs.button_edit}" disabled="#{!roleView.roleSelected}"
|
||||
update="editDialog" oncomplete="PF('editDialogVar').show();" styleClass="btn-teal btn-block"/>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-2" style="margin-top:10px">
|
||||
<p:commandButton id="deleteRoleButton" icon="fa fa-trash-o" value="#{msgs.button_delete}" disabled="#{!roleView.roleSelected}"
|
||||
action="#{roleView.deleteRole}" update=":roleForm:roleTable" styleClass="btn-danger btn-block">
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</div>
|
||||
</f:facet>
|
||||
</p:dataTable>
|
||||
|
||||
<p:spacer height="15px;" />
|
||||
|
||||
<p:dataTable id="permissionTable" value="#{roleView.rolePermissions}" var="permission" rowKey="#{permission.id}" styleClass="box-teal"
|
||||
selectionMode="single" selection="#{roleView.currentPermission}">
|
||||
<p:ajax event="rowSelect" update="addPermissionButton, deletePermissionButton" />
|
||||
<p:ajax event="rowUnselect" update="addPermissionButton, deletePermissionButton" />
|
||||
|
||||
<p:column headerText="Permission name">
|
||||
<h:outputText value="#{permission.permissionName}" />
|
||||
</p:column>
|
||||
<p:column headerText="Permission description">
|
||||
<h:outputText value="#{permission.permissionDescription}" />
|
||||
</p:column>
|
||||
<f:facet name="footer" >
|
||||
<p:selectOneMenu value="#{roleView.newPermission}" converter="omnifaces.SelectItemsConverter" >
|
||||
<f:selectItems id="permissionListItems" value="#{roleView.missingPermissions}" var="missingPermission" itemLabel="#{missingPermission.permissionName}" itemValue="#{missingPermission}" />
|
||||
</p:selectOneMenu>
|
||||
<div class="ui-g-12 ui-md-2">
|
||||
<p:commandButton id="addPermissionButton" icon="fa fa-plus" value="#{msgs.button_add}" action="#{roleView.addRolePermission}"
|
||||
update="permissionTable" styleClass="btn-primary btn-block" disabled="#{!roleView.missingPermissionAvailable}" />
|
||||
</div>
|
||||
<div class="ui-g-12 ui-md-2">
|
||||
<p:commandButton id="deletePermissionButton" icon="fa fa-trash-o" value="#{msgs.button_delete}" update=":roleForm:permissionTable"
|
||||
action="#{roleView.removeRolePermission}" styleClass="btn-danger btn-block"
|
||||
disabled="#{!roleView.permissionSelected}" >
|
||||
<p:confirm header="Confirmation" message="Are you sure?" icon="fa fa-exclamation-triangle" />
|
||||
</p:commandButton>
|
||||
</div>
|
||||
</f:facet>
|
||||
</p:dataTable>
|
||||
|
||||
<composite:confirmationDialog />
|
||||
</h:form>
|
||||
</p:panel>
|
||||
|
||||
<p:dialog id="editDialog" widgetVar="editDialogVar" header="Edit account" width="600"
|
||||
modal="true" appendTo="@(body)" showEffect="fade" hideEffect="fade" styleClass="box-solid box-primary" >
|
||||
<h:form id="editDialogForm">
|
||||
<p:messages id="editDialogMessages" showDetail="true" showIcon="true" showSummary="true">
|
||||
<p:autoUpdate />
|
||||
</p:messages>
|
||||
|
||||
<div class="ui-g ui-fluid">
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="newName" value="Role name" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:inputText id="newName" value="#{roleView.currentRole.roleName}" placeholder="#{msgs.label_name}" maxlength="80" size="40">
|
||||
<f:validator validatorId="uniqueApplicationRoleNameValidator"/>
|
||||
<f:attribute name="application" value="#{roleView.currentApplication}" />
|
||||
</p:inputText>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="newName"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:outputLabel for="newDescription" value="Description" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:inputText id="newDescription" value="#{roleView.currentRole.roleDescription}" placeholder="#{msgs.label_description}" maxlength="200" size="40" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-3">
|
||||
<p:message for="newDescription"><p:autoUpdate /></p:message>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Save" action="#{roleView.saveEditRole}" styleClass="btn-primary btn-block"
|
||||
oncomplete="if (args && !args.validationFailed) PF('editDialogVar').hide();" update=":roleForm:roleTable" />
|
||||
</div>
|
||||
<div class="col-sm-12 col-md-6">
|
||||
<p:spacer height="10px" />
|
||||
<p:commandButton value="Cancel" action="#{roleView.cancelEditRole}" immediate="true" styleClass="btn-teal btn-block"
|
||||
oncomplete="PF('editDialogVar').hide();" />
|
||||
</div>
|
||||
</div>
|
||||
</h:form>
|
||||
</p:dialog>
|
||||
</ui:define>
|
||||
|
||||
</ui:composition>
|
||||
117
account/pom.xml
117
account/pom.xml
@ -1,117 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>de.muehlencord.shared</groupId>
|
||||
<artifactId>shared-account</artifactId>
|
||||
<packaging>ejb</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>shared</artifactId>
|
||||
<groupId>de.muehlencord</groupId>
|
||||
<version>1.2-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>shared-account</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-db</artifactId>
|
||||
<type>ejb</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-account-dao</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-util</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.shiro</groupId>
|
||||
<artifactId>shiro-web</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>shared-jeeutil</artifactId>
|
||||
<type>jar</type>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-junit-jupiter</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-log4j12</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-api</artifactId>
|
||||
<type>jar</type>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<artifactId>hibernate-core</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<!-- create EJB version 3.1 -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-ejb-plugin</artifactId>
|
||||
<configuration>
|
||||
<ejbVersion>3.1</ejbVersion>
|
||||
<excludes>
|
||||
<exclude>**/persistence.xml</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@ -1,410 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
CAUTION: Do not modify this file unless you know what you are doing.
|
||||
Unexpected results may occur if the code is changed deliberately.
|
||||
-->
|
||||
<dbmodel pgmodeler-ver="0.9.2-beta" last-position="0,0" last-zoom="0.9" max-obj-count="13"
|
||||
default-owner="postgres">
|
||||
<database name="account_test" encoding="UTF8" lc-collate="C" lc-ctype="C" is-template="false" allow-conns="true" sql-disabled="true">
|
||||
</database>
|
||||
|
||||
<schema name="public" layer="0" fill-color="#e1e1e1" sql-disabled="true">
|
||||
</schema>
|
||||
|
||||
<table name="config" layer="0" collapse-mode="1" max-obj-count="6">
|
||||
<schema name="public"/>
|
||||
<position x="1480" y="220"/>
|
||||
<column name="application" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="config_key" not-null="true">
|
||||
<type name="varchar" length="100"/>
|
||||
</column>
|
||||
<column name="config_key_account" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="config_key_group">
|
||||
<type name="varchar" length="200"/>
|
||||
</column>
|
||||
<column name="config_value">
|
||||
<type name="varchar" length="2000"/>
|
||||
</column>
|
||||
<constraint name="config_pk" type="pk-constr" table="public.config">
|
||||
<columns names="application,config_key,config_key_account" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="application_role" layer="0" collapse-mode="1" max-obj-count="4">
|
||||
<schema name="public"/>
|
||||
<position x="100" y="260"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="application" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="role_name" not-null="true">
|
||||
<type name="character varying" length="80"/>
|
||||
</column>
|
||||
<column name="role_description" not-null="true">
|
||||
<type name="character varying" length="200"/>
|
||||
</column>
|
||||
<constraint name="application_role_pk" type="pk-constr" table="public.application_role">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
<constraint name="application_role_name_uidx" type="uq-constr" table="public.application_role">
|
||||
<columns names="application,role_name" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="account" layer="0" collapse-mode="1" max-obj-count="12">
|
||||
<schema name="public"/>
|
||||
<position x="1080" y="460"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="username" not-null="true">
|
||||
<type name="character varying" length="32"/>
|
||||
</column>
|
||||
<column name="emailaddress" not-null="true">
|
||||
<type name="character varying" length="200"/>
|
||||
</column>
|
||||
<column name="firstname" not-null="true">
|
||||
<type name="character varying" length="100"/>
|
||||
</column>
|
||||
<column name="lastname" not-null="true">
|
||||
<type name="character varying" length="100"/>
|
||||
</column>
|
||||
<column name="status" not-null="true" default-value="'NEW'">
|
||||
<type name="character varying" length="10"/>
|
||||
</column>
|
||||
<column name="created_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamp with time zone" length="0" with-timezone="true"/>
|
||||
</column>
|
||||
<column name="created_by" not-null="true">
|
||||
<type name="character varying" length="32"/>
|
||||
</column>
|
||||
<column name="last_updated_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamp with time zone" length="0" with-timezone="true"/>
|
||||
</column>
|
||||
<column name="last_updated_by" not-null="true">
|
||||
<type name="character varying" length="32"/>
|
||||
</column>
|
||||
<constraint name="pk_account" type="pk-constr" table="public.account">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
<constraint name="uidx_username" type="uq-constr" table="public.account">
|
||||
<columns names="username" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="account_history" layer="0" collapse-mode="1" max-obj-count="8">
|
||||
<schema name="public"/>
|
||||
<position x="180" y="640"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="account_id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="message">
|
||||
<type name="character varying" length="200"/>
|
||||
</column>
|
||||
<column name="failure_count" not-null="true" default-value="0">
|
||||
<type name="integer" length="0"/>
|
||||
</column>
|
||||
<column name="status" not-null="true">
|
||||
<type name="character varying" length="20"/>
|
||||
</column>
|
||||
<column name="last_updated_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamp with time zone" length="0" with-timezone="true"/>
|
||||
</column>
|
||||
<column name="last_updated_by" not-null="true">
|
||||
<type name="character varying" length="32"/>
|
||||
</column>
|
||||
<constraint name="pk_account_history" type="pk-constr" table="public.account_history">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="account_role" layer="0" collapse-mode="1" max-obj-count="3">
|
||||
<schema name="public"/>
|
||||
<position x="480" y="440"/>
|
||||
<column name="account" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="account_role" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<constraint name="pk_account_role" type="pk-constr" table="public.account_role">
|
||||
<columns names="account,account_role" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="application_permission" layer="0" collapse-mode="1" max-obj-count="4">
|
||||
<schema name="public"/>
|
||||
<position x="1080" y="100"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="application" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="permission_name" not-null="true">
|
||||
<type name="character varying" length="80"/>
|
||||
</column>
|
||||
<column name="permission_description" not-null="true">
|
||||
<type name="character varying" length="200"/>
|
||||
</column>
|
||||
<constraint name="pk_application_permission" type="pk-constr" table="public.application_permission">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
<constraint name="application_permission_name_uidx" type="uq-constr" table="public.application_permission">
|
||||
<columns names="application,permission_name" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="role_permission" layer="0" collapse-mode="1" max-obj-count="3">
|
||||
<schema name="public"/>
|
||||
<position x="560" y="80"/>
|
||||
<column name="application_role" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="role_permission" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<constraint name="pk_role_permission_role_permission_name" type="pk-constr" table="public.role_permission">
|
||||
<columns names="application_role,role_permission" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="mail_template" layer="0" collapse-mode="1" max-obj-count="2">
|
||||
<schema name="public"/>
|
||||
<position x="120" y="940"/>
|
||||
<column name="template_name" not-null="true">
|
||||
<type name="character varying" length="40"/>
|
||||
</column>
|
||||
<column name="template_value" not-null="true">
|
||||
<type name="text" length="0"/>
|
||||
</column>
|
||||
<constraint name="mail_template_pk" type="pk-constr" table="public.mail_template">
|
||||
<columns names="template_name" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="application" layer="0" collapse-mode="1" max-obj-count="2">
|
||||
<schema name="public"/>
|
||||
<position x="720" y="320"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="application_name" not-null="true">
|
||||
<type name="varchar" length="200"/>
|
||||
</column>
|
||||
<constraint name="application_pk" type="pk-constr" table="public.application">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<extension name="uuid-ossp" sql-disabled="true">
|
||||
<schema name="public"/>
|
||||
</extension>
|
||||
|
||||
<table name="account_login" layer="0" collapse-mode="1" max-obj-count="15">
|
||||
<schema name="public"/>
|
||||
<position x="1520" y="680"/>
|
||||
<column name="id" not-null="true" default-value="uuid_generate_v4()">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="account" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="account_password" not-null="true">
|
||||
<type name="varchar" length="200"/>
|
||||
</column>
|
||||
<column name="last_login">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="last_failed_login">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="failure_count" not-null="true" default-value="0">
|
||||
<type name="integer" length="0"/>
|
||||
</column>
|
||||
<column name="password_reset_ongoing" not-null="true" default-value="false">
|
||||
<type name="boolean" length="0"/>
|
||||
</column>
|
||||
<column name="password_reset_valid_to">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="password_reset_hash">
|
||||
<type name="varchar" length="200"/>
|
||||
</column>
|
||||
<column name="created_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="created_by" not-null="true">
|
||||
<type name="varchar" length="32"/>
|
||||
</column>
|
||||
<column name="last_updated_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="last_updated_by" not-null="true">
|
||||
<type name="varchar" length="32"/>
|
||||
</column>
|
||||
<constraint name="account_login_pk" type="pk-constr" table="public.account_login">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
<constraint name="account_login_uidx" type="uq-constr" table="public.account_login">
|
||||
<columns names="account" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<table name="api_key" layer="0" collapse-mode="1" max-obj-count="7">
|
||||
<schema name="public"/>
|
||||
<position x="680" y="760"/>
|
||||
<column name="id" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="account" not-null="true">
|
||||
<type name="uuid" length="0"/>
|
||||
</column>
|
||||
<column name="api_key" not-null="true">
|
||||
<type name="varchar" length="200"/>
|
||||
</column>
|
||||
<column name="issued_on" not-null="true" default-value="timezone('utc'::text, now())">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<column name="expiration">
|
||||
<type name="smallint" length="0"/>
|
||||
</column>
|
||||
<column name="expires_on" not-null="true">
|
||||
<type name="timestamptz" length="0"/>
|
||||
</column>
|
||||
<constraint name="api_key_pk" type="pk-constr" table="public.api_key">
|
||||
<columns names="id" ref-type="src-columns"/>
|
||||
</constraint>
|
||||
</table>
|
||||
|
||||
<constraint name="config_key_account_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.account" table="public.config">
|
||||
<columns names="config_key_account" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="config_application_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application" table="public.config">
|
||||
<columns names="application" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="application_role_app_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application" table="public.application_role">
|
||||
<columns names="application" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="fk_account_history_username_fk" type="fk-constr" comparison-type="MATCH SIMPLE"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.account" table="public.account_history">
|
||||
<columns names="account_id" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="fk_account_role_account" type="fk-constr" comparison-type="MATCH SIMPLE"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.account" table="public.account_role">
|
||||
<columns names="account" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="fk_account_role_role_name" type="fk-constr" comparison-type="MATCH SIMPLE"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application_role" table="public.account_role">
|
||||
<columns names="account_role" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="application_permission_app_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application" table="public.application_permission">
|
||||
<columns names="application" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="fk_role_permission_application_role" type="fk-constr" comparison-type="MATCH SIMPLE"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application_role" table="public.role_permission">
|
||||
<columns names="application_role" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="fk_role_permission_role_permission" type="fk-constr" comparison-type="MATCH SIMPLE"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.application_permission" table="public.role_permission">
|
||||
<columns names="role_permission" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="account_login_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.account" table="public.account_login">
|
||||
<columns names="account" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<constraint name="api_key_account_fk" type="fk-constr" comparison-type="MATCH FULL"
|
||||
upd-action="NO ACTION" del-action="NO ACTION" ref-table="public.account" table="public.api_key">
|
||||
<columns names="account" ref-type="src-columns"/>
|
||||
<columns names="id" ref-type="dst-columns"/>
|
||||
</constraint>
|
||||
|
||||
<relationship name="rel_config_account" type="relfk" layer="0"
|
||||
src-table="public.config"
|
||||
dst-table="public.account" reference-fk="config_key_account_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_config_application" type="relfk" layer="0"
|
||||
src-table="public.config"
|
||||
dst-table="public.application" reference-fk="config_application_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_application_role_application" type="relfk" layer="0"
|
||||
src-table="public.application_role"
|
||||
dst-table="public.application" reference-fk="application_role_app_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_account_history_account" type="relfk" layer="0"
|
||||
src-table="public.account_history"
|
||||
dst-table="public.account" reference-fk="fk_account_history_username_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_account_role_account" type="relfk" layer="0"
|
||||
src-table="public.account_role"
|
||||
dst-table="public.account" reference-fk="fk_account_role_account"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_account_role_application_role" type="relfk" layer="0"
|
||||
src-table="public.account_role"
|
||||
dst-table="public.application_role" reference-fk="fk_account_role_role_name"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_application_permission_application" type="relfk" layer="0"
|
||||
src-table="public.application_permission"
|
||||
dst-table="public.application" reference-fk="application_permission_app_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_role_permission_application_role" type="relfk" layer="0"
|
||||
src-table="public.role_permission"
|
||||
dst-table="public.application_role" reference-fk="fk_role_permission_application_role"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_role_permission_application_permission" type="relfk" layer="0"
|
||||
src-table="public.role_permission"
|
||||
dst-table="public.application_permission" reference-fk="fk_role_permission_role_permission"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_account_login_account" type="relfk" layer="0"
|
||||
src-table="public.account_login"
|
||||
dst-table="public.account" reference-fk="account_login_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
<relationship name="rel_api_key_account" type="relfk" layer="0"
|
||||
src-table="public.api_key"
|
||||
dst-table="public.account" reference-fk="api_key_account_fk"
|
||||
src-required="false" dst-required="false"/>
|
||||
|
||||
</dbmodel>
|
||||
@ -1,251 +0,0 @@
|
||||
-- Database generated with pgModeler (PostgreSQL Database Modeler).
|
||||
-- pgModeler version: 0.9.2-beta
|
||||
-- PostgreSQL version: 9.6
|
||||
-- Project Site: pgmodeler.io
|
||||
-- Model Author: ---
|
||||
|
||||
|
||||
-- Database creation must be done outside a multicommand file.
|
||||
-- These commands were put in this file only as a convenience.
|
||||
-- -- object: account_test | type: DATABASE --
|
||||
-- -- DROP DATABASE IF EXISTS account_test;
|
||||
-- CREATE DATABASE account_test
|
||||
-- ENCODING = 'UTF8'
|
||||
-- LC_COLLATE = 'C'
|
||||
-- LC_CTYPE = 'C';
|
||||
-- -- ddl-end --
|
||||
--
|
||||
|
||||
-- object: public.config | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.config CASCADE;
|
||||
CREATE TABLE public.config (
|
||||
application uuid NOT NULL,
|
||||
config_key varchar(100) NOT NULL,
|
||||
config_key_account uuid NOT NULL,
|
||||
config_key_group varchar(200),
|
||||
config_value varchar(200),
|
||||
CONSTRAINT config_pk PRIMARY KEY (application,config_key,config_key_account)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.application_role | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.application_role CASCADE;
|
||||
CREATE TABLE public.application_role (
|
||||
id uuid NOT NULL,
|
||||
application uuid NOT NULL,
|
||||
role_name character varying(80) NOT NULL,
|
||||
role_description character varying(200) NOT NULL,
|
||||
CONSTRAINT application_role_pk PRIMARY KEY (id),
|
||||
CONSTRAINT application_role_name_uidx UNIQUE (application,role_name)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.account | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.account CASCADE;
|
||||
CREATE TABLE public.account (
|
||||
id uuid NOT NULL,
|
||||
username character varying(32) NOT NULL,
|
||||
emailaddress character varying(200) NOT NULL,
|
||||
firstname character varying(100) NOT NULL,
|
||||
lastname character varying(100) NOT NULL,
|
||||
status character varying(10) NOT NULL DEFAULT 'NEW',
|
||||
created_on timestamp with time zone NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
created_by character varying(32) NOT NULL,
|
||||
last_updated_on timestamp with time zone NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
last_updated_by character varying(32) NOT NULL,
|
||||
CONSTRAINT pk_account PRIMARY KEY (id),
|
||||
CONSTRAINT uidx_username UNIQUE (username)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.account_history | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.account_history CASCADE;
|
||||
CREATE TABLE public.account_history (
|
||||
id uuid NOT NULL,
|
||||
account_id uuid NOT NULL,
|
||||
message character varying(200),
|
||||
failure_count integer NOT NULL DEFAULT 0,
|
||||
status character varying(20) NOT NULL,
|
||||
last_updated_on timestamp with time zone NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
last_updated_by character varying(32) NOT NULL,
|
||||
CONSTRAINT pk_account_history PRIMARY KEY (id)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.account_role | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.account_role CASCADE;
|
||||
CREATE TABLE public.account_role (
|
||||
account uuid NOT NULL,
|
||||
account_role uuid NOT NULL,
|
||||
CONSTRAINT pk_account_role PRIMARY KEY (account,account_role)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.application_permission | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.application_permission CASCADE;
|
||||
CREATE TABLE public.application_permission (
|
||||
id uuid NOT NULL,
|
||||
application uuid NOT NULL,
|
||||
permission_name character varying(80) NOT NULL,
|
||||
permission_description character varying(200) NOT NULL,
|
||||
CONSTRAINT pk_application_permission PRIMARY KEY (id),
|
||||
CONSTRAINT application_permission_name_uidx UNIQUE (application,permission_name)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.role_permission | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.role_permission CASCADE;
|
||||
CREATE TABLE public.role_permission (
|
||||
application_role uuid NOT NULL,
|
||||
role_permission uuid NOT NULL,
|
||||
CONSTRAINT pk_role_permission_role_permission_name PRIMARY KEY (application_role,role_permission)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.mail_template | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.mail_template CASCADE;
|
||||
CREATE TABLE public.mail_template (
|
||||
template_name character varying(40) NOT NULL,
|
||||
template_value text NOT NULL,
|
||||
CONSTRAINT mail_template_pk PRIMARY KEY (template_name)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.application | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.application CASCADE;
|
||||
CREATE TABLE public.application (
|
||||
id uuid NOT NULL,
|
||||
application_name varchar(200) NOT NULL,
|
||||
CONSTRAINT application_pk PRIMARY KEY (id)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- -- object: "uuid-ossp" | type: EXTENSION --
|
||||
-- -- DROP EXTENSION IF EXISTS "uuid-ossp" CASCADE;
|
||||
-- CREATE EXTENSION "uuid-ossp"
|
||||
-- WITH SCHEMA public;
|
||||
-- -- ddl-end --
|
||||
--
|
||||
-- object: public.account_login | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.account_login CASCADE;
|
||||
CREATE TABLE public.account_login (
|
||||
id uuid NOT NULL DEFAULT uuid_generate_v4(),
|
||||
account uuid NOT NULL,
|
||||
account_password varchar(200) NOT NULL,
|
||||
last_login timestamptz,
|
||||
last_failed_login timestamptz,
|
||||
failure_count integer NOT NULL DEFAULT 0,
|
||||
password_reset_ongoing boolean NOT NULL DEFAULT false,
|
||||
password_reset_valid_to timestamptz,
|
||||
password_reset_hash varchar(200),
|
||||
created_on timestamptz NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
created_by varchar(32) NOT NULL,
|
||||
last_updated_on timestamptz NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
last_updated_by varchar(32) NOT NULL,
|
||||
CONSTRAINT account_login_pk PRIMARY KEY (id),
|
||||
CONSTRAINT account_login_uidx UNIQUE (account)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: public.api_key | type: TABLE --
|
||||
DROP TABLE IF EXISTS public.api_key CASCADE;
|
||||
CREATE TABLE public.api_key (
|
||||
id uuid NOT NULL,
|
||||
account uuid NOT NULL,
|
||||
api_key varchar(200) NOT NULL,
|
||||
issued_on timestamptz NOT NULL DEFAULT timezone('utc'::text, now()),
|
||||
expiration smallint,
|
||||
expires_on timestamptz NOT NULL,
|
||||
CONSTRAINT api_key_pk PRIMARY KEY (id)
|
||||
|
||||
);
|
||||
-- ddl-end --
|
||||
|
||||
-- object: config_key_account_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.config DROP CONSTRAINT IF EXISTS config_key_account_fk CASCADE;
|
||||
ALTER TABLE public.config ADD CONSTRAINT config_key_account_fk FOREIGN KEY (config_key_account)
|
||||
REFERENCES public.account (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: config_application_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.config DROP CONSTRAINT IF EXISTS config_application_fk CASCADE;
|
||||
ALTER TABLE public.config ADD CONSTRAINT config_application_fk FOREIGN KEY (application)
|
||||
REFERENCES public.application (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: application_role_app_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.application_role DROP CONSTRAINT IF EXISTS application_role_app_fk CASCADE;
|
||||
ALTER TABLE public.application_role ADD CONSTRAINT application_role_app_fk FOREIGN KEY (application)
|
||||
REFERENCES public.application (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: fk_account_history_username_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.account_history DROP CONSTRAINT IF EXISTS fk_account_history_username_fk CASCADE;
|
||||
ALTER TABLE public.account_history ADD CONSTRAINT fk_account_history_username_fk FOREIGN KEY (account_id)
|
||||
REFERENCES public.account (id) MATCH SIMPLE
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: fk_account_role_account | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.account_role DROP CONSTRAINT IF EXISTS fk_account_role_account CASCADE;
|
||||
ALTER TABLE public.account_role ADD CONSTRAINT fk_account_role_account FOREIGN KEY (account)
|
||||
REFERENCES public.account (id) MATCH SIMPLE
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: fk_account_role_role_name | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.account_role DROP CONSTRAINT IF EXISTS fk_account_role_role_name CASCADE;
|
||||
ALTER TABLE public.account_role ADD CONSTRAINT fk_account_role_role_name FOREIGN KEY (account_role)
|
||||
REFERENCES public.application_role (id) MATCH SIMPLE
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: application_permission_app_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.application_permission DROP CONSTRAINT IF EXISTS application_permission_app_fk CASCADE;
|
||||
ALTER TABLE public.application_permission ADD CONSTRAINT application_permission_app_fk FOREIGN KEY (application)
|
||||
REFERENCES public.application (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: fk_role_permission_application_role | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.role_permission DROP CONSTRAINT IF EXISTS fk_role_permission_application_role CASCADE;
|
||||
ALTER TABLE public.role_permission ADD CONSTRAINT fk_role_permission_application_role FOREIGN KEY (application_role)
|
||||
REFERENCES public.application_role (id) MATCH SIMPLE
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: fk_role_permission_role_permission | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.role_permission DROP CONSTRAINT IF EXISTS fk_role_permission_role_permission CASCADE;
|
||||
ALTER TABLE public.role_permission ADD CONSTRAINT fk_role_permission_role_permission FOREIGN KEY (role_permission)
|
||||
REFERENCES public.application_permission (id) MATCH SIMPLE
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: account_login_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.account_login DROP CONSTRAINT IF EXISTS account_login_fk CASCADE;
|
||||
ALTER TABLE public.account_login ADD CONSTRAINT account_login_fk FOREIGN KEY (account)
|
||||
REFERENCES public.account (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
-- object: api_key_account_fk | type: CONSTRAINT --
|
||||
-- ALTER TABLE public.api_key DROP CONSTRAINT IF EXISTS api_key_account_fk CASCADE;
|
||||
ALTER TABLE public.api_key ADD CONSTRAINT api_key_account_fk FOREIGN KEY (account)
|
||||
REFERENCES public.account (id) MATCH FULL
|
||||
ON DELETE NO ACTION ON UPDATE NO ACTION;
|
||||
-- ddl-end --
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
DELETE FROM config;
|
||||
DELETE FROM account_role;
|
||||
DELETE FROM account_login;
|
||||
DELETE FROM account;
|
||||
DELETE FROM role_permission;
|
||||
DELETE FROM application_role;
|
||||
DELETE FROM application_permission;
|
||||
DELETE FROM application;
|
||||
|
||||
INSERT INTO application (id, application_name) values ('143a2bd3-7e0b-4162-a76e-3031331c7dfe', 'Account UI');
|
||||
|
||||
-- add roles to Account UI application
|
||||
INSERT INTO application_role (id, application, role_name, role_description) values ('5cd0aca0-5466-483d-8f3e-c369f8061131','143a2bd3-7e0b-4162-a76e-3031331c7dfe', 'Admin', 'Admin role');
|
||||
INSERT INTO application_role (id, application, role_name, role_description) values ('da30060e-fd23-4016-a506-4e12e9322148','143a2bd3-7e0b-4162-a76e-3031331c7dfe', 'User', 'Standard user role');
|
||||
|
||||
-- create accounts
|
||||
INSERT INTO account (id, username, firstname, lastname, emailaddress, created_by, last_updated_by) values ('2a712ed4-30f8-47b4-a002-7d87441b7013', 'system', 'system', 'system', 'n/a', 'system', 'system');
|
||||
INSERT INTO account (id, username, emailaddress, firstname, lastname, created_by, last_updated_by) values('ab5c8337-6872-4aea-a9b9-78ea63706b8f','admin', 'joern@muehlencord.de', 'Joern', 'Muehlencord','system','system');
|
||||
-- assign AccountUI.Admin role to admin user
|
||||
INSERT INTO account_role (account, account_role) values ('ab5c8337-6872-4aea-a9b9-78ea63706b8f', '5cd0aca0-5466-483d-8f3e-c369f8061131');
|
||||
|
||||
-- create login for user admin (login admin, password secret)
|
||||
INSERT INTO account_login (account, account_password, created_by, last_updated_by) VALUES ('ab5c8337-6872-4aea-a9b9-78ea63706b8f', '$shiro1$SHA-256$500000$4bHPNH9k539UjdFLgm/HOA==$T/n8skgoGSOtNw/c9ScDlXCiGrx2cZF0Esrvf6WPq6g=', 'system', 'system'); --admin/secret
|
||||
|
||||
-- config
|
||||
INSERT INTO config (application, config_key, config_key_account, config_value) VALUES ('143a2bd3-7e0b-4162-a76e-3031331c7dfe', 'account.maxFailedLogins', '2a712ed4-30f8-47b4-a002-7d87441b7013', '5');
|
||||
|
||||
|
||||
|
||||
@ -1,4 +0,0 @@
|
||||
echo off
|
||||
SET BACKUPFOLDER=%~dp0
|
||||
"C:\Program Files\PostgreSQL\10\bin\pg_dump.exe" -U jomu -n public --column-inserts --attribute-inserts --no-owner --no-privileges --no-acl --clean account > %BACKUPFOLDER%\account.dump
|
||||
pause;
|
||||
@ -1,4 +0,0 @@
|
||||
echo off
|
||||
SET BACKUPFOLDER=%~dp0
|
||||
"C:\Program Files\PostgreSQL\10\bin\pg_dump.exe" -U jomu -n public --column-inserts --attribute-inserts --no-owner --no-privileges --no-acl --clean account_test > %BACKUPFOLDER%\account_test.dump
|
||||
pause;
|
||||
@ -1,9 +0,0 @@
|
||||
@ECHO OFF
|
||||
set BASEDIR=%~dp0%
|
||||
set PGMODELER_DIR=c:\app\pgmodeler
|
||||
|
||||
setlocal
|
||||
cd %PGMODELER_DIR%
|
||||
pgmodeler-cli -if %BASEDIR%/account.dbm -ef -do -of %BASEDIR%/account.sql
|
||||
|
||||
pause
|
||||
@ -1,11 +0,0 @@
|
||||
DROP TABLE IF EXISTS config CASCADE;
|
||||
DROP TABLE IF EXISTS account_role CASCADE;
|
||||
DROP TABLE IF EXISTS account_login CASCADE;
|
||||
DROP TABLE IF EXISTS account CASCADE;
|
||||
DROP TABLE IF EXISTS role_permission CASCADE;
|
||||
DROP TABLE IF EXISTS application_role CASCADE;
|
||||
DROP TABLE IF EXISTS application_permission CASCADE;
|
||||
DROP TABLE IF EXISTS application CASCADE;
|
||||
DROP TABLE IF EXISTS account_history CASCADE;
|
||||
DROP TABLE IF EXISTS mail_template CASCADE;
|
||||
DROP TABLE IF EXISTS api_key CASCADE;
|
||||
@ -1,5 +0,0 @@
|
||||
@ECHO OFF
|
||||
SET BACKUPFOLDER=%~dp0
|
||||
"C:\Program Files\PostgreSQL\10\bin\psql.exe" -U jomu --set ON_ERROR_STOP=on account < %BACKUPFOLDER%\drop_all_tables.sql
|
||||
"C:\Program Files\PostgreSQL\10\bin\psql.exe" -U jomu --set ON_ERROR_STOP=on account < %BACKUPFOLDER%\restore.dump
|
||||
pause;
|
||||
@ -1,5 +0,0 @@
|
||||
@ECHO OFF
|
||||
SET BACKUPFOLDER=%~dp0
|
||||
"C:\Program Files\PostgreSQL\10\bin\psql.exe" -U jomu --set ON_ERROR_STOP=on account_test < %BACKUPFOLDER%\drop_all_tables.sql
|
||||
"C:\Program Files\PostgreSQL\10\bin\psql.exe" -U jomu --set ON_ERROR_STOP=on account_test < %BACKUPFOLDER%\restore.dump
|
||||
pause;
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.util.Permission;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public enum AccountPermissions implements Permission {
|
||||
|
||||
ACCOUNT_ADD("account:add", "Allow to create a new account"),
|
||||
ACCOUNT_EDIT ("account:edit", "Allow to edit an existing account"),
|
||||
ACCOUNT_DELETE("account:delete", "Allow to delete an existing account"),
|
||||
ACCOUNT_LOGIN_ADD ("account:login:add", "Allow to create a login for a user"),
|
||||
ACCOUNT_LOGIN_EDIT ("account:login:edit", "Allow to change a login for a user"),
|
||||
ACCOUNT_LOGIN_DELETE ("account:login:delete", "Allow to delete a login for a user");
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private AccountPermissions(String permissionName, String permissionDesc) {
|
||||
this.name = permissionName;
|
||||
this.description = permissionDesc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,123 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
||||
import java.io.Serializable;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import javax.annotation.ManagedBean;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.SessionScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.faces.context.FacesContext;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ManagedBean
|
||||
@SessionScoped
|
||||
public class AccountProducer implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AccountProducer.class);
|
||||
private static final long serialVersionUID = -3806204732038165311L;
|
||||
private final Map<String, Object> objectMap = new ConcurrentHashMap<>();
|
||||
|
||||
@EJB
|
||||
AccountControl accountController;
|
||||
|
||||
private Account account = null;
|
||||
private Locale locale = null;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
FacesContext currentInstance = FacesContext.getCurrentInstance();
|
||||
if (currentInstance == null) {
|
||||
locale = Locale.ENGLISH;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Using default locale {}", locale);
|
||||
}
|
||||
|
||||
} else {
|
||||
locale = currentInstance.getExternalContext().getRequestLocale();
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Using browser locale {}", locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Produces
|
||||
public Account getAccount() {
|
||||
String accountName;
|
||||
if (account == null) {
|
||||
Subject subject = null;
|
||||
try {
|
||||
subject = SecurityUtils.getSubject();
|
||||
} catch (Exception ex) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.error(ex.getMessage());
|
||||
LOGGER.error("Detailed stacktrace", new Object[]{ex});
|
||||
}
|
||||
}
|
||||
if (subject == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ((subject.isAuthenticated() == false) && (subject.isRemembered() == false)) {
|
||||
return null;
|
||||
} else {
|
||||
accountName = subject.getPrincipal().toString();
|
||||
}
|
||||
account = accountController.getAccountEntity(accountName, true);
|
||||
// TODO introduce locale support to account and switch to pre-defined locale if set
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
public <T> T getValue(String key, Class<T> clazz) {
|
||||
if (objectMap.containsKey(key)) {
|
||||
Object obj = objectMap.get(key);
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
return clazz.cast(obj);
|
||||
} catch (ClassCastException ex) {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setValue(String key, Object obj) {
|
||||
objectMap.put(key, obj);
|
||||
}
|
||||
|
||||
@Produces
|
||||
public Locale getLocale() {
|
||||
return locale;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,54 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.jeeutil.restexfw.APIError;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
public enum ApiKeyError implements APIError {
|
||||
|
||||
JWT_NO_TOKEN(Response.Status.BAD_REQUEST, "1000", "jwt_no_token"),
|
||||
JWT_TOKEN_INVALID (Response.Status.FORBIDDEN, "1001", "jwt_token_invalid");
|
||||
|
||||
private final Response.Status status;
|
||||
private final String errorCode;
|
||||
private final String messageKey;
|
||||
|
||||
private ApiKeyError(Response.Status status, String errorCode, String messageKey) {
|
||||
this.status = status;
|
||||
this.errorCode = errorCode;
|
||||
this.messageKey = messageKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response.Status getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorCode() {
|
||||
return this.errorCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageKey() {
|
||||
return this.messageKey;
|
||||
}
|
||||
}
|
||||
@ -1,49 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public class ApiKeyException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = -8017749942111814929L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>ApiKeyException</code> without detail message.
|
||||
*/
|
||||
public ApiKeyException() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>ApiKeyException</code> with the specified detail message.
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public ApiKeyException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>ApiKeyException</code> with the specified detail message and root cause.
|
||||
* @param msg the detail message.
|
||||
* @param th the root cause
|
||||
*/
|
||||
public ApiKeyException(String msg, Throwable th) {
|
||||
super(msg,th);
|
||||
}
|
||||
}
|
||||
@ -1,340 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.ApiKeyEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.JWTObject;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.dao.ApiKeyObject;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTDecoder;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTEncoder;
|
||||
import de.muehlencord.shared.jeeutil.jwt.JWTException;
|
||||
import de.muehlencord.shared.util.DateUtil;
|
||||
import de.muehlencord.shared.util.StringUtil;
|
||||
import java.io.Serializable;
|
||||
import java.time.ZoneId;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.Lock;
|
||||
import javax.ejb.LockType;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.ejb.TransactionAttribute;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.persistence.TypedQuery;
|
||||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Predicate;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Stateless
|
||||
public class ApiKeyService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6981864888118320228L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApiKeyService.class);
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
AccountControl accountControl;
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
private String password;
|
||||
private String issuer;
|
||||
private Short expirationInMinutes;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
if (configService == null) {
|
||||
password = null;
|
||||
issuer = null;
|
||||
} else {
|
||||
try {
|
||||
password = configService.getConfigValue("rest.password");
|
||||
issuer = configService.getConfigValue("rest.issuer");
|
||||
expirationInMinutes = Short.parseShort(configService.getConfigValue("rest.expiration_in_minutes", "120", true));
|
||||
} catch (ConfigException | NumberFormatException | ControllerException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
password = null;
|
||||
issuer = null;
|
||||
expirationInMinutes = null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public ApiKeyEntity getApiKeyFromString(String encodedJWT) throws ApiKeyException {
|
||||
if (StringUtil.isEmpty(encodedJWT)) {
|
||||
throw new ApiKeyException("Must provide authorization information");
|
||||
}
|
||||
JWTObject jwt = getJWTObject(encodedJWT);
|
||||
Query query = em.createNamedQuery("ApiKeyEntity.findByApiKey");
|
||||
query.setParameter("apiKey", jwt.getUnqiueId());
|
||||
List<ApiKeyEntity> apiKeys = query.getResultList();
|
||||
if ((apiKeys == null) || (apiKeys.isEmpty())) {
|
||||
throw new ApiKeyException("ApiKey not found in database");
|
||||
}
|
||||
return apiKeys.get(0);
|
||||
}
|
||||
|
||||
public List<ApiKeyEntity> getUsersApiKeys(AccountEntity account, boolean onlyValid) {
|
||||
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<ApiKeyEntity> cq = cb.createQuery(ApiKeyEntity.class);
|
||||
Root<ApiKeyEntity> root = cq.from(ApiKeyEntity.class);
|
||||
Predicate accountPredicate = cb.equal(root.get("account"), account);
|
||||
Predicate searchPredicate;
|
||||
if (onlyValid) {
|
||||
Predicate expiresOnPredicate = cb.greaterThanOrEqualTo(root.get("expiresOn"), now);
|
||||
searchPredicate = cb.and(accountPredicate, expiresOnPredicate);
|
||||
} else {
|
||||
searchPredicate = accountPredicate;
|
||||
}
|
||||
cq.where(searchPredicate);
|
||||
cq.orderBy(cb.desc(root.get("expiresOn")));
|
||||
TypedQuery<ApiKeyEntity> query = em.createQuery(cq);
|
||||
List<ApiKeyEntity> resultList = query.getResultList();
|
||||
if (resultList == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return resultList;
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApiKeyEntity> getUsersApiKeys(String userName) {
|
||||
return getUsersApiKeys(accountControl.getAccountEntity(userName, false), false);
|
||||
}
|
||||
|
||||
public List<ApiKeyEntity> getValidUsersApiKeys(String userName) {
|
||||
return getUsersApiKeys(accountControl.getAccountEntity(userName, false), true);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public ApiKeyObject createNewApiKey(String userName) throws ApiKeyException {
|
||||
if (userName == null) {
|
||||
throw new ApiKeyException("Username must not be null");
|
||||
}
|
||||
return createNewApiKey(userName, expirationInMinutes);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public ApiKeyObject createNewApiKey(String userName, short expirationInMinutes) throws ApiKeyException {
|
||||
if (password == null || issuer == null || userName == null) {
|
||||
String hint = "password, issuer or username not set in, please validate configuration";
|
||||
throw new ApiKeyException(hint);
|
||||
}
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
ZonedDateTime issuedOn = ZonedDateTime.ofInstant(now.toInstant(), ZoneId.of("UTC"));
|
||||
ZonedDateTime expiresOn = issuedOn.plusMinutes(expirationInMinutes);
|
||||
Date expiresOnDate = Date.from(expiresOn.toInstant());
|
||||
String apiKeyString = RandomStringUtils.randomAscii(50);
|
||||
|
||||
ApiKeyEntity apiKey = new ApiKeyEntity();
|
||||
apiKey.setAccount(accountControl.getAccountEntity(userName, false));
|
||||
apiKey.setApiKey(apiKeyString);
|
||||
apiKey.setIssuedOn(now);
|
||||
apiKey.setExpiresOn(expiresOnDate);
|
||||
apiKey.setExpiration(expirationInMinutes);
|
||||
|
||||
return getApiKeyObject(apiKey);
|
||||
}
|
||||
|
||||
public ApiKeyObject getApiKeyObject(ApiKeyEntity apiKey) throws ApiKeyException {
|
||||
if (apiKey == null) {
|
||||
throw new ApiKeyException("ApiKey must not be null");
|
||||
}
|
||||
ZonedDateTime issuedOn = ZonedDateTime.ofInstant(apiKey.getIssuedOn().toInstant(), ZoneId.of("UTC"));
|
||||
ZonedDateTime expiresOn = issuedOn.plusMinutes(expirationInMinutes);
|
||||
AccountEntity account = apiKey.getAccount();
|
||||
if (account == null) {
|
||||
throw new ApiKeyException("Account of apiKey must not be null");
|
||||
}
|
||||
String userName = account.getUsername();
|
||||
try {
|
||||
String jwtString = JWTEncoder.encode(password, issuer, issuedOn, userName, apiKey.getApiKey(), apiKey.getExpiration());
|
||||
em.persist(apiKey);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Created API key for {}, valid for {} minutes", userName, expirationInMinutes);
|
||||
}
|
||||
|
||||
ApiKeyObject apiKeyObject = new ApiKeyObject();
|
||||
apiKeyObject.setUserName(userName);
|
||||
apiKeyObject.setIssuedOn(Date.from(apiKey.getIssuedOn().toInstant()));
|
||||
apiKeyObject.setExpiresOn(Date.from(expiresOn.toInstant()));
|
||||
apiKeyObject.setAuthToken(jwtString);
|
||||
|
||||
return apiKeyObject;
|
||||
} catch (JWTException ex) {
|
||||
throw new ApiKeyException("Cannot create apiKey. Reason: " + ex.toString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean validateJWT(String encodedJWT) {
|
||||
JWTDecoder decoder = new JWTDecoder(password, issuer, encodedJWT);
|
||||
ApiKeyEntity validKey;
|
||||
try {
|
||||
validKey = getValidKey(decoder.getSubject(), decoder.getUniqueId(), encodedJWT);
|
||||
} catch (JWTException ex) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace(ex.toString(), ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return validKey != null;
|
||||
}
|
||||
|
||||
private ApiKeyEntity getValidKey(String userName, String apiKey, String authorizationHeader) throws JWTException {
|
||||
AccountEntity userAccount = accountControl.getAccountEntity(userName, false);
|
||||
if (userAccount == null) {
|
||||
throw new JWTException("AccountControl exception");
|
||||
}
|
||||
List<ApiKeyEntity> apiKeys = getUsersApiKeys(userAccount, true);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Found {} keys for user {}", apiKeys.size(), userName);
|
||||
}
|
||||
|
||||
Iterator<ApiKeyEntity> it = apiKeys.iterator();
|
||||
ApiKeyEntity keyToLogout = null;
|
||||
while (keyToLogout == null && it.hasNext()) {
|
||||
ApiKeyEntity key = it.next();
|
||||
if (key.getApiKey().equals(apiKey)) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Found API key in database");
|
||||
}
|
||||
|
||||
ZonedDateTime issuedOn = ZonedDateTime.ofInstant(key.getIssuedOn().toInstant(), ZoneOffset.UTC);
|
||||
String testString = JWTEncoder.encode(password, issuer, issuedOn, key.getAccount().getUsername(), key.getApiKey(), key.getExpiration());
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Successfully created validation JWT for user {}", userName);
|
||||
}
|
||||
|
||||
if (authorizationHeader.equals(testString)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Found valid key for user {}", userName);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("No valid key for user {} found", userName);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getJWTFromApiKey(ApiKeyEntity apiKey) throws ApiKeyException {
|
||||
ZonedDateTime issuedAt = ZonedDateTime.ofInstant(apiKey.getIssuedOn().toInstant(), ZoneOffset.UTC);
|
||||
try {
|
||||
return JWTEncoder.encode(password, issuer, issuedAt, apiKey.getAccount().getUsername(), apiKey.getApiKey(), apiKey.getExpiration());
|
||||
} catch (JWTException ex) {
|
||||
throw new ApiKeyException("Cannot retrieve JWT from key. Reason: " + ex.toString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public JWTObject getJWTObject(String encodedJWT) {
|
||||
JWTDecoder decoder = new JWTDecoder(password, issuer, encodedJWT);
|
||||
JWTObject jwtObject = new JWTObject();
|
||||
jwtObject.setUserName(decoder.getSubject());
|
||||
jwtObject.setUnqiueId(decoder.getUniqueId());
|
||||
jwtObject.setValid(true);
|
||||
return jwtObject;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param apiKey
|
||||
* @deprecated use delete (jwtObject) instead
|
||||
*/
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@Deprecated
|
||||
public void delete(ApiKeyEntity apiKey) {
|
||||
em.remove(em.merge(apiKey));
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public void delete(String authorizationHeader) throws ApiKeyException {
|
||||
|
||||
JWTObject jwtObject = getJWTObject(authorizationHeader);
|
||||
if (jwtObject.isValid()) {
|
||||
String userName = jwtObject.getUserName();
|
||||
|
||||
ApiKeyEntity keyToLogout;
|
||||
try {
|
||||
keyToLogout = getValidKey(userName, jwtObject.getUnqiueId(), authorizationHeader);
|
||||
} catch (JWTException ex) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
keyToLogout = null;
|
||||
}
|
||||
|
||||
if (keyToLogout == null) {
|
||||
// no valid key found - must not happen, JWTVeryfingFIlter should have catched this
|
||||
// FIXME - add logging / handle this problem
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("No valid key found, probably user {} has already logged out", userName);
|
||||
}
|
||||
throw new ApiKeyException("No valid key found, probably user " + userName + " has already logged out");
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Found matching apiKey to logout");
|
||||
}
|
||||
em.remove(em.merge(keyToLogout));
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Key deleted, user {} logged out from webservice", userName);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw new ApiKeyException("Provided JWT is not valid");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,427 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountLoginEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountStatus;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
|
||||
import de.muehlencord.shared.account.business.mail.boundary.MailService;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailException;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.account.util.SecurityUtil;
|
||||
import de.muehlencord.shared.util.DateUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javax.ejb.EJB;
|
||||
import javax.ejb.Lock;
|
||||
import javax.ejb.LockType;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.ejb.TransactionAttribute;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.NoResultException;
|
||||
import javax.persistence.Query;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Stateless
|
||||
public class AccountControl implements Serializable {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AccountControl.class.getName());
|
||||
private static final long serialVersionUID = 3424816272598108101L;
|
||||
|
||||
@EJB
|
||||
private MailService mailService;
|
||||
|
||||
@Inject
|
||||
private ApplicationEntity application;
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
public List<AccountEntity> getAllAccounts(boolean includeDisabled) {
|
||||
List<AccountEntity> resultList;
|
||||
if (includeDisabled) {
|
||||
resultList = getAllAccounts();
|
||||
} else {
|
||||
resultList = getActiveAccounts();
|
||||
}
|
||||
|
||||
if (SecurityUtil.checkPermission(ApplicationPermissions.ACCOUNT_LIST)) {
|
||||
return resultList;
|
||||
} else {
|
||||
String currentUserName = SecurityUtils.getSubject().getPrincipal().toString();
|
||||
return resultList.stream()
|
||||
.filter(account -> account.getAccountLogin() != null)
|
||||
.filter(account -> account.getUsername().equals(currentUserName))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of active accounts
|
||||
*
|
||||
* @return a list of active accounts
|
||||
*/
|
||||
private List<AccountEntity> getActiveAccounts() {
|
||||
Query query = em.createNamedQuery("AccountEntity.findActiveAccounts");
|
||||
query.setParameter("status", AccountStatus.DISABLED.name());
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a list of active accounts
|
||||
*
|
||||
* @return a list of active accounts
|
||||
*/
|
||||
private List<AccountEntity> getAllAccounts() {
|
||||
Query query = em.createNamedQuery("AccountEntity.findAll");
|
||||
return query.getResultList();
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public AccountEntity getAccountEntity(String userName, boolean loadRoles) {
|
||||
StringBuilder queryBuilder = new StringBuilder();
|
||||
queryBuilder.append("SELECT a FROM AccountEntity a ");
|
||||
if (loadRoles) {
|
||||
queryBuilder.append("LEFT JOIN FETCH a.applicationRoleList ");
|
||||
}
|
||||
queryBuilder.append("WHERE a.username = :username");
|
||||
Query query = em.createQuery(queryBuilder.toString());
|
||||
query.setParameter("username", userName);
|
||||
try {
|
||||
return (AccountEntity) query.getSingleResult();
|
||||
} catch (NoResultException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AccountEntity saveAccount(AccountEntity account, ApplicationEntity app, List<ApplicationRoleEntity> applicationRoles) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
String currentLoggedInUser = currentUser.getPrincipal().toString();
|
||||
|
||||
account.setLastUpdatedBy(currentLoggedInUser); // FIXME - should be done via updateable
|
||||
account.setLastUpdatedOn(now);
|
||||
|
||||
boolean newAccount = (account.getCreatedOn() == null);
|
||||
|
||||
// new account
|
||||
if (newAccount) {
|
||||
account.setCreatedOn(now);
|
||||
account.setCreatedBy(currentLoggedInUser);
|
||||
em.persist(account);
|
||||
} else {
|
||||
em.merge(account);
|
||||
|
||||
// reload account from db and join roles
|
||||
account = getAccountEntity(account.getUsername(), true);
|
||||
}
|
||||
|
||||
// assign roles to account
|
||||
if (account.getApplicationRoleList() == null) {
|
||||
account.setApplicationRoleList(new ArrayList<>());
|
||||
}
|
||||
|
||||
boolean roleSetupChanged = false;
|
||||
// remove roles which are no longer listed
|
||||
// ensure this is only done for the given application - keep the other applications untouched
|
||||
List<ApplicationRoleEntity> assignedRoles = new ArrayList<>();
|
||||
assignedRoles.addAll(account.getApplicationRoleList());
|
||||
for (ApplicationRoleEntity currentlyAssignedRole : assignedRoles) {
|
||||
if ((currentlyAssignedRole.getApplication().equals(app) && (!applicationRoles.contains(currentlyAssignedRole)))) {
|
||||
account.getApplicationRoleList().remove(currentlyAssignedRole);
|
||||
roleSetupChanged = true;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Removed role {} ({}) from user {}", currentlyAssignedRole.getRoleName(), application.getApplicationName(), account.getUsername());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add newly added roles to role list
|
||||
for (ApplicationRoleEntity applicationRole : applicationRoles) {
|
||||
if (!account.getApplicationRoleList().contains(applicationRole)) {
|
||||
account.addApplicationRole(applicationRole);
|
||||
roleSetupChanged = true;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Added role {} ({}) to account {}", applicationRole.getRoleName(), application.getApplicationName(), account.getUsername());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update account in database if roles changed
|
||||
if (roleSetupChanged) {
|
||||
em.merge(account);
|
||||
}
|
||||
return account;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteAccount(AccountEntity account) throws AccountException {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
String currentUserName = currentUser.getPrincipal().toString();
|
||||
|
||||
if (account.getUsername().equals(currentUserName)) {
|
||||
throw new AccountException("Cannot delete own account");
|
||||
} else {
|
||||
account.setStatus(AccountStatus.DISABLED.name());
|
||||
account.setLastUpdatedBy(currentUserName);
|
||||
account.setLastUpdatedOn(now);
|
||||
em.merge(account);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean initPasswordReset(String userName) {
|
||||
try {
|
||||
AccountEntity account = getAccountEntity(userName, false);
|
||||
if (account == null) {
|
||||
LOGGER.warn("Account with name " + userName + " not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account.getAccountLogin() == null) {
|
||||
LOGGER.error("No login for account {} defined, cannot reset password", userName);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account.getStatus().equals(AccountStatus.BLOCKED.name())) {
|
||||
LOGGER.warn("Account " + userName + " is locked, cannot initialize password reset");
|
||||
return false;
|
||||
}
|
||||
|
||||
String randomString = RandomStringUtils.random(40, true, true);
|
||||
|
||||
Date validTo = DateUtil.getCurrentTimeInUTC();
|
||||
validTo = new Date(validTo.getTime() + 1000 * 600); // 10 minutes to react
|
||||
|
||||
account.getAccountLogin().setPasswordResetHash(randomString);
|
||||
account.getAccountLogin().setPasswordResetOngoing(true);
|
||||
account.getAccountLogin().setPasswordResetValidTo(validTo);
|
||||
mailService.sendPasswortResetStartEmail(account, randomString);
|
||||
|
||||
em.merge(account.getAccountLogin());
|
||||
em.merge(account);
|
||||
return true;
|
||||
} catch (MailException | ConfigException ex) {
|
||||
LOGGER.error("Error while sending password reset mail. " + ex.toString());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Error while sending password reset mail.", ex);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public boolean resetPassword(String userName, String newPassword, String resetPasswordToken) {
|
||||
AccountEntity account = getAccountEntity(userName, false);
|
||||
|
||||
if (account == null) {
|
||||
LOGGER.warn("Error while resetting password, no account with username " + userName + " found");
|
||||
// TODO add extra logging for intrusion protection system like fail2ban
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account.getAccountLogin() == null) {
|
||||
// user has no defined login, cannot reset password
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account.getAccountLogin().getPasswordResetOngoing() && (account.getAccountLogin().getPasswordResetHash() != null) && (account.getAccountLogin().getPasswordResetValidTo() != null)) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
String storedHash = account.getAccountLogin().getPasswordResetHash().trim();
|
||||
if (account.getAccountLogin().getPasswordResetValidTo().after(now)) {
|
||||
if (storedHash.equals(resetPasswordToken)) {
|
||||
// everything ok, reset password
|
||||
executePasswordReset(account, newPassword);
|
||||
LOGGER.info("Updated password for user " + userName);
|
||||
return true;
|
||||
} else {
|
||||
// token is not valid, refuse to change password
|
||||
LOGGER.warn("Trying to reset password for user " + userName + " but wrong token " + resetPasswordToken + " provided");
|
||||
addLoginError(account);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// password reset token no longer valid
|
||||
LOGGER.warn("Trying to reset password for user " + userName + " but token is no longer valid");
|
||||
addLoginError(account);
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// user is not is password reset mode
|
||||
LOGGER.warn("Trying to reset password for user " + userName + " but password reset was not requested");
|
||||
addLoginError(account);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private void executePasswordReset(AccountEntity account, String newPassword) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
|
||||
String hashedPassword = SecurityUtil.createPassword(newPassword);
|
||||
if (account.getAccountLogin() == null) {
|
||||
return;
|
||||
}
|
||||
account.getAccountLogin().setAccountPassword(hashedPassword);
|
||||
account.getAccountLogin().setPasswordResetOngoing(false);
|
||||
account.getAccountLogin().setPasswordResetHash(null);
|
||||
account.getAccountLogin().setPasswordResetValidTo(null);
|
||||
account.setLastUpdatedBy(account.getUsername());
|
||||
account.setLastUpdatedOn(now);
|
||||
em.merge(account);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AccountLoginEntity updateSuccessFullLogin(AccountLoginEntity login, String byUser) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
// a scucessful login ends a password reset procedure
|
||||
if (login.getPasswordResetOngoing()) {
|
||||
login.setPasswordResetOngoing(false);
|
||||
login.setPasswordResetHash(null);
|
||||
login.setPasswordResetValidTo(null);
|
||||
login.setLastUpdatedOn(now);
|
||||
login.setLastUpdatedBy(byUser);
|
||||
}
|
||||
|
||||
login.setLastLogin(now);
|
||||
login.setFailureCount(0);
|
||||
return updateLogin(login);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public AccountLoginEntity updateLogin(AccountLoginEntity login) {
|
||||
return em.merge(login);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void updateLogin(AccountEntity account) {
|
||||
if (account.getAccountLogin() == null) {
|
||||
// TODO connect to IPRS - how can an account ask for an updated login if the user cannot login
|
||||
} else {
|
||||
updateSuccessFullLogin(account.getAccountLogin(), account.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addLoginError(AccountEntity account) {
|
||||
if (account.getAccountLogin() == null) {
|
||||
LOGGER.error("No login defined for {}", account.getUsername());
|
||||
} else {
|
||||
try {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
account.getAccountLogin().setLastFailedLogin(now);
|
||||
account.getAccountLogin().setFailureCount(account.getAccountLogin().getFailureCount() + 1);
|
||||
|
||||
int maxFailedLogins = Integer.parseInt(configService.getConfigValue("account.maxFailedLogins"));
|
||||
if ((account.getAccountLogin().getFailureCount() >= maxFailedLogins) && (!account.getStatus().equals("LOCKED"))) { // TOD add status enum
|
||||
// max failed logins reached, disabling user
|
||||
LOGGER.info("Locking account " + account.getUsername() + " due to " + account.getAccountLogin().getFailureCount() + " failed logins");
|
||||
account.setStatus(AccountStatus.BLOCKED.name());
|
||||
}
|
||||
|
||||
// on a failed login request, disable password reset
|
||||
account.getAccountLogin().setPasswordResetOngoing(false);
|
||||
account.getAccountLogin().setPasswordResetHash(null);
|
||||
account.getAccountLogin().setPasswordResetValidTo(null);
|
||||
|
||||
account.setLastUpdatedBy("system");
|
||||
account.setLastUpdatedOn(now);
|
||||
em.merge(account);
|
||||
} catch (ConfigException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AccountLoginEntity createLoginWithRandomPassword() {
|
||||
AccountLoginEntity login = new AccountLoginEntity();
|
||||
String randomPassword = RandomStringUtils.random(20, true, true);
|
||||
String hashedPassword = SecurityUtil.createPassword(randomPassword);
|
||||
login.setAccountPassword(hashedPassword);
|
||||
login.setLastLogin(null);
|
||||
login.setLastFailedLogin(null);
|
||||
login.setFailureCount(0);
|
||||
|
||||
return login;
|
||||
}
|
||||
|
||||
public String getHashedPassword(String password) {
|
||||
String hashedPassword = SecurityUtil.createPassword(password);
|
||||
return hashedPassword;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addLogin(AccountEntity accountToAdd, AccountLoginEntity accountLogin) {
|
||||
Date now = DateUtil.getCurrentTimeInUTC();
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
String currentLoggedInUser = currentUser.getPrincipal().toString();
|
||||
|
||||
AccountEntity account = em.merge(accountToAdd);
|
||||
accountLogin.setAccount(account);
|
||||
accountLogin.setCreatedBy(currentLoggedInUser);
|
||||
accountLogin.setCreatedOn(now);
|
||||
accountLogin.setLastUpdatedBy(currentLoggedInUser);
|
||||
accountLogin.setLastUpdatedOn(now);
|
||||
em.persist(accountLogin);
|
||||
|
||||
account.setAccountLogin(accountLogin);
|
||||
em.merge(account);
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void deleteLogin(AccountEntity accountToDelete) {
|
||||
AccountEntity account = em.merge(accountToDelete);
|
||||
AccountLoginEntity login = account.getAccountLogin();
|
||||
login.setAccount(null);
|
||||
account.setAccountLogin(null);
|
||||
em.remove(login);
|
||||
em.merge(account);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,28 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public interface Account {
|
||||
|
||||
String getUsername();
|
||||
String getFirstname();
|
||||
String getLastname();
|
||||
|
||||
}
|
||||
@ -1,29 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public enum AccountConfigurationKey {
|
||||
// the base path of the application
|
||||
BaseUrl,
|
||||
// the full pass to the reset password page
|
||||
PasswordResetUrl,
|
||||
// injection handler
|
||||
Producer;
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.enterprise.util.Nonbinding;
|
||||
import javax.inject.Qualifier;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.METHOD})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Qualifier
|
||||
public @interface AccountConfigurationValue {
|
||||
|
||||
@Nonbinding
|
||||
AccountConfigurationKey key();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -1,285 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
* IMPORANT: DO NOT CACHE - e.g. password changes are not synchronized
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "account")
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "AccountEntity.findAll", query = "SELECT a FROM AccountEntity a ORDER by a.lastname, a.firstname"),
|
||||
@NamedQuery(name = "AccountEntity.findByUsername", query = "SELECT a FROM AccountEntity a WHERE a.username = :username"),
|
||||
@NamedQuery(name = "AccountEntity.findByStatus", query = "SELECT a FROM AccountEntity a WHERE a.status = :status"),
|
||||
@NamedQuery(name = "AccountEntity.findActiveAccounts", query = "SELECT a FROM AccountEntity a WHERE a.status <> :status"),
|
||||
@NamedQuery(name = "AccountEntity.findByCreatedOn", query = "SELECT a FROM AccountEntity a WHERE a.createdOn = :createdOn"),
|
||||
@NamedQuery(name = "AccountEntity.findByCreatedBy", query = "SELECT a FROM AccountEntity a WHERE a.createdBy = :createdBy"),
|
||||
@NamedQuery(name = "AccountEntity.findByLastUpdatedOn", query = "SELECT a FROM AccountEntity a WHERE a.lastUpdatedOn = :lastUpdatedOn"),
|
||||
@NamedQuery(name = "AccountEntity.findByLastUpdatedBy", query = "SELECT a FROM AccountEntity a WHERE a.lastUpdatedBy = :lastUpdatedBy")
|
||||
})
|
||||
public class AccountEntity implements Serializable, Account {
|
||||
|
||||
private static final long serialVersionUID = 2174163529615355336L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "username")
|
||||
private String username;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "emailaddress")
|
||||
private String emailaddress;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 100)
|
||||
@Column(name = "firstname")
|
||||
private String firstname;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 100)
|
||||
@Column(name = "lastname")
|
||||
private String lastname;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 10)
|
||||
@Column(name = "status")
|
||||
private String status;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "created_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdOn;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "created_by")
|
||||
private String createdBy;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "last_updated_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastUpdatedOn;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "last_updated_by")
|
||||
private String lastUpdatedBy;
|
||||
@JoinTable(name = "account_role", joinColumns = {
|
||||
@JoinColumn(name = "account", referencedColumnName = "id")}, inverseJoinColumns = {
|
||||
@JoinColumn(name = "account_role", referencedColumnName = "id")})
|
||||
@ManyToMany(fetch = FetchType.LAZY)
|
||||
private List<ApplicationRoleEntity> applicationRoleList;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "accountId", fetch = FetchType.LAZY)
|
||||
private List<AccountHistoryEntity> accountHistoryList;
|
||||
@OneToOne(cascade = CascadeType.ALL, mappedBy = "account")
|
||||
private AccountLoginEntity accountLogin;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "account")
|
||||
private List<ConfigEntity> configItems;
|
||||
|
||||
public AccountEntity() {
|
||||
// empty constructor required for JPA
|
||||
}
|
||||
|
||||
public void addApplicationRole(ApplicationRoleEntity applicationRole) {
|
||||
if (applicationRoleList == null) {
|
||||
applicationRoleList = new ArrayList<>();
|
||||
}
|
||||
applicationRoleList.add(applicationRole);
|
||||
}
|
||||
|
||||
/* **** getter / setter **** */
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getEmailaddress() {
|
||||
return emailaddress;
|
||||
}
|
||||
|
||||
public void setEmailaddress(String emailaddress) {
|
||||
this.emailaddress = emailaddress;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public void setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getCreatedOn() {
|
||||
return createdOn;
|
||||
}
|
||||
|
||||
public void setCreatedOn(Date createdOn) {
|
||||
this.createdOn = createdOn;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public Date getLastUpdatedOn() {
|
||||
return lastUpdatedOn;
|
||||
}
|
||||
|
||||
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||
this.lastUpdatedOn = lastUpdatedOn;
|
||||
}
|
||||
|
||||
public String getLastUpdatedBy() {
|
||||
return lastUpdatedBy;
|
||||
}
|
||||
|
||||
public void setLastUpdatedBy(String lastUpdatedBy) {
|
||||
this.lastUpdatedBy = lastUpdatedBy;
|
||||
}
|
||||
|
||||
public List<ApplicationRoleEntity> getApplicationRoleList() {
|
||||
return applicationRoleList;
|
||||
}
|
||||
|
||||
public void setApplicationRoleList(List<ApplicationRoleEntity> applicationRoleList) {
|
||||
this.applicationRoleList = applicationRoleList;
|
||||
}
|
||||
|
||||
public List<AccountHistoryEntity> getAccountHistoryList() {
|
||||
return accountHistoryList;
|
||||
}
|
||||
|
||||
public void setAccountHistoryList(List<AccountHistoryEntity> accountHistoryList) {
|
||||
this.accountHistoryList = accountHistoryList;
|
||||
}
|
||||
|
||||
public AccountLoginEntity getAccountLogin() {
|
||||
return accountLogin;
|
||||
}
|
||||
|
||||
public void setAccountLogin(AccountLoginEntity accountLogin) {
|
||||
this.accountLogin = accountLogin;
|
||||
}
|
||||
|
||||
public List<ConfigEntity> getConfigItems() {
|
||||
return configItems;
|
||||
}
|
||||
|
||||
public void setConfigItems(List<ConfigEntity> configItems) {
|
||||
this.configItems = configItems;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof AccountEntity)) {
|
||||
return false;
|
||||
}
|
||||
AccountEntity other = (AccountEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.entity.Account[ id=" + id + " ]";
|
||||
}
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Raimund
|
||||
*/
|
||||
public class AccountException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>AccountException</code> without detail
|
||||
* message.
|
||||
*/
|
||||
public AccountException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>AccountException</code> with the
|
||||
* specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public AccountException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public AccountException(String entity_updated__deleted_please_reload, boolean b) {
|
||||
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
|
||||
}
|
||||
}
|
||||
@ -1,189 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "account_history")
|
||||
@Cacheable
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "AccountHistoryEntity.findAll", query = "SELECT a FROM AccountHistoryEntity a"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findById", query = "SELECT a FROM AccountHistoryEntity a WHERE a.id = :id"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findByMessage", query = "SELECT a FROM AccountHistoryEntity a WHERE a.message = :message"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findByFailureCount", query = "SELECT a FROM AccountHistoryEntity a WHERE a.failureCount = :failureCount"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findByStatus", query = "SELECT a FROM AccountHistoryEntity a WHERE a.status = :status"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findByLastUpdatedOn", query = "SELECT a FROM AccountHistoryEntity a WHERE a.lastUpdatedOn = :lastUpdatedOn"),
|
||||
@NamedQuery(name = "AccountHistoryEntity.findByLastUpdatedBy", query = "SELECT a FROM AccountHistoryEntity a WHERE a.lastUpdatedBy = :lastUpdatedBy")})
|
||||
public class AccountHistoryEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Size(max = 200)
|
||||
@Column(name = "message")
|
||||
private String message;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "failure_count")
|
||||
private int failureCount;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 20)
|
||||
@Column(name = "status")
|
||||
private String status;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "last_updated_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastUpdatedOn;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "last_updated_by")
|
||||
private String lastUpdatedBy;
|
||||
@JoinColumn(name = "account_id", referencedColumnName = "id")
|
||||
@ManyToOne(optional = false)
|
||||
private AccountEntity accountId;
|
||||
|
||||
public AccountHistoryEntity() {
|
||||
}
|
||||
|
||||
public AccountHistoryEntity(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public AccountHistoryEntity(UUID id, int failureCount, String status, Date lastUpdatedOn, String lastUpdatedBy) {
|
||||
this.id = id;
|
||||
this.failureCount = failureCount;
|
||||
this.status = status;
|
||||
this.lastUpdatedOn = lastUpdatedOn;
|
||||
this.lastUpdatedBy = lastUpdatedBy;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public int getFailureCount() {
|
||||
return failureCount;
|
||||
}
|
||||
|
||||
public void setFailureCount(int failureCount) {
|
||||
this.failureCount = failureCount;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Date getLastUpdatedOn() {
|
||||
return lastUpdatedOn;
|
||||
}
|
||||
|
||||
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||
this.lastUpdatedOn = lastUpdatedOn;
|
||||
}
|
||||
|
||||
public String getLastUpdatedBy() {
|
||||
return lastUpdatedBy;
|
||||
}
|
||||
|
||||
public void setLastUpdatedBy(String lastUpdatedBy) {
|
||||
this.lastUpdatedBy = lastUpdatedBy;
|
||||
}
|
||||
|
||||
public AccountEntity getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(AccountEntity accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof AccountHistoryEntity)) {
|
||||
return false;
|
||||
}
|
||||
AccountHistoryEntity other = (AccountHistoryEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.entity.AccountHistory[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,255 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "account_login")
|
||||
@Cacheable
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "AccountLoginEntity.findAll", query = "SELECT a FROM AccountLoginEntity a"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByAccountPassword", query = "SELECT a FROM AccountLoginEntity a WHERE a.accountPassword = :accountPassword"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByLastLogin", query = "SELECT a FROM AccountLoginEntity a WHERE a.lastLogin = :lastLogin"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByLastFailedLogin", query = "SELECT a FROM AccountLoginEntity a WHERE a.lastFailedLogin = :lastFailedLogin"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByFailureCount", query = "SELECT a FROM AccountLoginEntity a WHERE a.failureCount = :failureCount"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByPasswordResetOngoing", query = "SELECT a FROM AccountLoginEntity a WHERE a.passwordResetOngoing = :passwordResetOngoing"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByPasswordResetValidTo", query = "SELECT a FROM AccountLoginEntity a WHERE a.passwordResetValidTo = :passwordResetValidTo"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByPasswordResetHash", query = "SELECT a FROM AccountLoginEntity a WHERE a.passwordResetHash = :passwordResetHash"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByCreatedOn", query = "SELECT a FROM AccountLoginEntity a WHERE a.createdOn = :createdOn"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByCreatedBy", query = "SELECT a FROM AccountLoginEntity a WHERE a.createdBy = :createdBy"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByLastUpdatedOn", query = "SELECT a FROM AccountLoginEntity a WHERE a.lastUpdatedOn = :lastUpdatedOn"),
|
||||
@NamedQuery(name = "AccountLoginEntity.findByLastUpdatedBy", query = "SELECT a FROM AccountLoginEntity a WHERE a.lastUpdatedBy = :lastUpdatedBy")})
|
||||
public class AccountLoginEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -799045989045040077L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "account_password")
|
||||
private String accountPassword;
|
||||
@Column(name = "last_login")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastLogin;
|
||||
@Column(name = "last_failed_login")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastFailedLogin;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "failure_count")
|
||||
private int failureCount;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "password_reset_ongoing")
|
||||
private boolean passwordResetOngoing;
|
||||
@Column(name = "password_reset_valid_to")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date passwordResetValidTo;
|
||||
@Size(max = 200)
|
||||
@Column(name = "password_reset_hash")
|
||||
private String passwordResetHash;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "created_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date createdOn;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "created_by")
|
||||
private String createdBy;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "last_updated_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date lastUpdatedOn;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 32)
|
||||
@Column(name = "last_updated_by")
|
||||
private String lastUpdatedBy;
|
||||
@JoinColumn(name = "account", referencedColumnName = "id")
|
||||
@OneToOne(optional = false)
|
||||
private AccountEntity account;
|
||||
|
||||
public AccountLoginEntity() {
|
||||
}
|
||||
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getAccountPassword() {
|
||||
return accountPassword;
|
||||
}
|
||||
|
||||
public void setAccountPassword(String accountPassword) {
|
||||
this.accountPassword = accountPassword;
|
||||
}
|
||||
|
||||
public Date getLastLogin() {
|
||||
return lastLogin;
|
||||
}
|
||||
|
||||
public void setLastLogin(Date lastLogin) {
|
||||
this.lastLogin = lastLogin;
|
||||
}
|
||||
|
||||
public Date getLastFailedLogin() {
|
||||
return lastFailedLogin;
|
||||
}
|
||||
|
||||
public void setLastFailedLogin(Date lastFailedLogin) {
|
||||
this.lastFailedLogin = lastFailedLogin;
|
||||
}
|
||||
|
||||
public int getFailureCount() {
|
||||
return failureCount;
|
||||
}
|
||||
|
||||
public void setFailureCount(int failureCount) {
|
||||
this.failureCount = failureCount;
|
||||
}
|
||||
|
||||
public boolean getPasswordResetOngoing() {
|
||||
return passwordResetOngoing;
|
||||
}
|
||||
|
||||
public void setPasswordResetOngoing(boolean passwordResetOngoing) {
|
||||
this.passwordResetOngoing = passwordResetOngoing;
|
||||
}
|
||||
|
||||
public Date getPasswordResetValidTo() {
|
||||
return passwordResetValidTo;
|
||||
}
|
||||
|
||||
public void setPasswordResetValidTo(Date passwordResetValidTo) {
|
||||
this.passwordResetValidTo = passwordResetValidTo;
|
||||
}
|
||||
|
||||
public String getPasswordResetHash() {
|
||||
return passwordResetHash;
|
||||
}
|
||||
|
||||
public void setPasswordResetHash(String passwordResetHash) {
|
||||
this.passwordResetHash = passwordResetHash;
|
||||
}
|
||||
|
||||
public Date getCreatedOn() {
|
||||
return createdOn;
|
||||
}
|
||||
|
||||
public void setCreatedOn(Date createdOn) {
|
||||
this.createdOn = createdOn;
|
||||
}
|
||||
|
||||
public String getCreatedBy() {
|
||||
return createdBy;
|
||||
}
|
||||
|
||||
public void setCreatedBy(String createdBy) {
|
||||
this.createdBy = createdBy;
|
||||
}
|
||||
|
||||
public Date getLastUpdatedOn() {
|
||||
return lastUpdatedOn;
|
||||
}
|
||||
|
||||
public void setLastUpdatedOn(Date lastUpdatedOn) {
|
||||
this.lastUpdatedOn = lastUpdatedOn;
|
||||
}
|
||||
|
||||
public String getLastUpdatedBy() {
|
||||
return lastUpdatedBy;
|
||||
}
|
||||
|
||||
public void setLastUpdatedBy(String lastUpdatedBy) {
|
||||
this.lastUpdatedBy = lastUpdatedBy;
|
||||
}
|
||||
|
||||
public AccountEntity getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(AccountEntity account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof AccountLoginEntity)) {
|
||||
return false;
|
||||
}
|
||||
AccountLoginEntity other = (AccountLoginEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.business.account.entity.AccountLoginEntity[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
public enum AccountStatus {
|
||||
|
||||
NEW, // account is created but never used
|
||||
NORMAL, // normal account, at least on login, neither blocked or disabled
|
||||
BLOCKED, // account is blocked after too many login failures or other security related events
|
||||
DISABLED; // account is disabled and cannot be used anymore
|
||||
|
||||
public static List<String> getAllStatusNames() {
|
||||
List<String> statusNames = new ArrayList<>();
|
||||
for (AccountStatus currentStatus : AccountStatus.values()) {
|
||||
statusNames.add (currentStatus.name());
|
||||
}
|
||||
return statusNames;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,171 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Entity
|
||||
@Cacheable
|
||||
@Table(name = "api_key")
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ApiKeyEntity.findAll", query = "SELECT a FROM ApiKeyEntity a"),
|
||||
@NamedQuery(name = "ApiKeyEntity.findByApiKey", query = "SELECT a FROM ApiKeyEntity a WHERE a.apiKey = :apiKey",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApiKeyEntity.findByIssuedOn", query = "SELECT a FROM ApiKeyEntity a WHERE a.issuedOn = :issuedOn"),
|
||||
@NamedQuery(name = "ApiKeyEntity.findByAccount", query = "SELECT a FROM ApiKeyEntity a WHERE a.account = :account ORDER BY a.issuedOn DESC",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApiKeyEntity.findByExpiration", query = "SELECT a FROM ApiKeyEntity a WHERE a.expiration = :expiration")})
|
||||
public class ApiKeyEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1044658457228215810L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "api_key")
|
||||
private String apiKey;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "issued_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date issuedOn;
|
||||
@Column(name = "expiration")
|
||||
private Short expiration;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "expires_on")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
private Date expiresOn;
|
||||
@JoinColumn(name = "account", referencedColumnName = "id")
|
||||
@ManyToOne(optional = false)
|
||||
private AccountEntity account;
|
||||
|
||||
public ApiKeyEntity() {
|
||||
// empty constructor required for JPA
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getApiKey() {
|
||||
return apiKey;
|
||||
}
|
||||
|
||||
public void setApiKey(String apiKey) {
|
||||
this.apiKey = apiKey;
|
||||
}
|
||||
|
||||
public Date getIssuedOn() {
|
||||
return issuedOn;
|
||||
}
|
||||
|
||||
public void setIssuedOn(Date issuedOn) {
|
||||
this.issuedOn = issuedOn;
|
||||
}
|
||||
|
||||
public Short getExpiration() {
|
||||
return expiration;
|
||||
}
|
||||
|
||||
public void setExpiration(Short expiration) {
|
||||
this.expiration = expiration;
|
||||
}
|
||||
|
||||
public Date getExpiresOn() {
|
||||
return expiresOn;
|
||||
}
|
||||
|
||||
public void setExpiresOn(Date expiresOn) {
|
||||
this.expiresOn = expiresOn;
|
||||
}
|
||||
|
||||
public AccountEntity getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(AccountEntity account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ApiKeyEntity)) {
|
||||
return false;
|
||||
}
|
||||
ApiKeyEntity other = (ApiKeyEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "com.wincornixdorf.pcd.business.account.ApiKeyEntity[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.account.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public class JWTObject {
|
||||
|
||||
private String userName;
|
||||
private String unqiueId;
|
||||
private boolean valid;
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getUnqiueId() {
|
||||
return unqiueId;
|
||||
}
|
||||
|
||||
public void setUnqiueId(String unqiueId) {
|
||||
this.unqiueId = unqiueId;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
public void setValid(boolean valid) {
|
||||
this.valid = valid;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@ -1,46 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.util.SecurityError;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public enum ApplicationError implements SecurityError {
|
||||
|
||||
LIST_DENIED("1000", "list_denied");
|
||||
|
||||
private final String errorCode;
|
||||
private final String messageKey;
|
||||
|
||||
private ApplicationError(String errorCode, String messageKey) {
|
||||
this.errorCode = errorCode;
|
||||
this.messageKey = messageKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getErrorCode() {
|
||||
return errorCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessageKey() {
|
||||
return messageKey;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,130 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.instance.boundary.ApplicationPermissions;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.account.util.AccountSecurityException;
|
||||
import de.muehlencord.shared.account.util.SecurityUtil;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Stateless
|
||||
public class ApplicationControl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4262608935325326191L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationControl.class);
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
public ApplicationEntity findById(UUID id) {
|
||||
return em.find(ApplicationEntity.class, id);
|
||||
}
|
||||
|
||||
public List<ApplicationEntity> getAllApplications() throws AccountSecurityException {
|
||||
List<ApplicationEntity> resultList = new ArrayList<>();
|
||||
Query query = em.createNamedQuery("ApplicationEntity.findAll");
|
||||
List<ApplicationEntity> queryList = query.getResultList();
|
||||
if ((queryList == null) || (queryList.isEmpty())) {
|
||||
return resultList;
|
||||
}
|
||||
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
if (currentUser == null)
|
||||
return resultList;
|
||||
String userName = currentUser.getPrincipal().toString();
|
||||
|
||||
queryList.stream().forEach(app -> {
|
||||
String applicationName = app.getApplicationName(); // TODO add unique short cut to db model
|
||||
applicationName = applicationName.toLowerCase();
|
||||
applicationName = applicationName.replace (" ", "");
|
||||
String permissionName = ApplicationPermissions.APP_LIST.getName()+":"+applicationName;
|
||||
boolean userHasPermissionToListApplication = SecurityUtil.checkPermission (permissionName);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("validating if user {} has permission {} = {}", userName, permissionName, userHasPermissionToListApplication);
|
||||
}
|
||||
|
||||
if (userHasPermissionToListApplication) {
|
||||
resultList.add (app);
|
||||
}
|
||||
});
|
||||
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ApplicationEntity createOrUpdate(ApplicationEntity app) {
|
||||
if (app == null) {
|
||||
// TODO add error handling
|
||||
return null;
|
||||
} else {
|
||||
if (app.getId() == null) {
|
||||
em.persist(app);
|
||||
ApplicationEntity returnValue = findByApplicationName(app.getApplicationName());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Application {} created", app.getApplicationName());
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
} else {
|
||||
ApplicationEntity returnValue = em.merge(app);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Applicateion {} updated", app.getApplicationName());
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationEntity findByApplicationName(String applicationName) {
|
||||
Query query = em.createNamedQuery("ApplicationEntity.findByApplicationName");
|
||||
query.setParameter("applicationName", applicationName);
|
||||
List<ApplicationEntity> resultList = query.getResultList();
|
||||
if ((resultList == null) || (resultList.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
return resultList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(ApplicationEntity app) {
|
||||
ApplicationEntity attachedApp = em.find(ApplicationEntity.class, app.getId());
|
||||
em.remove(attachedApp);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Application {} deleted", app.getApplicationName());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,165 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.account.util.Permission;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.Query;
|
||||
import javax.transaction.Transactional;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Stateless
|
||||
public class ApplicationPermissionControl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3761100587901739481L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationPermissionControl.class);
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
public List<ApplicationPermissionEntity> getApplicationPermissions(ApplicationEntity app) {
|
||||
if (application == null) {
|
||||
return Collections.EMPTY_LIST;
|
||||
}
|
||||
Query query = em.createNamedQuery("ApplicationPermissionEntity.findAll");
|
||||
query.setParameter("application", app);
|
||||
List<ApplicationPermissionEntity> permissionList = query.getResultList();
|
||||
if (permissionList == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return permissionList;
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity findPermissionByName(ApplicationEntity application, String permissionName) {
|
||||
Query query = em.createNamedQuery("ApplicationPermissionEntity.findByPermissionName");
|
||||
query.setParameter("application", application);
|
||||
query.setParameter("permissionName", permissionName);
|
||||
List<ApplicationPermissionEntity> resultList = query.getResultList();
|
||||
if ((resultList == null) || (resultList.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
return resultList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void create(ApplicationEntity application, String name, String description) {
|
||||
ApplicationPermissionEntity permission = new ApplicationPermissionEntity(application, name, description);
|
||||
em.persist(permission);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void update(ApplicationPermissionEntity permission) throws AccountException {
|
||||
ApplicationPermissionEntity existing = attach(permission);
|
||||
em.merge(existing);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void createOrUpdate(ApplicationEntity application, String name, String description) {
|
||||
ApplicationPermissionEntity permission = findByName(application, name);
|
||||
if (permission == null) {
|
||||
permission = new ApplicationPermissionEntity(name, description);
|
||||
em.persist(permission);
|
||||
} else {
|
||||
permission.setPermissionDescription(description);
|
||||
em.merge(permission);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(ApplicationPermissionEntity permission) throws AccountException {
|
||||
ApplicationPermissionEntity existingPermission = attach(permission);
|
||||
em.remove(existingPermission);
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity attach(ApplicationPermissionEntity permission) throws AccountException {
|
||||
try {
|
||||
return em.merge(permission);
|
||||
} catch (OptimisticLockException ex) {
|
||||
throw new AccountException("Entity updated / deleted, please reload", true);
|
||||
}
|
||||
}
|
||||
|
||||
private ApplicationPermissionEntity findByName(ApplicationEntity application, String name) {
|
||||
Query query = em.createNamedQuery("ApplicationPermissionEntity.findByPermissionName");
|
||||
query.setParameter("application", application);
|
||||
query.setParameter("permissionName", name);
|
||||
List<ApplicationPermissionEntity> permissions = query.getResultList();
|
||||
if ((permissions == null) || (permissions.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
return permissions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setupPermissions(List<Permission> permissions) {
|
||||
if (application == null) {
|
||||
LOGGER.error("Application not initialized, cannot setup permissions");
|
||||
} else {
|
||||
for (Permission permission : permissions) {
|
||||
ApplicationPermissionEntity existingPermission = findByName(application, permission.getName());
|
||||
if (existingPermission == null) {
|
||||
// permission not available, create it
|
||||
LOGGER.info("missing permission {} of {}", permission.getName(), application.getApplicationName());
|
||||
existingPermission = new ApplicationPermissionEntity(permission.getName(), permission.getDescription());
|
||||
existingPermission.setApplication(application);
|
||||
em.persist(existingPermission);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("missing permission {} added to {}", permission.getName(), application.getApplicationName());
|
||||
}
|
||||
} else {
|
||||
if (existingPermission.getPermissionDescription().equals(permission.getDescription())) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Permission {} for {} already exists, skipping", permission.getName(), application.getApplicationName());
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("description of permssion {} for {} differs, resetting to orignal value {}", permission.getName(), application.getApplicationName(), permission.getDescription());
|
||||
}
|
||||
|
||||
existingPermission.setPermissionDescription(permission.getDescription());
|
||||
em.merge(existingPermission);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("updated permission description {} for {}", permission.getName(), application.getApplicationName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,209 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountException;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationPermissionEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationRoleEntity;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.account.util.Permission;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.ejb.EJB;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.OptimisticLockException;
|
||||
import javax.persistence.Query;
|
||||
import javax.transaction.Transactional;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Stateless
|
||||
public class ApplicationRoleControl implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 5962478269550134748L;
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationRoleControl.class);
|
||||
|
||||
@EJB
|
||||
ApplicationPermissionControl applicationPermissionControl;
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public List<ApplicationRoleEntity> getAllRoles(ApplicationEntity app) {
|
||||
Query query = em.createNamedQuery("ApplicationRoleEntity.findAll");
|
||||
query.setParameter("application", app);
|
||||
|
||||
List<ApplicationRoleEntity> roles = query.getResultList();
|
||||
if (roles == null) {
|
||||
return new ArrayList<>();
|
||||
} else {
|
||||
return roles;
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void createOrUpdate(ApplicationEntity app, String name, String description) {
|
||||
ApplicationRoleEntity role = findByName(app, name);
|
||||
if (role == null) {
|
||||
role = new ApplicationRoleEntity(app, name, description);
|
||||
em.persist(role);
|
||||
} else {
|
||||
role.setRoleDescription(description);
|
||||
em.merge(role);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void create(ApplicationRoleEntity role) {
|
||||
em.persist(role);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void update(ApplicationRoleEntity role) {
|
||||
em.merge(role);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void delete(ApplicationRoleEntity role) throws AccountException {
|
||||
ApplicationRoleEntity existingRole = attach(role);
|
||||
em.remove(existingRole);
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity attach(ApplicationRoleEntity role) throws AccountException {
|
||||
try {
|
||||
return em.merge(role);
|
||||
} catch (OptimisticLockException ex) {
|
||||
throw new AccountException("Entity updated / deleted, please reload", true);
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity findByName(String name) {
|
||||
return findByName(application, name);
|
||||
}
|
||||
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public ApplicationRoleEntity findByName(ApplicationEntity app, String name) {
|
||||
Query query = em.createNamedQuery("ApplicationRoleEntity.findByRoleName");
|
||||
query.setParameter("application", app);
|
||||
query.setParameter("roleName", name);
|
||||
List<ApplicationRoleEntity> permissions = query.getResultList();
|
||||
if ((permissions == null) || (permissions.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
return permissions.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
public List<ApplicationPermissionEntity> getRolePermissions(ApplicationRoleEntity role) throws AccountException {
|
||||
ApplicationRoleEntity existingRole = em.find(ApplicationRoleEntity.class, role.getId());
|
||||
List<ApplicationPermissionEntity> permissions = existingRole.getApplicationPermissionList();
|
||||
if ((permissions != null) && (permissions.isEmpty())) {
|
||||
permissions.size(); // force list to load
|
||||
}
|
||||
|
||||
return permissions;
|
||||
}
|
||||
|
||||
public List<ApplicationPermissionEntity> getNotAssignedApplicationPermissions(ApplicationRoleEntity role) {
|
||||
try {
|
||||
List<ApplicationPermissionEntity> rolePermissions = getRolePermissions(role);
|
||||
List<ApplicationPermissionEntity> allPermssions = applicationPermissionControl.getApplicationPermissions(role.getApplication());
|
||||
|
||||
List<ApplicationPermissionEntity> missingPermissions = new ArrayList<>();
|
||||
allPermssions.stream().filter((perm) -> (!rolePermissions.contains(perm))).forEachOrdered((perm) -> {
|
||||
missingPermissions.add(perm);
|
||||
});
|
||||
return missingPermissions;
|
||||
} catch (AccountException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.debug(ex.toString());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void addPermission(ApplicationRoleEntity role, ApplicationPermissionEntity permission) throws AccountException {
|
||||
ApplicationRoleEntity existingRole = attach(role);
|
||||
if (existingRole.getApplicationPermissionList() == null) {
|
||||
existingRole.setApplicationPermissionList(new ArrayList<>());
|
||||
}
|
||||
existingRole.getApplicationPermissionList().add(permission);
|
||||
em.merge(role);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
// TODO requires special role to maintain role for other allication
|
||||
public void removePermission(ApplicationRoleEntity role, ApplicationPermissionEntity permission) throws AccountException {
|
||||
ApplicationRoleEntity existingRole = attach(role);
|
||||
if ((existingRole.getApplicationPermissionList() != null) && (existingRole.getApplicationPermissionList().contains(permission))) {
|
||||
existingRole.getApplicationPermissionList().remove(permission);
|
||||
}
|
||||
em.merge(role);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void setupRolePermission(List<Permission> permissions, String roleName) throws AccountException {
|
||||
ApplicationRoleEntity role = findByName(application, roleName);
|
||||
if (role == null) {
|
||||
LOGGER.error("A role with name " + roleName + " is not defined for application " + application.getApplicationName());
|
||||
} else {
|
||||
for (Permission permission : permissions) {
|
||||
ApplicationPermissionEntity existingPermission = applicationPermissionControl.findPermissionByName(application, permission.getName());
|
||||
if (existingPermission == null) {
|
||||
LOGGER.error("Required permission " + permission.getName() + " of application " + application.getApplicationName() + " does not exist. Ensure to call setupPermissions first");
|
||||
} else {
|
||||
if (role.getApplicationPermissionList().contains(existingPermission)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Permission {} already assigned to role {} of {}, skipping", permission.getName(), roleName, application.getApplicationName());
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Permission {} not assigned to role {} of {}", permission.getName(), roleName, application.getApplicationName());
|
||||
}
|
||||
addPermission(role, existingPermission);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Added permission {} to role {} of {}", permission.getName(), roleName, application.getApplicationName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,155 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "application")
|
||||
@XmlRootElement
|
||||
@Cacheable
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ApplicationEntity.findAll", query = "SELECT a FROM ApplicationEntity a",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationEntity.findByApplicationName", query = "SELECT a FROM ApplicationEntity a WHERE a.applicationName = :applicationName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")})
|
||||
})
|
||||
|
||||
public class ApplicationEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -6407525020014743727L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "application_name", unique = true)
|
||||
private String applicationName;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "application")
|
||||
private List<ApplicationRoleEntity> applicationRoleEntityList;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "application")
|
||||
private List<ApplicationPermissionEntity> applicationPermissions;
|
||||
@OneToMany(cascade = CascadeType.ALL, mappedBy = "application")
|
||||
private List<ConfigEntity> configEntityList;
|
||||
|
||||
public ApplicationEntity() {
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getApplicationName() {
|
||||
return applicationName;
|
||||
}
|
||||
|
||||
public void setApplicationName(String applicationName) {
|
||||
this.applicationName = applicationName;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<ApplicationRoleEntity> getApplicationRoleEntityList() {
|
||||
return applicationRoleEntityList;
|
||||
}
|
||||
|
||||
public void setApplicationRoleEntityList(List<ApplicationRoleEntity> applicationRoleEntityList) {
|
||||
this.applicationRoleEntityList = applicationRoleEntityList;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<ApplicationPermissionEntity> getApplicationPermissions() {
|
||||
return applicationPermissions;
|
||||
}
|
||||
|
||||
public void setApplicationPermissions(List<ApplicationPermissionEntity> applicationPermissions) {
|
||||
this.applicationPermissions = applicationPermissions;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<ConfigEntity> getConfigEntityList() {
|
||||
return configEntityList;
|
||||
}
|
||||
|
||||
public void setConfigEntityList(List<ConfigEntity> configEntityList) {
|
||||
this.configEntityList = configEntityList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ApplicationEntity)) {
|
||||
return false;
|
||||
}
|
||||
ApplicationEntity other = (ApplicationEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.business.application.entity.ApplicationEntity[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,188 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "application_permission")
|
||||
@XmlRootElement
|
||||
@Cacheable
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ApplicationPermissionEntity.findAll", query = "SELECT a FROM ApplicationPermissionEntity a WHERE a.application=:application order by a.permissionName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationPermissionEntity.findNotAssigned", query = "SELECT a FROM ApplicationPermissionEntity a LEFT OUTER JOIN a.applicationRoles r WHERE a.application=:application AND r NOT IN :permissions",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationPermissionEntity.findByPermissionName", query = "SELECT a FROM ApplicationPermissionEntity a WHERE a.application=:application AND a.permissionName = :permissionName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationPermissionEntity.findByPermissionDescription", query = "SELECT a FROM ApplicationPermissionEntity a WHERE a.application=:application AND a.permissionDescription = :permissionDescription",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")})
|
||||
})
|
||||
public class ApplicationPermissionEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8985982754544829534L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 80)
|
||||
@Column(name = "permission_name")
|
||||
private String permissionName;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "permission_description")
|
||||
private String permissionDescription;
|
||||
@JoinColumn(name = "application", referencedColumnName = "id")
|
||||
@ManyToOne(optional = false)
|
||||
private ApplicationEntity application;
|
||||
@ManyToMany(mappedBy = "applicationPermissionList")
|
||||
private List<ApplicationRoleEntity> applicationRoles;
|
||||
|
||||
public ApplicationPermissionEntity() {
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity(String permissionName, String permissionDescription) {
|
||||
this.id = null;
|
||||
this.permissionName = permissionName;
|
||||
this.permissionDescription = permissionDescription;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity(ApplicationEntity application, String permissionName, String permissionDescription) {
|
||||
this.id = null;
|
||||
this.application = application;
|
||||
this.permissionName = permissionName;
|
||||
this.permissionDescription = permissionDescription;
|
||||
}
|
||||
|
||||
public ApplicationPermissionEntity(UUID id, ApplicationEntity application, String permissionName, String permissionDescription) {
|
||||
this.id = id;
|
||||
this.application = application;
|
||||
this.permissionName = permissionName;
|
||||
this.permissionDescription = permissionDescription;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getPermissionName() {
|
||||
return permissionName;
|
||||
}
|
||||
|
||||
public void setPermissionName(String permissionName) {
|
||||
this.permissionName = permissionName;
|
||||
}
|
||||
|
||||
public String getPermissionDescription() {
|
||||
return permissionDescription;
|
||||
}
|
||||
|
||||
public void setPermissionDescription(String permissionDescription) {
|
||||
this.permissionDescription = permissionDescription;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<ApplicationRoleEntity> getApplicationRoles() {
|
||||
return applicationRoles;
|
||||
}
|
||||
|
||||
public void setApplicationRoles(List<ApplicationRoleEntity> applicationRoles) {
|
||||
this.applicationRoles = applicationRoles;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ApplicationPermissionEntity)) {
|
||||
return false;
|
||||
}
|
||||
ApplicationPermissionEntity other = (ApplicationPermissionEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.entity.ApplicationPermission[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public void setApplication(ApplicationEntity application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,198 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.application.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
import org.hibernate.annotations.GenericGenerator;
|
||||
import org.hibernate.annotations.Type;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "application_role")
|
||||
@Cacheable
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ApplicationRoleEntity.findAll", query = "SELECT a FROM ApplicationRoleEntity a WHERE a.application = :application ORDER BY a.roleName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationRoleEntity.findByRoleName", query = "SELECT a FROM ApplicationRoleEntity a WHERE a.application = :application AND a.roleName = :roleName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ApplicationRoleEntity.findByRoleDescription", query = "SELECT a FROM ApplicationRoleEntity a WHERE a.application = :application AND a.roleDescription = :roleDescription",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")})
|
||||
})
|
||||
|
||||
public class ApplicationRoleEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -8324054525780893823L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Column(name = "id")
|
||||
@GeneratedValue(generator = "uuid2")
|
||||
@GenericGenerator(name = "uuid2", strategy = "uuid2")
|
||||
@Type(type = "pg-uuid")
|
||||
private UUID id;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 80)
|
||||
@Column(name = "role_name")
|
||||
private String roleName;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 200)
|
||||
@Column(name = "role_description")
|
||||
private String roleDescription;
|
||||
@ManyToMany(mappedBy = "applicationRoleList")
|
||||
private List<AccountEntity> accountList;
|
||||
@JoinTable(name = "role_permission", joinColumns = {
|
||||
@JoinColumn(name = "application_role", referencedColumnName = "id")}, inverseJoinColumns = {
|
||||
@JoinColumn(name = "role_permission", referencedColumnName = "id")})
|
||||
@ManyToMany
|
||||
private List<ApplicationPermissionEntity> applicationPermissionList;
|
||||
@JoinColumn(name = "application", referencedColumnName = "id")
|
||||
@ManyToOne(optional = false)
|
||||
private ApplicationEntity application;
|
||||
|
||||
public ApplicationRoleEntity() {
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity(ApplicationEntity application) {
|
||||
this.id = null;
|
||||
this.application = application;
|
||||
this.roleName = "";
|
||||
this.roleDescription = "";
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity(ApplicationEntity application, String roleName, String roleDescription) {
|
||||
this.id = null;
|
||||
this.application = application;
|
||||
this.roleName = roleName;
|
||||
this.roleDescription = roleDescription;
|
||||
}
|
||||
|
||||
public ApplicationRoleEntity(UUID id, ApplicationEntity application, String roleName, String roleDescription) {
|
||||
this.id = id;
|
||||
this.application = application;
|
||||
this.roleName = roleName;
|
||||
this.roleDescription = roleDescription;
|
||||
}
|
||||
|
||||
public UUID getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(UUID id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getRoleName() {
|
||||
return roleName;
|
||||
}
|
||||
|
||||
public void setRoleName(String roleName) {
|
||||
this.roleName = roleName;
|
||||
}
|
||||
|
||||
public String getRoleDescription() {
|
||||
return roleDescription;
|
||||
}
|
||||
|
||||
public void setRoleDescription(String roleDescription) {
|
||||
this.roleDescription = roleDescription;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<AccountEntity> getAccountList() {
|
||||
return accountList;
|
||||
}
|
||||
|
||||
public void setAccountList(List<AccountEntity> accountList) {
|
||||
this.accountList = accountList;
|
||||
}
|
||||
|
||||
@XmlTransient
|
||||
public List<ApplicationPermissionEntity> getApplicationPermissionList() {
|
||||
return applicationPermissionList;
|
||||
}
|
||||
|
||||
public void setApplicationPermissionList(List<ApplicationPermissionEntity> applicationPermissionList) {
|
||||
this.applicationPermissionList = applicationPermissionList;
|
||||
}
|
||||
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public void setApplication(ApplicationEntity application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (id != null ? id.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ApplicationRoleEntity)) {
|
||||
return false;
|
||||
}
|
||||
ApplicationRoleEntity other = (ApplicationRoleEntity) object;
|
||||
if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.entity.ApplicationRole[ id=" + id + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,277 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntity;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigEntityPK;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import java.io.Serializable;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import javax.ejb.Lock;
|
||||
import javax.ejb.LockType;
|
||||
import javax.ejb.Singleton;
|
||||
import javax.ejb.Startup;
|
||||
import javax.ejb.TransactionAttribute;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import static javax.ejb.TransactionAttributeType.REQUIRES_NEW;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import javax.transaction.Transactional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Singleton
|
||||
@Startup
|
||||
public class ConfigService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3195224653632853003L;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ConfigService.class);
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
/**
|
||||
* returns global config key which is not assigned to any. If more than one value is defined for the given key, the
|
||||
* key assigned to system is returned. If more than one key is defined but system key is not defined, an exception
|
||||
* is thrown.
|
||||
*
|
||||
* @param configKey the key to return
|
||||
* @return the configValue belonging to the given configKey
|
||||
* @throws de.muehlencord.shared.account.business.config.entity.ConfigException if more than one value is defined
|
||||
* for the given key but none of the values is defined for the system user
|
||||
*/
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String getConfigValue(String configKey) throws ConfigException {
|
||||
Query query = em.createNamedQuery("ConfigEntity.findByConfigKey");
|
||||
query.setParameter("application", application);
|
||||
query.setParameter("configKey", configKey);
|
||||
List<ConfigEntity> configList = query.getResultList();
|
||||
if ((configList == null) || (configList.isEmpty())) {
|
||||
// key is not found in the database at all
|
||||
return null;
|
||||
} else if (configList.size() == 1) {
|
||||
// exact one element found, return this one
|
||||
return configList.get(0).getConfigValue();
|
||||
} else {
|
||||
// if more than one result found, return the one which is assigned to system if present
|
||||
// if not present, throw exception
|
||||
Optional<ConfigEntity> firstItem = configList.stream()
|
||||
.filter(config -> config.getConfigPK().getConfigKeyAccount().getUsername().equals("system"))
|
||||
.findFirst();
|
||||
if (firstItem.isPresent()) {
|
||||
return firstItem.get().getConfigValue();
|
||||
} else {
|
||||
throw new ConfigException("ConfigKey " + configKey + " not unique and system value not defined");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO replace with DAO?
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public List<ConfigEntity> getApplicationConfigItems() {
|
||||
Query query = em.createNamedQuery("ConfigEntity.findByApplication");
|
||||
query.setParameter("application", application);
|
||||
List<ConfigEntity> configList = query.getResultList();
|
||||
return configList;
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String getConfigValue(String configKey, String defaultValue) throws ConfigException, ControllerException {
|
||||
return getConfigValue(configKey, defaultValue, false);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@TransactionAttribute(REQUIRES_NEW)
|
||||
public String getConfigValue(String configKey, String defaultValue, boolean storeDefaultValue) throws ConfigException, ControllerException {
|
||||
// get configValue as usual
|
||||
String configValue = getConfigValue(configKey);
|
||||
|
||||
// if config value is not found null has been returned
|
||||
// in this case the value to return is the defaultValue
|
||||
if (StringUtils.isEmpty(configValue)) {
|
||||
configValue = defaultValue;
|
||||
}
|
||||
|
||||
// check if the default value should be stored in the database
|
||||
if (storeDefaultValue) {
|
||||
AccountEntity account = getAccount("system");
|
||||
updateConfigValue(configKey, account, configValue);
|
||||
}
|
||||
|
||||
return configValue;
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String getConfigValue(String configKey, String defaultValue, String accountName, boolean fallbackToSystem) throws ConfigException {
|
||||
Account account = getAccount(accountName);
|
||||
if (account == null) {
|
||||
if (fallbackToSystem) {
|
||||
return getConfigValue (configKey);
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
} else {
|
||||
return getConfigValue (configKey, account, fallbackToSystem);
|
||||
}
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String getConfigValue(String configKey, Account account, boolean fallbackToSystem) throws ConfigException {
|
||||
Query query = em.createNamedQuery("ConfigEntity.findByConfigKeyAndAccount");
|
||||
query.setParameter("application", application);
|
||||
query.setParameter("configKey", configKey);
|
||||
query.setParameter("account", account);
|
||||
List<ConfigEntity> configList = query.getResultList();
|
||||
if ((configList == null) || (configList.isEmpty())) {
|
||||
// fallback to default / system value
|
||||
if (fallbackToSystem) {
|
||||
return getConfigValue(configKey);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (configList.size() == 1) {
|
||||
// exact one element found, return this one
|
||||
return configList.get(0).getConfigValue();
|
||||
} else {
|
||||
// more than one value must not happen - this is not possible per the defintion of the datamodel
|
||||
throw new ConfigException("Cannot have more than one value for the the given key " + configKey + " and the given account " + account.getUsername());
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@TransactionAttribute(REQUIRES_NEW)
|
||||
public String getConfigValue(String configKey, String defaultValue, boolean storeDefaultValue, Account account, boolean fallbackToSystem) throws ConfigException, ControllerException {
|
||||
String configValue = getConfigValue(configKey, account, fallbackToSystem);
|
||||
|
||||
if (configValue == null) {
|
||||
// value not found for given account and if allowed also not found for system user
|
||||
configValue = defaultValue;
|
||||
}
|
||||
|
||||
// check if the default value should be stored in the database
|
||||
if (storeDefaultValue) {
|
||||
updateConfigValue(configKey, account, configValue);
|
||||
}
|
||||
|
||||
return configValue;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@TransactionAttribute(REQUIRES_NEW)
|
||||
public boolean updateConfigValue(String configKey, String configValue) throws ConfigException, ControllerException {
|
||||
Account account = getAccount("system");
|
||||
return updateConfigValue(configKey, account, configValue);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@TransactionAttribute(REQUIRES_NEW)
|
||||
public boolean updateConfigValue(String configKey, String accountName, String configValue) throws ControllerException {
|
||||
Account account = getAccount(accountName);
|
||||
if (accountName == null) {
|
||||
return false;
|
||||
}
|
||||
if (account == null) {
|
||||
LOGGER.error("Account for userName {} not found", accountName);
|
||||
return false;
|
||||
}
|
||||
return updateConfigValue(configKey, account, configValue);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
@TransactionAttribute(REQUIRES_NEW)
|
||||
public boolean updateConfigValue(String configKey, Account account, String configValue) throws ControllerException {
|
||||
if ((configKey == null) || (configKey.equals(""))) {
|
||||
// null or empty key
|
||||
return false;
|
||||
}
|
||||
|
||||
if (account == null) {
|
||||
throw new ControllerException(ControllerException.CAUSE_CANNOT_PERSIST, "Account must not be null, not updating");
|
||||
}
|
||||
|
||||
AccountEntity accountEntity = getAccount(account.getUsername());
|
||||
ConfigEntityPK pk = new ConfigEntityPK(application, configKey, accountEntity);
|
||||
ConfigEntity currentEntity = em.find(ConfigEntity.class, pk);
|
||||
if (currentEntity == null) {
|
||||
currentEntity = new ConfigEntity(pk);
|
||||
currentEntity.setConfigValue(configValue);
|
||||
em.persist(currentEntity);
|
||||
return true; // config item created - udpate performed
|
||||
} else {
|
||||
if ((currentEntity.getConfigValue() != null) && (currentEntity.getConfigValue().equals(configValue))) {
|
||||
// value is the same - no update
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("configValue {} not changed, keeping {}", configKey, currentEntity.getConfigValue());
|
||||
}
|
||||
|
||||
return false;
|
||||
} else {
|
||||
String oldValue = currentEntity.getConfigValue();
|
||||
currentEntity.setConfigValue(configValue);
|
||||
em.merge(currentEntity);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("configValue for {} updated from {} to {}", configKey, oldValue, configValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AccountEntity getAccount(String accountName) {
|
||||
Query query = em.createNamedQuery("AccountEntity.findByUsername");
|
||||
query.setParameter("username", accountName);
|
||||
List<AccountEntity> accountList = query.getResultList();
|
||||
if ((accountList == null) || (accountList.isEmpty())) {
|
||||
return null;
|
||||
} else {
|
||||
return accountList.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
||||
@Transactional
|
||||
@Lock(LockType.WRITE)
|
||||
public void delete(ConfigEntity config) throws ControllerException {
|
||||
em.remove(em.merge(config));
|
||||
}
|
||||
}
|
||||
@ -1,62 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationKey;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountConfigurationValue;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.Dependent;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.enterprise.inject.spi.Annotated;
|
||||
import javax.enterprise.inject.spi.InjectionPoint;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Dependent
|
||||
public class ConfigurationProducer {
|
||||
|
||||
@EJB
|
||||
ConfigService configService;
|
||||
|
||||
@Produces
|
||||
@AccountConfigurationValue(key = AccountConfigurationKey.Producer)
|
||||
public String produceConfigurationValue(InjectionPoint injectionPoint) {
|
||||
Annotated annotated = injectionPoint.getAnnotated();
|
||||
AccountConfigurationValue annotation = annotated.getAnnotation(AccountConfigurationValue.class);
|
||||
if (annotation != null) {
|
||||
AccountConfigurationKey key = annotation.key();
|
||||
if (key != null) {
|
||||
try {
|
||||
switch (key) {
|
||||
case BaseUrl:
|
||||
return configService.getConfigValue("base.url");
|
||||
case PasswordResetUrl:
|
||||
return configService.getConfigValue("base.url") + "/login.xhtml";
|
||||
default:
|
||||
throw new IllegalStateException("Invalid key " + key + " for injection point: " + injectionPoint);
|
||||
}
|
||||
} catch (ConfigException ex) {
|
||||
throw new IllegalStateException("Invalid key " + key + " for injection point: " + injectionPoint + ". Exception: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("No key for injection point: " + injectionPoint);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,163 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.EmbeddedId;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Entity
|
||||
@Table(name = "config")
|
||||
@XmlRootElement
|
||||
@Cacheable(true)
|
||||
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "Configuration")
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "ConfigEntity.findAll", query = "SELECT c FROM ConfigEntity c ORDER BY c.configPK.configKey",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ConfigEntity.findByApplication", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.application = :application",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ConfigEntity.findByConfigKey", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.application = :application AND c.configPK.configKey = :configKey",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ConfigEntity.findByConfigKeyAndAccount", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.application = :application AND c.configPK.configKey = :configKey AND c.configPK.configKeyAccount = :account",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "ConfigEntity.findByConfigValue", query = "SELECT c FROM ConfigEntity c WHERE c.configPK.application = :application AND c.configValue = :configValue",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")})
|
||||
})
|
||||
|
||||
public class ConfigEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -2013982316933782223L;
|
||||
|
||||
@EmbeddedId
|
||||
protected ConfigEntityPK configPK;
|
||||
@Size(max = 2000)
|
||||
@Column(name = "config_value")
|
||||
private String configValue;
|
||||
@Size(max = 200)
|
||||
@Column(name = "config_key_group")
|
||||
private String configKeyGroup;
|
||||
@JoinColumn(name = "config_key_account", referencedColumnName = "id", insertable = false, updatable = false)
|
||||
@ManyToOne(optional = false)
|
||||
private AccountEntity account;
|
||||
@JoinColumn(name = "application", referencedColumnName = "id", insertable = false, updatable = false)
|
||||
@ManyToOne(optional = false)
|
||||
private ApplicationEntity application;
|
||||
|
||||
public ConfigEntity() {
|
||||
}
|
||||
|
||||
public ConfigEntity(ApplicationEntity application, String configKey, AccountEntity account) {
|
||||
this.configPK = new ConfigEntityPK(application, configKey, account);
|
||||
}
|
||||
|
||||
public ConfigEntity(ConfigEntityPK configPK) {
|
||||
this.configPK = configPK;
|
||||
}
|
||||
|
||||
public ConfigEntityPK getConfigPK() {
|
||||
return configPK;
|
||||
}
|
||||
|
||||
public void setConfigPK(ConfigEntityPK configPK) {
|
||||
this.configPK = configPK;
|
||||
}
|
||||
|
||||
public String getConfigValue() {
|
||||
return configValue;
|
||||
}
|
||||
|
||||
public void setConfigValue(String configValue) {
|
||||
this.configValue = configValue;
|
||||
}
|
||||
|
||||
public String getConfigKeyGroup() {
|
||||
return configKeyGroup;
|
||||
}
|
||||
|
||||
public void setConfigKeyGroup(String configKeyGroup) {
|
||||
this.configKeyGroup = configKeyGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (configPK != null ? configPK.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ConfigEntity)) {
|
||||
return false;
|
||||
}
|
||||
ConfigEntity other = (ConfigEntity) object;
|
||||
if ((this.configPK == null && other.configPK != null) || (this.configPK != null && !this.configPK.equals(other.configPK))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.business.config.entity.Config[ configPK=" + configPK + " ]";
|
||||
}
|
||||
|
||||
public AccountEntity getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public void setAccount(AccountEntity account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public void setApplication(ApplicationEntity application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,113 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Embeddable;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Embeddable
|
||||
public class ConfigEntityPK implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 8133795368429249008L;
|
||||
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 100)
|
||||
@Column(name = "config_key")
|
||||
private String configKey;
|
||||
@JoinColumn(name = "config_key_account", referencedColumnName = "id", insertable = false, updatable = false)
|
||||
@ManyToOne(optional = false)
|
||||
private AccountEntity configKeyAccount;
|
||||
@JoinColumn(name = "application", referencedColumnName = "id", insertable = false, updatable = false)
|
||||
@ManyToOne(optional = false)
|
||||
private ApplicationEntity application;
|
||||
|
||||
public ConfigEntityPK() {
|
||||
// empty constructor required for JPA
|
||||
}
|
||||
|
||||
public ConfigEntityPK(ApplicationEntity application, String configKey, AccountEntity configKeyAccount) {
|
||||
this.application = application;
|
||||
this.configKey = configKey;
|
||||
this.configKeyAccount = configKeyAccount;
|
||||
}
|
||||
|
||||
public String getConfigKey() {
|
||||
return configKey;
|
||||
}
|
||||
|
||||
public void setConfigKey(String configKey) {
|
||||
this.configKey = configKey;
|
||||
}
|
||||
|
||||
public AccountEntity getConfigKeyAccount() {
|
||||
return configKeyAccount;
|
||||
}
|
||||
|
||||
public void setConfigKeyAccount(AccountEntity configKeyAccount) {
|
||||
this.configKeyAccount = configKeyAccount;
|
||||
}
|
||||
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
}
|
||||
|
||||
public void setApplication(ApplicationEntity application) {
|
||||
this.application = application;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (configKey != null ? configKey.hashCode() : 0);
|
||||
hash += (configKeyAccount != null ? configKeyAccount.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof ConfigEntityPK)) {
|
||||
return false;
|
||||
}
|
||||
ConfigEntityPK other = (ConfigEntityPK) object;
|
||||
if ((this.configKey == null && other.configKey != null) || (this.configKey != null && !this.configKey.equals(other.configKey))) {
|
||||
return false;
|
||||
}
|
||||
if ((this.configKeyAccount == null && other.configKeyAccount != null) || (this.configKeyAccount != null && !this.configKeyAccount.equals(other.configKeyAccount))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.business.config.entity.ConfigPK[ configKey=" + configKey + ", configKeyAccount=" + configKeyAccount + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,53 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.config.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public class ConfigException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 7246584814637280123L;
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>ConfigException</code> without detail
|
||||
* message.
|
||||
*/
|
||||
public ConfigException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>ConfigException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public ConfigException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>ConfigException</code> with the specified
|
||||
* detail message and root cause.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the root cause
|
||||
*/
|
||||
public ConfigException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.instance.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.util.Permission;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public enum ApplicationPermissions implements Permission {
|
||||
|
||||
APP_LIST("application:list", "Allows to list all avaiable applications"),
|
||||
APP_ADD("application:add", "Allow to add a new application"),
|
||||
APP_EDIT("application:edit", "Allow to edit an application"),
|
||||
APP_DELETE("application:delete", "Allow to delete an application"),
|
||||
PERMISSION_ADD("permission:add", "Allow to add a permission to an application"),
|
||||
PERMISSION_EDIT("permission:edit", "Allow to edit a permission"),
|
||||
PERMISSION_DELETE("permmission:delete", "Allow to delete a permission"),
|
||||
ROLE_ADD("role:add", "Allow to add a role to an application"),
|
||||
ROLE_EDIT("role:edit", "Allow to edit a role"),
|
||||
ROLE_DELETE("role:delete", "Allow to delete a role"),
|
||||
ROLE_PERMISSION_ASSIGN("role:permission:assign", "Allow to assign a permission to role"),
|
||||
ROLE_PERMISSION_REVOKE("role:permission:revoke", "All ow to revoke a permission from a role"),
|
||||
ACCOUNT_LIST ("account:list", "Allow to list all accounts of an application"),
|
||||
ACCOUNT_ADD ("account:add", "Allow to create a new account"),
|
||||
ACCOUNT_EDIT ("account:edit", "Allow to edit an existing account"),
|
||||
ACCOUNT_DELETE ("account:delete", "Allow to delete an existing account"),
|
||||
ACCOUNT_LOGIN_ADD ("account:login:add", "Allow to add a login to an account"),
|
||||
ACCOUNT_LOGIN_EDIT ("account:login:edit", "Allow to overwrite the password of an account"),
|
||||
ACCOUNT_LOGIN_DELETE ("account:login:delete", "Allow to delete the login of an account");
|
||||
|
||||
private final String name;
|
||||
private final String description;
|
||||
|
||||
private ApplicationPermissions(String permissionName, String permissionDesc) {
|
||||
this.name = permissionName;
|
||||
this.description = permissionDesc;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
}
|
||||
@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.instance.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.db.ControllerException;
|
||||
import javax.annotation.PreDestroy;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.context.Initialized;
|
||||
import javax.enterprise.event.Observes;
|
||||
import javax.inject.Inject;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@ApplicationScoped
|
||||
public class StartupBean {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StartupBean.class);
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
@Inject
|
||||
ApplicationEntity application;
|
||||
|
||||
public void init(@Observes @Initialized(ApplicationScoped.class) Object init) {
|
||||
if (application == null) {
|
||||
LOGGER.error("Application not initialized");
|
||||
throw new RuntimeException ("Application not initilized, validate applicationUID mapping");
|
||||
} else {
|
||||
try {
|
||||
LOGGER.info("Starting application {}", application.getApplicationName());
|
||||
String instanceName = configService.getConfigValue("base.instance", "Development System", true);
|
||||
LOGGER.info("instanceName={}", instanceName);
|
||||
|
||||
// ensure maxFailedLogins is available
|
||||
configService.getConfigValue("account.maxFailedLogins", "5", true);
|
||||
|
||||
LOGGER.info("Application startup complete");
|
||||
} catch (ConfigException | ControllerException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
public void shutdown() {
|
||||
LOGGER.info("Shutting down application {}", application.getApplicationName());
|
||||
|
||||
LOGGER.info("Application shutdown complete");
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.instance.control;
|
||||
|
||||
import de.muehlencord.shared.account.business.application.control.ApplicationControl;
|
||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Properties;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.ejb.EJB;
|
||||
import javax.enterprise.context.ApplicationScoped;
|
||||
import javax.enterprise.inject.Produces;
|
||||
import javax.inject.Named;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
@Named("applicationController")
|
||||
@ApplicationScoped
|
||||
public class ApplicationController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ApplicationController.class);
|
||||
|
||||
@EJB
|
||||
ApplicationControl applicationService;
|
||||
|
||||
private String version;
|
||||
private String buildDate;
|
||||
private UUID uuid;
|
||||
private ApplicationEntity application = null;
|
||||
|
||||
@PostConstruct
|
||||
public void readBuildInfoProperties() {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("Trying to read buildInfo.properties");
|
||||
}
|
||||
InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("buildInfo.properties");
|
||||
if (in == null) {
|
||||
return;
|
||||
}
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(in);
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("properties read from buildInfo.properties");
|
||||
}
|
||||
|
||||
version = props.getProperty("build.version");
|
||||
buildDate = props.getProperty("build.timestamp");
|
||||
String uuidString = props.getProperty("application.uuid");
|
||||
if (StringUtils.isEmpty(uuidString)) {
|
||||
throw new RuntimeException("ApplicationId not defined, please check database setup");
|
||||
} else {
|
||||
uuid = UUID.fromString(uuidString);
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("buildInfo.properties parsed successfully");
|
||||
}
|
||||
|
||||
} catch (IOException ex) {
|
||||
LOGGER.error("Cannot find buildInfo.properties. ", ex);
|
||||
version = "??";
|
||||
buildDate = "??";
|
||||
uuid = null;
|
||||
throw new RuntimeException("Application id not readable, application will not be able to run");
|
||||
}
|
||||
|
||||
if (uuid != null) {
|
||||
this.application = applicationService.findById(uuid);
|
||||
if (application == null) {
|
||||
throw new RuntimeException("ApplicationId " + uuid.toString() + " not readable, application will not be able to run. You need to setup application in account database first.");
|
||||
} else {
|
||||
LOGGER.info("Found application {} with id {}", application.getApplicationName(), uuid.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* needs to return link to "Account UI" and not to current selected application TODO: ensure only Account UI can
|
||||
* call functions where application can be handed in - all other applications need to call the function which use
|
||||
* the injected application
|
||||
*/
|
||||
@Produces
|
||||
public ApplicationEntity getApplication() {
|
||||
return application;
|
||||
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public String getBuildDate() {
|
||||
return buildDate;
|
||||
}
|
||||
|
||||
public UUID getApplicationId() {
|
||||
return uuid;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,235 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountLoginEntity;
|
||||
import de.muehlencord.shared.account.business.config.boundary.ConfigService;
|
||||
import de.muehlencord.shared.account.business.config.entity.ConfigException;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailDatamodel;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailException;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailTemplateException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import javax.annotation.Resource;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.inject.Inject;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.Multipart;
|
||||
import javax.mail.Session;
|
||||
import javax.mail.Transport;
|
||||
import javax.mail.internet.InternetAddress;
|
||||
import javax.mail.internet.MimeBodyPart;
|
||||
import javax.mail.internet.MimeMessage;
|
||||
import javax.mail.internet.MimeMultipart;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Stateless
|
||||
public class MailService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1937218474908356747L;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MailService.class);
|
||||
|
||||
@Inject
|
||||
private MailTemplateService mailTemplateService;
|
||||
|
||||
@Inject
|
||||
ConfigService configService;
|
||||
|
||||
// @Inject
|
||||
// @AccountConfigurationValue(key = AccountConfigurationKey.BaseUrl)
|
||||
// private String baseUrl;
|
||||
|
||||
// @Inject
|
||||
// @AccountConfigurationValue(key = AccountConfigurationKey.PasswordResetUrl)
|
||||
// private String passwordResetUrl;
|
||||
|
||||
// TODO make this configurable by injection from the application it uses it, fall back to defaul mail setup if not available
|
||||
@Resource(lookup = "java:jboss/mail/ssgMail")
|
||||
private Session mailSession;
|
||||
|
||||
public String sendTestEmail(String recipient) throws MailException {
|
||||
return sendMail(recipient, "Test email", "This is a test email");
|
||||
}
|
||||
|
||||
public String sendTestHtmlEmail(String recipient) throws MailException {
|
||||
Date now = new Date();
|
||||
AccountEntity account = new AccountEntity();
|
||||
account.setId(UUID.randomUUID());
|
||||
account.setFirstname("Jörn");
|
||||
account.setLastname("Mühlencord");
|
||||
AccountLoginEntity accountLogin = new AccountLoginEntity();
|
||||
accountLogin.setAccountPassword("secret");
|
||||
accountLogin.setAccount(account);
|
||||
account.setAccountLogin(accountLogin);
|
||||
MailDatamodel dataModel = new MailDatamodel(account);
|
||||
dataModel.addParameter("url", "http://url.de");
|
||||
dataModel.addParameter("resetUrl", "http://reseturl.de");
|
||||
return sendHTMLMail(recipient, "Test HTML Email", dataModel, "password_reset_html");
|
||||
}
|
||||
|
||||
public String sendMail(String recipient, String subject, String body) throws MailException {
|
||||
try {
|
||||
MimeMessage message = new MimeMessage(mailSession);
|
||||
message.setSubject(subject, "UTF-8");
|
||||
message.setFrom();
|
||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient, false));
|
||||
message.setText(body, "UTF-8");
|
||||
return transportMail(message);
|
||||
} catch (MessagingException ex) {
|
||||
throw new MailException("Error while sending email.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String sendHTMLMail(String recipient, String subject, MailDatamodel dataModel, String templateName) throws MailException {
|
||||
return sendHTMLMail(recipient, subject, dataModel, templateName, null);
|
||||
}
|
||||
|
||||
public String sendHTMLMail(String recipient, String subject, MailDatamodel dataModel, String htmlTemplateName, String plainTemplateName) throws MailException {
|
||||
return sendHTMLMail(recipient, null, null, subject, dataModel, htmlTemplateName, plainTemplateName, "UTF-8", new ArrayList<>());
|
||||
}
|
||||
|
||||
public String sendHTMLMail(String recipient, String ccRecipient, String bccRecipient, String subject, MailDatamodel dataModel, String htmlTemplateName, String plainTemplateName) throws MailException {
|
||||
return sendHTMLMail(recipient, ccRecipient, bccRecipient, subject, dataModel, htmlTemplateName, plainTemplateName, "UTF-8", new ArrayList<>());
|
||||
}
|
||||
|
||||
public String sendHTMLMail(String recipient, String ccRecipient, String bccRecipient, String subject,
|
||||
MailDatamodel dataModel, String htmlTemplateName, String plainTemplateName, String encoding, List<File> attachments) throws MailException {
|
||||
|
||||
try {
|
||||
String htmlBody = mailTemplateService.getStringFromTemplate(htmlTemplateName, dataModel);
|
||||
String plainBody;
|
||||
if (plainTemplateName != null) {
|
||||
plainBody = mailTemplateService.getStringFromTemplate(plainTemplateName, dataModel);
|
||||
} else {
|
||||
plainBody = null;
|
||||
}
|
||||
return sendHTMLMail(recipient, ccRecipient, bccRecipient, subject, htmlBody, plainBody, encoding, attachments);
|
||||
} catch (MailTemplateException ex) {
|
||||
throw new MailException("Error while sending email.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String sendHTMLMail(String recipient, String ccRecipient, String bccRecipient, String subject, String htmlBody, String plainBody, String encoding, List<File> attachments) throws MailException {
|
||||
try {
|
||||
MimeMessage message = new MimeMessage(mailSession);
|
||||
message.setFrom(); // use default from
|
||||
message.setRecipients(Message.RecipientType.TO, InternetAddress.parse(recipient, false));
|
||||
if (ccRecipient != null) {
|
||||
message.setRecipients(Message.RecipientType.CC, InternetAddress.parse(ccRecipient, false));
|
||||
}
|
||||
if (bccRecipient != null) {
|
||||
message.setRecipients(Message.RecipientType.BCC, InternetAddress.parse(bccRecipient, false));
|
||||
}
|
||||
|
||||
message.setSubject(subject, encoding);
|
||||
|
||||
Multipart contentMultiPart = new MimeMultipart("alternative");
|
||||
|
||||
MimeBodyPart htmlBodyPart = new MimeBodyPart();
|
||||
htmlBodyPart.setContent(htmlBody, "text/html; charset=UTF-8");
|
||||
contentMultiPart.addBodyPart(htmlBodyPart);
|
||||
|
||||
if (plainBody != null) {
|
||||
MimeBodyPart plainBodyPart = new MimeBodyPart();
|
||||
plainBodyPart.setText(plainBody, "UTF-8");
|
||||
contentMultiPart.addBodyPart(plainBodyPart);
|
||||
}
|
||||
|
||||
if ((attachments == null) || (attachments.isEmpty())) {
|
||||
message.setContent(contentMultiPart);
|
||||
} else {
|
||||
MimeBodyPart contentBodyPart = new MimeBodyPart();
|
||||
contentBodyPart.setContent(contentMultiPart);
|
||||
|
||||
MimeMultipart messageMultipart = new MimeMultipart("related");
|
||||
messageMultipart.addBodyPart(contentBodyPart);
|
||||
for (File attachment : attachments) {
|
||||
try {
|
||||
MimeBodyPart attachmentBodyPart = new MimeBodyPart();
|
||||
attachmentBodyPart.attachFile(attachment);
|
||||
String contentType = Files.probeContentType(attachment.toPath());
|
||||
if (contentType != null) {
|
||||
attachmentBodyPart.setHeader("Content-Type", contentType);
|
||||
}
|
||||
messageMultipart.addBodyPart(attachmentBodyPart);
|
||||
} catch (IOException ex) {
|
||||
throw new MailException("Cannot attach " + attachment.toString() + " to email. Reason: " + ex.toString(), ex);
|
||||
}
|
||||
}
|
||||
message.setContent(messageMultipart);
|
||||
}
|
||||
return transportMail(message);
|
||||
} catch (MessagingException ex) {
|
||||
throw new MailException("Error while sending email.", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public String sendPasswortResetStartEmail(AccountEntity account, String token) throws MailException, ConfigException {
|
||||
MailDatamodel model = new MailDatamodel(account);
|
||||
|
||||
/* old aproach via FacesContext - add this back as fallback if injection point if not configured
|
||||
try {
|
||||
// String absoluteWebPath = FacesContext.getCurrentInstance().getExternalContext().getApplicationContextPath();
|
||||
ExternalContext externalContext = FacesContext.getCurrentInstance().getExternalContext();
|
||||
String resetPage = "/login.xhtml?token=" + token;
|
||||
URL baseUrl;
|
||||
|
||||
// TODO move out of this class, this is not mandatorily connected to a form
|
||||
baseUrl = new URL(externalContext.getRequestScheme(),
|
||||
externalContext.getRequestServerName(),
|
||||
externalContext.getRequestServerPort(),
|
||||
externalContext.getRequestContextPath());
|
||||
model.addParameter("url", baseUrl.toString());
|
||||
model.addParameter("resetUrl", baseUrl.toString() + resetPage);
|
||||
} catch (MalformedURLException ex) {
|
||||
throw new MailException("Error while sending email.", ex);
|
||||
}
|
||||
|
||||
String resetUrlWithToken = baseUrl + "/login.xhtml?token=" + token;
|
||||
*/
|
||||
|
||||
String passwordResetUrl = configService.getConfigValue("backend.passwordreset.url");
|
||||
String baseUrl = configService.getConfigValue("backend.base.url");
|
||||
String resetUrlWithToken = passwordResetUrl + "?token=" + token;
|
||||
|
||||
model.addParameter("url", baseUrl);
|
||||
model.addParameter("resetUrl", resetUrlWithToken);
|
||||
return sendHTMLMail(account.getEmailaddress(), "Reset your password", model, "password_reset_html");
|
||||
}
|
||||
|
||||
private String transportMail(Message message) throws MessagingException {
|
||||
message.setSentDate(new Date());
|
||||
Transport.send(message);
|
||||
String messageId = message.getHeader("Message-ID")[0];
|
||||
LOGGER.info("Mail sent to {}, messageid = {}", message.getAllRecipients()[0].toString(), messageId);
|
||||
return messageId;
|
||||
|
||||
}
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.boundary;
|
||||
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailDatamodel;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailTemplateEntity;
|
||||
import de.muehlencord.shared.account.business.mail.entity.MailTemplateException;
|
||||
import de.muehlencord.shared.account.util.AccountPU;
|
||||
import freemarker.cache.StringTemplateLoader;
|
||||
import freemarker.template.Configuration;
|
||||
import freemarker.template.Template;
|
||||
import freemarker.template.TemplateException;
|
||||
import freemarker.template.TemplateExceptionHandler;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
import javax.ejb.Lock;
|
||||
import javax.ejb.LockType;
|
||||
import javax.ejb.Stateless;
|
||||
import javax.ejb.TransactionAttribute;
|
||||
import javax.ejb.TransactionAttributeType;
|
||||
import javax.inject.Inject;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.Query;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
@Stateless
|
||||
public class MailTemplateService implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -136113381443058697L;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(MailTemplateService.class.getName());
|
||||
|
||||
@Inject
|
||||
@AccountPU
|
||||
EntityManager em;
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String getStringFromTemplate(String templateName, MailDatamodel dataModel) throws MailTemplateException {
|
||||
try {
|
||||
Query query = em.createNamedQuery("MailTemplateEntity.findByTemplateName");
|
||||
query.setParameter("templateName", templateName);
|
||||
MailTemplateEntity templateEntity = (MailTemplateEntity) query.getSingleResult();
|
||||
if (templateEntity == null) {
|
||||
LOGGER.error("Tempate with name " + templateName + " not found");
|
||||
return null;
|
||||
}
|
||||
return fillTemplate(templateName, templateEntity.getTemplateValue(), dataModel);
|
||||
} catch (MailTemplateException ex) {
|
||||
String hint = "Error while processing template with name " + templateName + ".";
|
||||
LOGGER.error(hint + " " + ex.toString());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(hint, ex);
|
||||
}
|
||||
throw new MailTemplateException(hint, ex);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Lock(LockType.READ)
|
||||
@TransactionAttribute(TransactionAttributeType.NOT_SUPPORTED)
|
||||
public String fillTemplate(String templateName, String templateString, MailDatamodel dataModel) throws MailTemplateException {
|
||||
try {
|
||||
Configuration configuration = new Configuration(Configuration.VERSION_2_3_23);
|
||||
configuration.setDefaultEncoding("UTF-8"); // FIXME - make encoding configurable
|
||||
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
|
||||
|
||||
StringTemplateLoader stringLoader = new StringTemplateLoader();
|
||||
stringLoader.putTemplate(templateName, templateString);
|
||||
configuration.setTemplateLoader(stringLoader);
|
||||
Template template = configuration.getTemplate(templateName);
|
||||
|
||||
Writer out = new StringWriter();
|
||||
template.process(dataModel, out);
|
||||
String resultString = out.toString();
|
||||
return resultString;
|
||||
} catch (TemplateException | IOException ex) {
|
||||
String hint = "Error while processing template with name " + templateName + ".";
|
||||
LOGGER.error(hint + " " + ex.toString());
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(hint, ex);
|
||||
}
|
||||
throw new MailTemplateException(hint, ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,55 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.entity;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
public class MailDatamodel {
|
||||
|
||||
private final AccountEntity account;
|
||||
private final Map<String,Object> parameter;
|
||||
|
||||
public MailDatamodel() {
|
||||
this.account = null;
|
||||
this.parameter = new HashMap<>();
|
||||
}
|
||||
|
||||
public MailDatamodel(AccountEntity account) {
|
||||
this.parameter = new HashMap<>();
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public void addParameter(String name, Object value) {
|
||||
this.parameter.put(name, value);
|
||||
}
|
||||
|
||||
|
||||
/* **** getter / setter **** */
|
||||
|
||||
public AccountEntity getAccount() {
|
||||
return account;
|
||||
}
|
||||
|
||||
public Map<String, Object> getParameter() {
|
||||
return parameter;
|
||||
}
|
||||
}
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Raimund
|
||||
*/
|
||||
public class MailException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>MailException</code> without detail
|
||||
* message.
|
||||
*/
|
||||
public MailException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>MailException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>MailException</code> with the specified
|
||||
* detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the root cause
|
||||
*/
|
||||
public MailException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
}
|
||||
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
import javax.persistence.Basic;
|
||||
import javax.persistence.Cacheable;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.NamedQueries;
|
||||
import javax.persistence.NamedQuery;
|
||||
import javax.persistence.QueryHint;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Size;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Entity
|
||||
@Cacheable
|
||||
@Table(name = "mail_template")
|
||||
@XmlRootElement
|
||||
@NamedQueries({
|
||||
@NamedQuery(name = "MailTemplateEntity.findAll", query = "SELECT m FROM MailTemplateEntity m",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "MailTemplateEntity.findByTemplateName", query = "SELECT m FROM MailTemplateEntity m WHERE m.templateName = :templateName",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")}),
|
||||
@NamedQuery(name = "MailTemplateEntity.findByTemplateValue", query = "SELECT m FROM MailTemplateEntity m WHERE m.templateValue = :templateValue",
|
||||
hints = {
|
||||
@QueryHint(name = "org.hibernate.cacheable", value = "true"),
|
||||
@QueryHint(name = "org.hibernate.cacheRegion", value = "Queries")})})
|
||||
public class MailTemplateEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4527399247302581555L;
|
||||
|
||||
@Id
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 40)
|
||||
@Column(name = "template_name")
|
||||
private String templateName;
|
||||
@Basic(optional = false)
|
||||
@NotNull
|
||||
@Size(min = 1, max = 2147483647)
|
||||
@Column(name = "template_value")
|
||||
private String templateValue;
|
||||
|
||||
public MailTemplateEntity() {
|
||||
}
|
||||
|
||||
public MailTemplateEntity(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public MailTemplateEntity(String templateName, String templateValue) {
|
||||
this.templateName = templateName;
|
||||
this.templateValue = templateValue;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public String getTemplateValue() {
|
||||
return templateValue;
|
||||
}
|
||||
|
||||
public void setTemplateValue(String templateValue) {
|
||||
this.templateValue = templateValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
hash += (templateName != null ? templateName.hashCode() : 0);
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
// TODO: Warning - this method won't work in the case the id fields are not set
|
||||
if (!(object instanceof MailTemplateEntity)) {
|
||||
return false;
|
||||
}
|
||||
MailTemplateEntity other = (MailTemplateEntity) object;
|
||||
if ((this.templateName == null && other.templateName != null) || (this.templateName != null && !this.templateName.equals(other.templateName))) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "de.muehlencord.shared.account.entity.MailTemplate[ templateName=" + templateName + " ]";
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,52 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.business.mail.entity;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author jomu
|
||||
*/
|
||||
public class MailTemplateException extends Exception {
|
||||
|
||||
/**
|
||||
* Creates a new instance of <code>MailTemplateException</code> without
|
||||
* detail message.
|
||||
*/
|
||||
public MailTemplateException() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>MailTemplateException</code> with the
|
||||
* specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
*/
|
||||
public MailTemplateException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an instance of <code>MailTemplateException</code> with the
|
||||
* specified detail message.
|
||||
*
|
||||
* @param msg the detail message.
|
||||
* @param th the root cause
|
||||
*/
|
||||
public MailTemplateException(String msg, Throwable th) {
|
||||
super(msg, th);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.account.business.account.entity.AccountEntity;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.context.ExternalContext;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import org.apache.shiro.SecurityUtils;
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.subject.Subject;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
@Named(value = "loginView")
|
||||
@ViewScoped
|
||||
public class LoginView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1164860380769648432L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String username = null;
|
||||
private String password = null;
|
||||
private boolean rememberMe = false;
|
||||
|
||||
private String resetPasswordToken = null;
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(LoginView.class.getName());
|
||||
|
||||
public void authenticate() {
|
||||
|
||||
// Example using most common scenario of username/password pair:
|
||||
UsernamePasswordToken token = new UsernamePasswordToken(getUsername(), getPassword());
|
||||
|
||||
// "Remember Me" built-in:
|
||||
token.setRememberMe(rememberMe);
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
LOGGER.info("Trying to login user {}", username);
|
||||
|
||||
try {
|
||||
currentUser.login(token);
|
||||
LOGGER.info("User {} logged in", username);
|
||||
// user logged in, update account entity
|
||||
AccountEntity account = accountService.getAccountEntity(username, true);
|
||||
accountService.updateLogin(account);
|
||||
|
||||
// redirect to home
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
ServletResponse servletResponse = (ServletResponse) ec.getResponse();
|
||||
String fallbackUrl = "/web/index.xhtml"; // TODO make configurable
|
||||
// ec.redirect(url);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("redirecting to {}, fallbackUrl={}", servletResponse.toString(), fallbackUrl);
|
||||
}
|
||||
|
||||
WebUtils.redirectToSavedRequest((ServletRequest) ec.getRequest(), servletResponse, fallbackUrl);
|
||||
} catch (IOException | AuthenticationException ex) {
|
||||
// Could catch a subclass of AuthenticationException if you like
|
||||
String hint = "Error while authenticating user " + username;
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(hint, ex);
|
||||
}
|
||||
|
||||
if (ex.getMessage() != null) {
|
||||
hint += "Reason: " + ex.getMessage();
|
||||
} else {
|
||||
hint += "Reason: " + ex.toString();
|
||||
}
|
||||
if ((ex.getCause() != null) && (ex.getCause().getMessage() != null)) {
|
||||
hint += "Rootcause: " + ex.getMessage();
|
||||
|
||||
LOGGER.error(hint);
|
||||
}
|
||||
FacesUtil.addGlobalErrorMessage("Login failed", hint);
|
||||
|
||||
AccountEntity account = accountService.getAccountEntity(username, false);
|
||||
if (account != null) {
|
||||
accountService.addLoginError(account);
|
||||
}
|
||||
} finally {
|
||||
token.clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void logout() {
|
||||
Subject currentUser = SecurityUtils.getSubject();
|
||||
try {
|
||||
currentUser.logout();
|
||||
|
||||
ExternalContext ec = FacesContext.getCurrentInstance().getExternalContext();
|
||||
|
||||
// ensure faces session is invalidated so beans are destroyed
|
||||
ec.invalidateSession();
|
||||
|
||||
// check if redirect shall be executed
|
||||
// default setting is yes to /login.xhtml
|
||||
// can be overwritten using parameters
|
||||
// de.muehlencord.shared.account.loginview.executeredirect boolean true/false
|
||||
// de.muehlencord.shared.account.loginview.redirecttarget path to redirect to (without external context, will be added automatically)
|
||||
String executeRedirectString = ec.getInitParameter("de.muehlencord.shared.account.loginview.executeredirect");
|
||||
boolean executeRedirect = true;
|
||||
if (executeRedirectString != null) {
|
||||
executeRedirect = Boolean.parseBoolean(executeRedirectString);
|
||||
}
|
||||
|
||||
String redirectTarget = ec.getInitParameter("de.muehlencord.shared.account.loginview.redirecttarget");
|
||||
if ((redirectTarget == null) || (redirectTarget.equals(""))) {
|
||||
redirectTarget = "/login.xhtml";
|
||||
}
|
||||
|
||||
if (executeRedirect) {
|
||||
String url = ec.getRequestContextPath() + redirectTarget;
|
||||
ec.redirect(url);
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
LOGGER.warn(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public String executePasswordReset() {
|
||||
boolean passwordResetted = accountService.resetPassword(username, password, resetPasswordToken);
|
||||
if (passwordResetted) {
|
||||
// TODO add email notification on updated user account
|
||||
FacesUtil.addGlobalInfoMessage("Password resetted", null);
|
||||
return login();
|
||||
} else {
|
||||
// TODO add email notificaton on failed password reset
|
||||
FacesUtil.addGlobalErrorMessage("Password reset failed", null);
|
||||
return login();
|
||||
}
|
||||
}
|
||||
|
||||
/* **** naviation rules **** */
|
||||
public String login() {
|
||||
return "/login.xhtml"; // TODO make configurable
|
||||
}
|
||||
|
||||
/* *** getter / setter */
|
||||
public String getUsername() {
|
||||
return username;
|
||||
}
|
||||
|
||||
public void setUsername(String un) {
|
||||
this.username = un;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return password;
|
||||
}
|
||||
|
||||
public void setPassword(String pw) {
|
||||
this.password = pw;
|
||||
}
|
||||
|
||||
public boolean isRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public void setRememberMe(boolean rememberMe) {
|
||||
this.rememberMe = rememberMe;
|
||||
}
|
||||
|
||||
public String getResetPasswordToken() {
|
||||
return resetPasswordToken;
|
||||
}
|
||||
|
||||
public void setResetPasswordToken(String resetPasswordToken) {
|
||||
this.resetPasswordToken = resetPasswordToken;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.presentation;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.control.AccountControl;
|
||||
import de.muehlencord.shared.jeeutil.FacesUtil;
|
||||
import java.io.Serializable;
|
||||
import javax.ejb.EJB;
|
||||
import javax.faces.view.ViewScoped;
|
||||
import javax.inject.Named;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern@muehlencord.de
|
||||
*/
|
||||
@Named (value = "lostPasswordView")
|
||||
@ViewScoped
|
||||
public class LostPasswordView implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -1793445795465830069L;
|
||||
|
||||
@EJB
|
||||
private AccountControl accountService;
|
||||
|
||||
private String userName;
|
||||
private boolean passwordResetStarted = false;
|
||||
|
||||
public String initPasswordReset() {
|
||||
if (accountService.initPasswordReset(userName)) {
|
||||
passwordResetStarted = true;
|
||||
FacesUtil.addGlobalInfoMessage("Password reset started.", "Please check your email account.");
|
||||
} else {
|
||||
FacesUtil.addGlobalErrorMessage("Error while resetting password.", "Please contact your administrator.");
|
||||
}
|
||||
return "/login.xhtml"; // TODO make configurable, get from LoginView?
|
||||
}
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public boolean getPasswordResetStarted() {
|
||||
return passwordResetStarted;
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.shiro.authc;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.boundary.ApiKeyService;
|
||||
import de.muehlencord.shared.account.business.account.entity.JWTObject;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.credential.CredentialsMatcher;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
public class JwtMatcher implements CredentialsMatcher {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(JwtMatcher.class);
|
||||
private final ApiKeyService apiKeyService = lookupApiKeyServiceBean();
|
||||
|
||||
@Override
|
||||
public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
|
||||
if (token == null) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("No token available - cannot match credentials");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((info == null) || (info.getCredentials() == null)) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("No authenticationInfo available - cannot match credentials");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Object submittedJwtObj = token.getCredentials();
|
||||
Object storedCredentials = getStoredPassword(info);
|
||||
if ((submittedJwtObj != null) && (submittedJwtObj.getClass().isAssignableFrom(String.class))) {
|
||||
String submittedJwt = (String) submittedJwtObj;
|
||||
if (apiKeyService.validateJWT(submittedJwt)) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("JWT is valid, checking if it comes from the correct user");
|
||||
}
|
||||
|
||||
JWTObject jwtObject = apiKeyService.getJWTObject(submittedJwt);
|
||||
String storedUsername = info.getPrincipals().getPrimaryPrincipal().toString();
|
||||
if (jwtObject.getUserName().equals(storedUsername)) {
|
||||
if (jwtObject.getUnqiueId().equals (storedCredentials)) {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("JWT matches user and password is correct");
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JWT password does not match provided password");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("JWT belongs to user {}, but authinfo is from user {} - JWT does not match");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("JWT is invalid");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
LOGGER.error("Unexpected authInfoFormat - please check your configuration");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected Object getStoredPassword(AuthenticationInfo storedAccountInfo) {
|
||||
Object stored = storedAccountInfo != null ? storedAccountInfo.getCredentials() : null;
|
||||
//fix for https://issues.apache.org/jira/browse/SHIRO-363
|
||||
if (stored instanceof char[]) {
|
||||
stored = new String((char[]) stored);
|
||||
}
|
||||
return stored;
|
||||
}
|
||||
|
||||
// TODO - can this be injected?
|
||||
private ApiKeyService lookupApiKeyServiceBean() {
|
||||
try {
|
||||
Context c = new InitialContext();
|
||||
return (ApiKeyService) c.lookup("java:module/ApiKeyService"); // NOI18N
|
||||
} catch (NamingException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,169 +0,0 @@
|
||||
/*
|
||||
* Copyright 2018 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.shiro.filter;
|
||||
|
||||
import de.muehlencord.shared.account.business.account.boundary.ApiKeyService;
|
||||
import de.muehlencord.shared.account.business.account.entity.JWTObject;
|
||||
import de.muehlencord.shared.account.shiro.token.JWTAuthenticationToken;
|
||||
import de.muehlencord.shared.account.util.AccountSecurityException;
|
||||
import de.muehlencord.shared.jeeutil.restexfw.APIException;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import javax.json.Json;
|
||||
import javax.json.JsonObject;
|
||||
import javax.json.JsonReader;
|
||||
import javax.naming.Context;
|
||||
import javax.naming.InitialContext;
|
||||
import javax.naming.NamingException;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
||||
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
|
||||
import org.apache.shiro.web.util.WebUtils;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
||||
*/
|
||||
public final class JWTAuthenticationFilter extends AuthenticatingFilter {
|
||||
|
||||
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(JWTAuthenticationFilter.class);
|
||||
protected static final String AUTHORIZATION_HEADER = "Authorization"; // NOI18N
|
||||
protected static final String USERNAME = "username"; // NOI18N
|
||||
protected static final String PASSWORD = "password"; // NOI18N
|
||||
|
||||
private final ApiKeyService apiKeyService = lookupApiKeyServiceBean();
|
||||
|
||||
public JWTAuthenticationFilter() {
|
||||
// FIXME - logging in via JWTAuthenticationFilter does not yet work. Need to set login to anonymous to execute login in rest service
|
||||
setLoginUrl("/rest/account/login");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
|
||||
boolean loggedIn = false;
|
||||
|
||||
if (isLoginRequest(request, response) || isLoggedAttempt(request, response)) {
|
||||
loggedIn = executeLogin(request, response);
|
||||
}
|
||||
|
||||
if (!loggedIn) {
|
||||
HttpServletResponse httpResponse = WebUtils.toHttp(response);
|
||||
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
|
||||
return loggedIn;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
|
||||
if (isLoginRequest(request, response)) {
|
||||
String json = IOUtils.toString(request.getInputStream(), "UTF-8"); // FIXME - check charset in request
|
||||
|
||||
if (json != null && !json.isEmpty()) {
|
||||
try (JsonReader jr = Json.createReader(new StringReader(json))) {
|
||||
JsonObject object = jr.readObject();
|
||||
String username = object.getString(USERNAME);
|
||||
String password = object.getString(PASSWORD);
|
||||
return new UsernamePasswordToken(username, password);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoggedAttempt(request, response)) {
|
||||
String jwtToken = getAuthzHeader(request);
|
||||
if (LOGGER.isTraceEnabled()) {
|
||||
LOGGER.trace("found jwtToken in header = {}", jwtToken);
|
||||
}
|
||||
|
||||
if (jwtToken != null) {
|
||||
JWTObject jwtObject = apiKeyService.getJWTObject(jwtToken);
|
||||
return new JWTAuthenticationToken(jwtObject.getUserName(), jwtToken);
|
||||
}
|
||||
}
|
||||
|
||||
return new UsernamePasswordToken();
|
||||
}
|
||||
|
||||
private boolean isLoggedAttempt(ServletRequest request, ServletResponse response) {
|
||||
String authzHeader = getAuthzHeader(request);
|
||||
return authzHeader != null;
|
||||
}
|
||||
|
||||
private String getAuthzHeader(ServletRequest request) {
|
||||
HttpServletRequest httpRequest = WebUtils.toHttp(request);
|
||||
return httpRequest.getHeader(AUTHORIZATION_HEADER);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Overwrite cleanup to ensure no exception is thrown if an
|
||||
* AccountSecurityException / APIException is raised during login. As long
|
||||
* as the user is not logged in JERSEYs ExceptionMapper and intercepor
|
||||
* classes are overruled by Shiro.
|
||||
*
|
||||
* @param request the incoming request
|
||||
* @param response the response to return
|
||||
* @param existing the raised exception
|
||||
* @throws ServletException may be thrown by AuthenticatingFilter.cleanup if
|
||||
* existing is not a AccountSecurityException
|
||||
* @throws IOException may be thrown by AuthenticatingFilter.cleanup if
|
||||
* existing is not a AccountSecurityException
|
||||
*/
|
||||
@Override
|
||||
protected void cleanup(ServletRequest request, ServletResponse response, Exception existing) throws ServletException, IOException {
|
||||
if ((existing != null) && (existing.getClass().isAssignableFrom(AccountSecurityException.class))) {
|
||||
HttpServletResponse httpResponse = WebUtils.toHttp(response);
|
||||
httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
} else if ((existing != null) && (existing.getClass().isAssignableFrom(APIException.class))) {
|
||||
APIException apiException = (APIException) existing;
|
||||
|
||||
HttpServletResponse httpResponse = WebUtils.toHttp(response);
|
||||
httpResponse.setStatus(apiException.getHttpResponse().getStatus());
|
||||
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR));
|
||||
httpResponse.addHeader(APIException.HTTP_HEADER_X_ERROR_CODE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ERROR_CODE));
|
||||
|
||||
if (apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE) != null) {
|
||||
httpResponse.addHeader(APIException.HTTP_HEADER_X_ROOT_CAUSE, apiException.getHttpResponse().getHeaderString(APIException.HTTP_HEADER_X_ROOT_CAUSE));
|
||||
}
|
||||
} else {
|
||||
super.cleanup(request, response, existing);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - can this be injected?
|
||||
private ApiKeyService lookupApiKeyServiceBean() {
|
||||
try {
|
||||
Context c = new InitialContext();
|
||||
return (ApiKeyService) c.lookup("java:module/ApiKeyService"); // NOI18N
|
||||
} catch (NamingException ex) {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(ex.toString(), ex);
|
||||
} else {
|
||||
LOGGER.error(ex.toString());
|
||||
}
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,82 +0,0 @@
|
||||
/*
|
||||
* Copyright 2019 joern.muehlencord.
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
package de.muehlencord.shared.account.shiro.pam;
|
||||
|
||||
import org.apache.shiro.authc.AuthenticationException;
|
||||
import org.apache.shiro.authc.AuthenticationInfo;
|
||||
import org.apache.shiro.authc.AuthenticationToken;
|
||||
import org.apache.shiro.authc.UnknownAccountException;
|
||||
import org.apache.shiro.authc.pam.AbstractAuthenticationStrategy;
|
||||
import org.apache.shiro.realm.Realm;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author joern.muehlencord
|
||||
*/
|
||||
public class AllSupportedSuccessfulStrategy extends AbstractAuthenticationStrategy {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(AllSupportedSuccessfulStrategy.class);
|
||||
|
||||
public AuthenticationInfo beforeAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo info) throws AuthenticationException {
|
||||
if (!realm.supports(token)) {
|
||||
return info;
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
public AuthenticationInfo afterAttempt(Realm realm, AuthenticationToken token, AuthenticationInfo info, AuthenticationInfo aggregate, Throwable t)
|
||||
throws AuthenticationException {
|
||||
if (t != null) {
|
||||
if (t instanceof AuthenticationException) {
|
||||
//propagate:
|
||||
throw ((AuthenticationException) t);
|
||||
} else {
|
||||
String msg = "Unable to acquire account data from realm [" + realm + "]. The ["
|
||||
+ getClass().getName() + " implementation requires all configured realm(s) to operate successfully "
|
||||
+ "for a successful authentication.";
|
||||
throw new AuthenticationException(msg, t);
|
||||
}
|
||||
}
|
||||
if (info == null) {
|
||||
if (realm.supports(token)) {
|
||||
String msg = "Realm [" + realm + "] could not find any associated account data for the submitted "
|
||||
+ "AuthenticationToken [" + token + "]. The [" + getClass().getName() + "] implementation requires "
|
||||
+ "all configured realm(s) to acquire valid account data for a submitted token during the "
|
||||
+ "log-in process.";
|
||||
throw new UnknownAccountException(msg);
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Realm [{}] does not support token of type [{}], skipped realm", realm, token);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOGGER.debug("Account successfully authenticated using realm [{}]", realm);
|
||||
}
|
||||
|
||||
// If non-null account is returned, then the realm was able to authenticate the
|
||||
// user - so merge the account with any accumulated before
|
||||
// if the realm does not support the token, null is returned
|
||||
if (realm.supports(token)) {
|
||||
merge(info, aggregate);
|
||||
}
|
||||
|
||||
return aggregate;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user