Compare commits
84 Commits
v1.1
...
f2387ffe92
| Author | SHA1 | Date | |
|---|---|---|---|
| f2387ffe92 | |||
| c844c7a504 | |||
| 5c74d12622 | |||
| 62ceea63bc | |||
| 32af3caf77 | |||
| 70302edc58 | |||
| fb1b3001ac | |||
| 9297be25d6 | |||
| ddeedfb3ad | |||
| 3b4c214e3f | |||
| 081af716d1 | |||
| 84ed78bcef | |||
| 1d8ff8b02e | |||
| ffaf9a16c5 | |||
| 698ddfd199 | |||
| ec82f06f88 | |||
| d427956422 | |||
| e82a4cadd4 | |||
| 84b8b0545f | |||
| cd2e3b0642 | |||
| b129228b36 | |||
| 57907d05e6 | |||
| c983bde031 | |||
| 0e21c9baf7 | |||
| e12127f6dd | |||
| 9090b2c66e | |||
| 799c7d52e3 | |||
| 6d9a87e15b | |||
| 4dddc1f3dc | |||
| b4a28bb0b0 | |||
| d5dc39e8ff | |||
| 233164fb54 | |||
| bea1d80f1e | |||
| 571386046d | |||
| 103b8348d0 | |||
| 06fe2231ec | |||
| 113cb4a641 | |||
| 6d49dec89f | |||
| ee1a20836d | |||
| 626ab1b528 | |||
| aeab3a5ca9 | |||
| a2430f748f | |||
| af298c8060 | |||
| 6348f81bed | |||
| 13d16a1309 | |||
| 585b6d7d02 | |||
| a071cb5732 | |||
| f804c11ceb | |||
| 218d7a7365 | |||
| 2128ad95bc | |||
| 53991b7f56 | |||
| 59420af4a5 | |||
| fe8b0d272b | |||
| 89ddbbdbb2 | |||
| c4d71f9614 | |||
| 97649c9306 | |||
| 0cbab859f8 | |||
| eb3bf3b71a | |||
| b138841faa | |||
| 5a840dad7f | |||
| 0f98586434 | |||
| 08a0adcc6f | |||
| 8205ffaec3 | |||
| 54f2e56a4c | |||
| 119fb04520 | |||
| 24dc927ab7 | |||
| 3ae4dba8fe | |||
| bf590223b8 | |||
| 1e5e15cda0 | |||
| 40acbcd6ac | |||
| ab2a0e2301 | |||
| a8e0f9bd5f | |||
| 88d2509893 | |||
| 96892cf8f9 | |||
| 6829b65a2f | |||
| a9e136d3ac | |||
| aa478dbf9f | |||
| 2a75d2a1fe | |||
| a8a609491f | |||
| 43f5401773 | |||
| e9dede69cb | |||
| 7a380dc214 | |||
| 212e4dad5d | |||
| d50f21f869 |
1154
.editorconfig
Normal file
1154
.editorconfig
Normal file
File diff suppressed because it is too large
Load Diff
197
.gitignore
vendored
197
.gitignore
vendored
@ -1,8 +1,191 @@
|
|||||||
/**/.settings/
|
# ---> NetBeans
|
||||||
**/target/
|
nbproject/private/
|
||||||
.classpath
|
build/
|
||||||
.project
|
nbbuild/
|
||||||
**/nbproject/
|
dist/
|
||||||
*.dump
|
nbdist/
|
||||||
**/_dump
|
nbactions.xml
|
||||||
**/nb-configuration.xml
|
**/nb-configuration.xml
|
||||||
|
.nb-gradle/
|
||||||
|
**/faces-config.NavData
|
||||||
|
|
||||||
|
# ---> 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
|
||||||
|
|
||||||
|
|
||||||
|
# --> Idea
|
||||||
|
**/.idea
|
||||||
|
**/*.iml
|
||||||
|
|
||||||
|
# ---> 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
|
||||||
|
|
||||||
|
|
||||||
|
## project specific
|
||||||
|
/source/vvh-access-import/src/main/resources/hibernate.cfg.xml
|
||||||
|
/source/office-parent/office-entities/src/main/resources/META-INF/persistence.xml
|
||||||
|
|||||||
@ -1,55 +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.1</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<groupId>de.muehlencord.shared</groupId>
|
|
||||||
<artifactId>shared-account-dao</artifactId>
|
|
||||||
<packaging>jar</packaging>
|
|
||||||
|
|
||||||
<name>shared-account-dao</name>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.google.code.gson</groupId>
|
|
||||||
<artifactId>gson</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-annotations</artifactId>
|
|
||||||
<version>2.9.8</version>
|
|
||||||
</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>
|
|
||||||
<dependency>
|
|
||||||
<groupId>com.fasterxml.jackson.core</groupId>
|
|
||||||
<artifactId>jackson-databind</artifactId>
|
|
||||||
<version>2.9.8</version>
|
|
||||||
<type>jar</type>
|
|
||||||
</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,150 +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.1</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>
|
|
||||||
</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/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,7 +0,0 @@
|
|||||||
jsf.projectStage=Development
|
|
||||||
|
|
||||||
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,17 +0,0 @@
|
|||||||
jsf.projectStage=Production
|
|
||||||
|
|
||||||
ldap.url = ldaps://host:port
|
|
||||||
## we will use provided username / password from webapplication
|
|
||||||
ldap.user = user
|
|
||||||
ldap.password = secret
|
|
||||||
ldap.suffix = @diebold.com
|
|
||||||
ldap.fallbackSuffix = @dieboldnixdorf.com
|
|
||||||
ldap.searchBase = dc=ad,dc=diebold,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.suffix}${line.separator}ldapRealm.fallbackPrincipalSuffix = ${ldap.fallbackSuffix}${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.instance.boundary.ApplicationPermissions;
|
|
||||||
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 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.account.util.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,151 +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 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.instance.control.ApplicationController;
|
|
||||||
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 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,69 +0,0 @@
|
|||||||
package de.muehlencord.shared.account.web.presentation;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @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,63 +0,0 @@
|
|||||||
package de.muehlencord.shared.account.web.presentation;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
import de.muehlencord.shared.account.business.application.control.ApplicationControl;
|
|
||||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @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.entity.ApplicationPermissionEntity;
|
|
||||||
import de.muehlencord.shared.account.business.application.control.ApplicationPermissionControl;
|
|
||||||
import de.muehlencord.shared.account.business.application.entity.ApplicationEntity;
|
|
||||||
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,32 +0,0 @@
|
|||||||
admin.loginPage=login.xhtml
|
|
||||||
admin.indexPage=web/index.xhtml
|
|
||||||
#admin.dateFormat=
|
|
||||||
#admin.breadcrumbSize=5
|
|
||||||
admin.renderMessages=true
|
|
||||||
#admin.renderAjaxStatus=true
|
|
||||||
## disable filter to redirect to login page - shiro security filter is already doing this
|
|
||||||
admin.disableFilter=true
|
|
||||||
#admin.renderBreadCrumb=true
|
|
||||||
#admin.enableSlideMenu=true
|
|
||||||
#admin.enableRipple=true
|
|
||||||
#admin.rippleElements= .ripplelink,button.ui-button,.ui-selectlistbox-item,.ui-multiselectlistbox-item,.ui-selectonemenu-label,.ui-selectcheckboxmenu,\
|
|
||||||
#.ui-autocomplete-dropdown, .ui-autocomplete-item ... (the list goes on)
|
|
||||||
admin.skin=skin-purple-light
|
|
||||||
#admin.autoShowNavbar=true
|
|
||||||
#admin.ignoredResources=
|
|
||||||
#admin.loadingImage=ajaxloadingbar.gif
|
|
||||||
#admin.extensionLessUrls=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=true
|
|
||||||
#admin.rippleMobileOnly=true
|
|
||||||
admin.renderMenuSearch=false
|
|
||||||
## do not autohide
|
|
||||||
admin.autoHideMessages=false
|
|
||||||
#admin.messagesHideTimeout=2500
|
|
||||||
@ -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,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>web/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,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,84 +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-6">
|
|
||||||
<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}" actionListener="#{applicationView.selectApplication}" />
|
|
||||||
</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="applicationName" value="Application name" />
|
|
||||||
</div>
|
|
||||||
<div class="col-sm-12 col-md-6">
|
|
||||||
<p:inputText id="applicationName" value="#{applicationView.editApplication.applicationName}">
|
|
||||||
<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>
|
|
||||||
112
account/pom.xml
112
account/pom.xml
@ -1,112 +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.1</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<name>shared-account</name>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
<maven.compiler.source>10</maven.compiler.source>
|
|
||||||
<maven.compiler.target>10</maven.compiler.target>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<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>${project.groupId}</groupId>
|
|
||||||
<artifactId>shared-account-dao</artifactId>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>junit</groupId>
|
|
||||||
<artifactId>junit</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.mockito</groupId>
|
|
||||||
<artifactId>mockito-core</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>de.muehlencord.shared</groupId>
|
|
||||||
<artifactId>shared-util</artifactId>
|
|
||||||
<type>jar</type>
|
|
||||||
</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="200"/>
|
|
||||||
</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,10 +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;
|
|
||||||
@ -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,305 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2016 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.business;
|
|
||||||
|
|
||||||
import de.muehlencord.shared.account.business.account.entity.Account;
|
|
||||||
import de.muehlencord.shared.account.util.ApplicationPU;
|
|
||||||
import de.muehlencord.shared.account.util.Updateable;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import javax.ejb.Lock;
|
|
||||||
import javax.ejb.LockType;
|
|
||||||
import javax.ejb.TransactionAttribute;
|
|
||||||
import javax.ejb.TransactionAttributeType;
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.persistence.EntityManager;
|
|
||||||
import javax.persistence.TypedQuery;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Order;
|
|
||||||
import javax.persistence.criteria.Path;
|
|
||||||
import javax.persistence.criteria.Predicate;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
import javax.persistence.metamodel.IdentifiableType;
|
|
||||||
import javax.persistence.metamodel.Metamodel;
|
|
||||||
import javax.persistence.metamodel.SingularAttribute;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
import org.apache.shiro.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
|
||||||
* @param <T>
|
|
||||||
*/
|
|
||||||
public abstract class AbstractController<T> {
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
@ApplicationPU
|
|
||||||
protected EntityManager em;
|
|
||||||
|
|
||||||
@Inject
|
|
||||||
protected Account account;
|
|
||||||
|
|
||||||
private final Class<T> entityClass;
|
|
||||||
|
|
||||||
public AbstractController(Class<T> clazz) {
|
|
||||||
this.entityClass = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Predicate getFilterCondition(CriteriaBuilder cb, Root<T> root, Map<String, Object> filters) {
|
|
||||||
return getFilterCondition(cb, root, filters, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Predicate getFilterCondition(CriteriaBuilder cb, Root<T> root, Map<String, Object> filters, Map<String, Object> excludeFilters) {
|
|
||||||
Predicate filterCondition = null;
|
|
||||||
filterCondition = getFilterCondition(filterCondition, cb, root, filters, true);
|
|
||||||
filterCondition = getFilterCondition(filterCondition, cb, root, excludeFilters, false);
|
|
||||||
return filterCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Predicate addFilterCondition(CriteriaBuilder cb, Predicate filterCondition, Predicate addCondition) {
|
|
||||||
if (addCondition == null) {
|
|
||||||
return filterCondition;
|
|
||||||
}
|
|
||||||
if (filterCondition == null) {
|
|
||||||
filterCondition = addCondition;
|
|
||||||
} else {
|
|
||||||
filterCondition = cb.and(filterCondition, addCondition);
|
|
||||||
}
|
|
||||||
return filterCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* extends the given filterCondition by the addtional filters
|
|
||||||
*
|
|
||||||
* @param filterCondition the current filter condition
|
|
||||||
* @param cb the criteria builder to use
|
|
||||||
* @param root the root of the object to search for
|
|
||||||
* @param filters the filters to apply
|
|
||||||
* @param include if set to true, the filter is used as include filter
|
|
||||||
* (equals, in). If set to false, the filter is inverted and used as exclude
|
|
||||||
* filter (not equals, not in etc)
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
protected Predicate getFilterCondition(Predicate filterCondition, CriteriaBuilder cb, Root<T> root, Map<String, Object> filters, boolean include) {
|
|
||||||
String wildCard = "%";
|
|
||||||
if (filters != null) {
|
|
||||||
for (Map.Entry<String, Object> filter : filters.entrySet()) {
|
|
||||||
if (!"".equals(filter.getValue())) {
|
|
||||||
Path<String> path = getPathElement(root, filter);
|
|
||||||
|
|
||||||
// check for differnt types
|
|
||||||
// 1st String, either from Enum Status or from other free text string
|
|
||||||
if (String.class.equals(filter.getValue().getClass())) {
|
|
||||||
switch (filter.getKey()) {
|
|
||||||
default:
|
|
||||||
String filterValue = filter.getValue().toString();
|
|
||||||
Predicate predicate;
|
|
||||||
if (filterValue.equals("{NULL}")) {
|
|
||||||
if (include) {
|
|
||||||
predicate = cb.isNull(path);
|
|
||||||
} else {
|
|
||||||
predicate = cb.isNotNull(path);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
filterValue = filterValue.trim();
|
|
||||||
filterValue = filterValue.replace("?", "_");
|
|
||||||
filterValue = filterValue.replace("*", "%");
|
|
||||||
|
|
||||||
String[] values = filterValue.split("\\s+"); // split by whitespaces
|
|
||||||
Predicate[] partSearchPredicates = new Predicate[values.length];
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
String value = wildCard + values[i] + wildCard;
|
|
||||||
if (include) {
|
|
||||||
partSearchPredicates[i] = cb.like(cb.upper(path), value.toUpperCase(Locale.US), '\\');
|
|
||||||
} else {
|
|
||||||
partSearchPredicates[i] = cb.notLike(cb.upper(path), value.toUpperCase(Locale.US), '\\');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
predicate = cb.and(partSearchPredicates); // all parts must be available
|
|
||||||
}
|
|
||||||
filterCondition = addFilterCondition(cb, filterCondition, predicate);
|
|
||||||
}
|
|
||||||
} // 2nd for arrays, received from e.g. project selections
|
|
||||||
else if (filter.getValue().getClass().isArray()) {
|
|
||||||
Predicate condition = null;
|
|
||||||
Object[] values = (Object[]) filter.getValue();
|
|
||||||
if (values.length > 0) {
|
|
||||||
for (Object value : values) {
|
|
||||||
if (include) {
|
|
||||||
Predicate equalPredicate = cb.equal(path, value);
|
|
||||||
if (condition == null) {
|
|
||||||
condition = equalPredicate;
|
|
||||||
} else {
|
|
||||||
condition = cb.or(condition, equalPredicate);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Predicate equalPredicate = cb.notEqual(path, value);
|
|
||||||
if (condition == null) {
|
|
||||||
condition = equalPredicate;
|
|
||||||
} else {
|
|
||||||
condition = cb.and(condition, equalPredicate);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
filterCondition = addFilterCondition(cb, filterCondition, condition);
|
|
||||||
}
|
|
||||||
} else { // at last object comparison
|
|
||||||
if (include) {
|
|
||||||
filterCondition = addFilterCondition(cb, filterCondition, cb.equal(path, filter.getValue()));
|
|
||||||
} else {
|
|
||||||
filterCondition = addFilterCondition(cb, filterCondition, cb.notEqual(path, filter.getValue()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return filterCondition;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Path<String> getPathElement(Root<T> root, Map.Entry<String, Object> filter) {
|
|
||||||
String[] pathElements = StringUtils.split(filter.getKey(), '.');
|
|
||||||
Path<String> path = null;
|
|
||||||
for (String element : pathElements) {
|
|
||||||
if (path == null) {
|
|
||||||
path = root.get(element);
|
|
||||||
} else {
|
|
||||||
path = path.get(element);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyUpdateableChanges(Updateable updateable, boolean onCreate) throws ControllerException {
|
|
||||||
if (onCreate) {
|
|
||||||
updateable.setCreatedBy(account.getUsername());
|
|
||||||
updateable.setCreatedOn(new Date());
|
|
||||||
}
|
|
||||||
updateable.setLastUpdatedBy(account.getUsername());
|
|
||||||
updateable.setLastUpdatedOn(new Date());
|
|
||||||
}
|
|
||||||
|
|
||||||
public T attach(T entity) {
|
|
||||||
return em.merge(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
public T create(T entity) throws ControllerException {
|
|
||||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
|
||||||
Updateable updateable = (Updateable) entity;
|
|
||||||
applyUpdateableChanges(updateable, true);
|
|
||||||
}
|
|
||||||
em.persist(entity);
|
|
||||||
return entity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
public T update(T entity) throws ControllerException {
|
|
||||||
if (Updateable.class.isAssignableFrom(entity.getClass())) {
|
|
||||||
Updateable updateable = (Updateable) entity;
|
|
||||||
applyUpdateableChanges(updateable, false);
|
|
||||||
}
|
|
||||||
return em.merge(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
public void delete(T entity) throws ControllerException {
|
|
||||||
em.remove(attach(entity));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
public T find(Object id) {
|
|
||||||
return em.find(entityClass, id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
public List<T> findAll() {
|
|
||||||
return findAll(new ArrayList<>());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
public List<T> findAll(String... orderFields) {
|
|
||||||
return findAll(Arrays.asList(orderFields));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
public List<T> findAll(List<String> orderFields) {
|
|
||||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
|
||||||
final CriteriaQuery<T> criteria = cb.createQuery(entityClass);
|
|
||||||
|
|
||||||
final Root<T> r = criteria.from(entityClass);
|
|
||||||
|
|
||||||
List<Order> orderList = new ArrayList<>();
|
|
||||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(r.get(field))));
|
|
||||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
|
||||||
|
|
||||||
return query.getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
public List<T> find(Map<String, Object> filters, List<String> orderFields) {
|
|
||||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
|
||||||
final CriteriaQuery<T> criteria = cb.createQuery(entityClass);
|
|
||||||
|
|
||||||
final Root<T> r = criteria.from(entityClass);
|
|
||||||
Predicate filterCondition = getFilterCondition(cb, r, filters);
|
|
||||||
if (filterCondition != null) {
|
|
||||||
criteria.where(filterCondition);
|
|
||||||
}
|
|
||||||
List<Order> orderList = new ArrayList<>();
|
|
||||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(r.get(field))));
|
|
||||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
|
||||||
|
|
||||||
return query.getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* returns null, if the list is empty or null itself. Returns the one
|
|
||||||
* element if there is exactly one element in the list. Otherwise an
|
|
||||||
* exception is thrown
|
|
||||||
*
|
|
||||||
* @param resultList
|
|
||||||
* @return
|
|
||||||
* @throws ControllerException
|
|
||||||
*/
|
|
||||||
public T ensureSingleElement(List<T> resultList) throws ControllerException {
|
|
||||||
if ((resultList == null) || (resultList.isEmpty())) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (resultList.size() > 1) {
|
|
||||||
throw new ControllerException(ControllerException.CAUSE_TOO_MANY_ROWS, "More than one element found in list - expected exactly one");
|
|
||||||
}
|
|
||||||
return resultList.get(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
private <T> SingularAttribute<? super T, ?> getIdAttribute() {
|
|
||||||
Metamodel m = em.getEntityManagerFactory().getMetamodel();
|
|
||||||
IdentifiableType<T> of = (IdentifiableType<T>) m.managedType(entityClass);
|
|
||||||
// of.getDeclaredId(entityClass).getJavaMember().
|
|
||||||
return of.getId(of.getIdType().getJavaType());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,106 +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.business;
|
|
||||||
|
|
||||||
import de.muehlencord.shared.account.util.EndDateable;
|
|
||||||
import de.muehlencord.shared.account.util.Updateable;
|
|
||||||
import de.muehlencord.shared.util.DateUtil;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Date;
|
|
||||||
import java.util.List;
|
|
||||||
import javax.ejb.Lock;
|
|
||||||
import javax.ejb.LockType;
|
|
||||||
import javax.ejb.TransactionAttribute;
|
|
||||||
import javax.ejb.TransactionAttributeType;
|
|
||||||
import javax.persistence.TypedQuery;
|
|
||||||
import javax.persistence.criteria.CriteriaBuilder;
|
|
||||||
import javax.persistence.criteria.CriteriaQuery;
|
|
||||||
import javax.persistence.criteria.Order;
|
|
||||||
import javax.persistence.criteria.Predicate;
|
|
||||||
import javax.persistence.criteria.Root;
|
|
||||||
import javax.transaction.Transactional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author Joern Muehlencord <joern at muehlencord.de>
|
|
||||||
* @param <T> an entity which needs to extend EndDateable
|
|
||||||
*/
|
|
||||||
public abstract class AbstractEnddateableController<T extends EndDateable<T>> extends AbstractController<T> {
|
|
||||||
|
|
||||||
private final Class<T> endDateableClass;
|
|
||||||
|
|
||||||
public AbstractEnddateableController(Class<T> clazz) {
|
|
||||||
super(clazz);
|
|
||||||
this.endDateableClass = clazz;
|
|
||||||
}
|
|
||||||
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
@Override
|
|
||||||
public void delete(T entity) throws ControllerException {
|
|
||||||
T entityToUpdate = attach(entity);
|
|
||||||
if (Updateable.class.isAssignableFrom(entityToUpdate.getClass())) {
|
|
||||||
Updateable updateable = (Updateable) entityToUpdate;
|
|
||||||
applyUpdateableChanges(updateable, false);
|
|
||||||
}
|
|
||||||
entityToUpdate.setValidTo(DateUtil.getCurrentTimeInUTC());
|
|
||||||
em.merge(entityToUpdate);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
public T create(T entity) throws ControllerException {
|
|
||||||
entity.setValidFrom(DateUtil.getCurrentTimeInUTC());
|
|
||||||
return super.create(entity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@TransactionAttribute(TransactionAttributeType.REQUIRED)
|
|
||||||
@Transactional
|
|
||||||
@Lock(LockType.WRITE)
|
|
||||||
@Override
|
|
||||||
public T update(T entity) throws ControllerException {
|
|
||||||
T newEntity = entity.cloneEndDateable();
|
|
||||||
delete(entity);
|
|
||||||
return create (newEntity);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Lock(LockType.READ)
|
|
||||||
@Override
|
|
||||||
public List<T> findAll(List<String> orderFields) {
|
|
||||||
Date now = DateUtil.getCurrentTimeInUTC();
|
|
||||||
final CriteriaBuilder cb = em.getCriteriaBuilder();
|
|
||||||
final CriteriaQuery<T> criteria = cb.createQuery(endDateableClass);
|
|
||||||
final Root<T> root = criteria.from(endDateableClass);
|
|
||||||
|
|
||||||
Predicate alreadyValid = cb.lessThanOrEqualTo(root.get("validFrom"), now);
|
|
||||||
|
|
||||||
Predicate validToNotSet = cb.isNull(root.get("validTo"));
|
|
||||||
Predicate isBeforeValidTo = cb.greaterThanOrEqualTo(root.get("validTo"), now);
|
|
||||||
Predicate stillValid = cb.or (isBeforeValidTo, validToNotSet);
|
|
||||||
Predicate isValid = cb.and(alreadyValid, stillValid);
|
|
||||||
criteria.where(isValid);
|
|
||||||
|
|
||||||
List<Order> orderList = new ArrayList<>();
|
|
||||||
orderFields.stream().forEachOrdered(field -> orderList.add(cb.asc(root.get(field))));
|
|
||||||
final TypedQuery<T> query = em.createQuery(criteria.orderBy(orderList));
|
|
||||||
|
|
||||||
return query.getResultList();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -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,115 +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 = SecurityUtils.getSubject();
|
|
||||||
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,339 +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.ControllerException;
|
|
||||||
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.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)) {
|
|
||||||
LOGGER.error("password, issuer or username not set in, please validate configuration");
|
|
||||||
}
|
|
||||||
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,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,261 +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.ControllerException;
|
|
||||||
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 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.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 (configValue == null) {
|
|
||||||
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, 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 = 200)
|
|
||||||
@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.ControllerException;
|
|
||||||
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 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,202 +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.subject.Subject;
|
|
||||||
import org.apache.shiro.SecurityUtils;
|
|
||||||
import org.apache.shiro.authc.AuthenticationException;
|
|
||||||
import org.apache.shiro.authc.UsernamePasswordToken;
|
|
||||||
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,172 +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 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;
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @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 jwtToke 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