Merge "Test Eclipse Gitea Connect Gerrit" into DEVELOP_BE
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8550c70
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,15 @@
+.git
+.idea/**/*.xml
+.settings
+.classpath
+target
+/.idea/compiler.xml
+/.idea/*.xml
+/.idea/modules.xml
+/.idea/vcs.xml
+/bin/
+.iml
+.project
+.classpath
+.idea
+/portal.iml
diff --git a/LICENSE.md b/LICENSE.md
new file mode 100644
index 0000000..11ecb79
--- /dev/null
+++ b/LICENSE.md
@@ -0,0 +1,198 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC
+LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM
+CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation
+ distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+ i) changes to the Program, and
+ ii) additions to the Program;
+
+ where such changes and/or additions to the Program originate from and are
+ distributed by that particular Contributor. A Contribution 'originates' from
+ a Contributor if it was added to the Program by such Contributor itself or
+ anyone acting on such Contributor's behalf. Contributions do not include
+ additions to the Program which: (i) are separate modules of software
+ distributed in conjunction with the Program under their own license
+ agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents" mean patent claims licensable by a Contributor which are
+necessarily infringed by the use or sale of its Contribution alone or when
+combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement,
+including all Contributors.
+
+2. GRANT OF RIGHTS
+ a) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free copyright license to
+ reproduce, prepare derivative works of, publicly display, publicly perform,
+ distribute and sublicense the Contribution of such Contributor, if any, and
+ such derivative works, in source code and object code form.
+ b) Subject to the terms of this Agreement, each Contributor hereby grants
+ Recipient a non-exclusive, worldwide, royalty-free patent license under
+ Licensed Patents to make, use, sell, offer to sell, import and otherwise
+ transfer the Contribution of such Contributor, if any, in source code and
+ object code form. This patent license shall apply to the combination of the
+ Contribution and the Program if, at the time the Contribution is added by
+ the Contributor, such addition of the Contribution causes such combination
+ to be covered by the Licensed Patents. The patent license shall not apply
+ to any other combinations which include the Contribution. No hardware per
+ se is licensed hereunder.
+ c) Recipient understands that although each Contributor grants the licenses to
+ its Contributions set forth herein, no assurances are provided by any
+ Contributor that the Program does not infringe the patent or other
+ intellectual property rights of any other entity. Each Contributor
+ disclaims any liability to Recipient for claims brought by any other entity
+ based on infringement of intellectual property rights or otherwise. As a
+ condition to exercising the rights and licenses granted hereunder, each
+ Recipient hereby assumes sole responsibility to secure any other
+ intellectual property rights needed, if any. For example, if a third party
+ patent license is required to allow Recipient to distribute the Program, it
+ is Recipient's responsibility to acquire that license before distributing
+ the Program.
+ d) Each Contributor represents that to its knowledge it has sufficient
+ copyright rights in its Contribution, if any, to grant the copyright
+ license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its
+own license agreement, provided that:
+
+ a) it complies with the terms and conditions of this Agreement; and
+ b) its license agreement:
+ i) effectively disclaims on behalf of all Contributors all warranties and
+ conditions, express and implied, including warranties or conditions of
+ title and non-infringement, and implied warranties or conditions of
+ merchantability and fitness for a particular purpose;
+ ii) effectively excludes on behalf of all Contributors all liability for
+ damages, including direct, indirect, special, incidental and
+ consequential damages, such as lost profits;
+ iii) states that any provisions which differ from this Agreement are offered
+ by that Contributor alone and not by any other party; and
+ iv) states that source code for the Program is available from such
+ Contributor, and informs licensees how to obtain it in a reasonable
+ manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+ a) it must be made available under this Agreement; and
+ b) a copy of this Agreement must be included with each copy of the Program.
+ Contributors may not remove or alter any copyright notices contained within
+ the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if
+any, in a manner that reasonably allows subsequent Recipients to identify the
+originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with
+respect to end users, business partners and the like. While this license is
+intended to facilitate the commercial use of the Program, the Contributor who
+includes the Program in a commercial product offering should do so in a manner
+which does not create potential liability for other Contributors. Therefore, if
+a Contributor includes the Program in a commercial product offering, such
+Contributor ("Commercial Contributor") hereby agrees to defend and indemnify
+every other Contributor ("Indemnified Contributor") against any losses, damages
+and costs (collectively "Losses") arising from claims, lawsuits and other legal
+actions brought by a third party against the Indemnified Contributor to the
+extent caused by the acts or omissions of such Commercial Contributor in
+connection with its distribution of the Program in a commercial product
+offering. The obligations in this section do not apply to any claims or Losses
+relating to any actual or alleged intellectual property infringement. In order
+to qualify, an Indemnified Contributor must: a) promptly notify the Commercial
+Contributor in writing of such claim, and b) allow the Commercial Contributor to
+control, and cooperate with the Commercial Contributor in, the defense and any
+related settlement negotiations. The Indemnified Contributor may participate in
+any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product
+offering, Product X. That Contributor is then a Commercial Contributor. If that
+Commercial Contributor then makes performance claims, or offers warranties
+related to Product X, those performance claims and warranties are such
+Commercial Contributor's responsibility alone. Under this section, the
+Commercial Contributor would have to defend claims against the other
+Contributors related to those performance claims and warranties, and if a court
+requires any other Contributor to pay any damages as a result, the Commercial
+Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
+IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE,
+NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each
+Recipient is solely responsible for determining the appropriateness of using and
+distributing the Program and assumes all risks associated with its exercise of
+rights under this Agreement , including but not limited to the risks and costs
+of program errors, compliance with applicable laws, damage to or loss of data,
+programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY
+CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
+PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS
+GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable
+law, it shall not affect the validity or enforceability of the remainder of the
+terms of this Agreement, and without further action by the parties hereto, such
+provision shall be reformed to the minimum extent necessary to make such
+provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a
+cross-claim or counterclaim in a lawsuit) alleging that the Program itself
+(excluding combinations of the Program with other software or hardware)
+infringes such Recipient's patent(s), then such Recipient's rights granted under
+Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to
+comply with any of the material terms or conditions of this Agreement and does
+not cure such failure in a reasonable period of time after becoming aware of
+such noncompliance. If all Recipient's rights under this Agreement terminate,
+Recipient agrees to cease use and distribution of the Program as soon as
+reasonably practicable. However, Recipient's obligations under this Agreement
+and any licenses granted by Recipient relating to the Program shall continue and
+survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in
+order to avoid inconsistency the Agreement is copyrighted and may only be
+modified in the following manner. The Agreement Steward reserves the right to
+publish new versions (including revisions) of this Agreement from time to time.
+No one other than the Agreement Steward has the right to modify this Agreement.
+The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation
+may assign the responsibility to serve as the Agreement Steward to a suitable
+separate entity. Each new version of the Agreement will be given a
+distinguishing version number. The Program (including Contributions) may always
+be distributed subject to the version of the Agreement under which it was
+received. In addition, after a new version of the Agreement is published,
+Contributor may elect to distribute the Program (including its Contributions)
+under the new version. Except as expressly stated in Sections 2(a) and 2(b)
+above, Recipient receives no rights or licenses to the intellectual property of
+any Contributor under this Agreement, whether expressly, by implication,
+estoppel or otherwise. All rights in the Program not expressly granted under
+this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the
+intellectual property laws of the United States of America. No party to this
+Agreement will bring a legal action under this Agreement more than one year
+after the cause of action arose. Each party waives its rights to a jury trial in
+any resulting litigation.
diff --git a/api/swagger/swagger.yaml b/api/swagger/swagger.yaml
new file mode 100644
index 0000000..c506da6
--- /dev/null
+++ b/api/swagger/swagger.yaml
@@ -0,0 +1,13 @@
+swagger: "2.0"
+info:
+ version: "1.0.0"
+ title: eLogbook API
+host: localhost:3000
+basePath: /
+schemes:
+ - http
+consumes:
+ - application/json
+produces:
+ - application/json
+paths:
\ No newline at end of file
diff --git a/deploy/conf/context.xml b/deploy/conf/context.xml
new file mode 100644
index 0000000..eff12ed
--- /dev/null
+++ b/deploy/conf/context.xml
@@ -0,0 +1,43 @@
+<?xml version='1.0' encoding='utf-8'?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You 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.
+-->
+<!-- The contents of this file will be loaded for each web application -->
+
+
+<!-- jdbc:oracle:thin:@entbwora1:1521:dboetng4 -->
+<Context>
+
+ <!-- Default set of monitored resources -->
+ <WatchedResource>WEB-INF/web.xml</WatchedResource>
+
+ <!-- Uncomment this to disable session persistence across Tomcat restarts -->
+
+ <!--Manager pathname=""/>
+
+
+ <Parameter name="environment" override="false" value="Development"/-->
+
+ <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="DevLocal"/>
+
+
+ <!-- Uncomment this to enable Comet connection tacking (provides events
+ on session expiration as well as webapp lifecycle) -->
+ <!--
+ <Valve className="org.apache.catalina.valves.CometConnectionManagerValve" />
+ -->
+
+</Context>
diff --git a/deploy/get_started.txt b/deploy/get_started.txt
new file mode 100644
index 0000000..51ff81f
--- /dev/null
+++ b/deploy/get_started.txt
@@ -0,0 +1,92 @@
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+GET STARTED
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+
+---------------- REQUIREMENTS -------------
+Java 1.8
+Apache Maven 3.5.0
+
+IF you have this versions, check if you have set JAVA_HOME and M2_HOME.
+ - If yes ignore step 1 and 2
+ - If no follow the corresponding steps below
+
+-------------------- 1 ---------------------
+Install java 8
+
+- Open a cmd and check your java version
+ $ java -version
+- If you dont have java version 1.8 then download and install it from:
+ http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
+- Set JAVA_HOME (Windows OS):
+ Right click on This Computer and select Properties.
+ On the Advanced tab, select Environment Variables, and then edit JAVA_HOME to point to where the JDK software is located, for example, C:\Program Files\Java\jdk1.8.xxx.
+ Also, edit The Path variable in System variables and add the bin path (C:\Program Files\Java\jdk1.8.xxx\bin)
+- Restart your PC
+- Confirm by checking the version
+ $ java -version
+
+
+-------------------- 2 ---------------------
+Install Apache Maven to your pc
+
+Maven is a tool that can be used for building and managing any Java-based project.
+
+- Download maven 3.5.0 from
+ https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.0/
+- Extract the folder and place it on your C drive
+- Set M2_HOME (Windows OS):
+ - Right click on This Computer and select Properties.
+ - On the Advanced tab, select Environment Variables, and then create M2_HOME to point to where the Maven software is located, for example, C:\apache-maven-3.5.0.
+ - Also edit The Path variable in System variables and add the bin path (C:\apache-maven-3.5.0\bin)
+- Restart your PC
+- Confirm with
+ $ mvn -v
+
+-------------------- 3 ---------------------
+To get started with the project you have to clone all four(elogbook and portal backend-frontend ) projects.
+
+- Create a folder and do following for each of them
+- Open a cmd and navigate to the folder
+- Use the command to create a clone of each project
+ § git clone <project_url>
+- If you are going to develop, important is a switch to the develop branch
+ - navigate in the folder with the clone and switch to develop branch
+ $ git checkout <branch>
+- At the end just pull the actual version of the code
+ $ git pull origin <branch>
+
+
+--------------------------
+Active Develop Branches: |
+Backend -> DEVELOP_BE |
+Frontend -> DEVELOP_FE |
+-------------------------|
+Stable Branches: master |
+--------------------------
+
+
+-------------------- 4 ---------------------
+Build the maven project
+
+Building the maven project, will produce a <project_name>.war file(Web Application Archive), which is needed to run the project.
+- Open a command line and navigate to the root folder of the backend project
+- Use the following call to cleanly build and install artifacts into the local repository:
+ $ mvn clean install
+
+-------------------- 5 ---------------------
+Open and familiarize yourself with the project
+
+- If you successfully build the maven project you can find in /target/generated-docs all the documentations of this projects
+ - auth_n_auth_howtoBuild -> here you can read how to build the whole (backend and frontend) project
+ - auth_n_auth_howtoRun -> here you can read how to run the Application
+ - auth_n_auth_architectureDocumentation -> here you can read about the architecture documetation this module
+ - auth_n_auth_interfaceDocumentation -> here you can read about the backend REST Services which are used
+
+- Other useful files:
+ - /target/site/jacoco/index.html -> jacoco code coverage review
+ - /target/surefire-reports -> test reports
+
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+NEXT STEP -> READ THE auth_n_auth_howtoBuild FILE !
+!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
\ No newline at end of file
diff --git a/deploy/lib/postgresql-42.0.0.jar b/deploy/lib/postgresql-42.0.0.jar
new file mode 100644
index 0000000..b89509b
--- /dev/null
+++ b/deploy/lib/postgresql-42.0.0.jar
Binary files differ
diff --git a/doc/build.txt b/doc/build.txt
new file mode 100644
index 0000000..737e8a3
--- /dev/null
+++ b/doc/build.txt
@@ -0,0 +1,23 @@
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+Backend:
+>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+
+Voraussetzungen:
+----------------
+Java 1.8 JDK
+Maven
+
+Bauen:
+------
+Im Rootpath des Backend-Projektes:
+>mvn clean install
+
+(Erzeugt in Target das WAR, die surefire-reports und das jacoco.exec für die Codecoverage-Analyse)
+Im Sonarqube schließen wir folgende Files von der CodeCoverageAnalyse aus:
+
+
+**/de/pta/openkonsequenz/betriebstagebuch/common/Globals.java
+**/rest/*.java
+**/LoggerUtil.java
+**/dao/*.java
+**/dao/interfaces/*.java
diff --git a/doc/doc_eLogbook_Rest.docx b/doc/doc_eLogbook_Rest.docx
new file mode 100644
index 0000000..14201c8
--- /dev/null
+++ b/doc/doc_eLogbook_Rest.docx
Binary files differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..9c27fd5
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,298 @@
+<?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>openk.pta.de</groupId>
+ <artifactId>portal</artifactId>
+ <version>1.1.2</version>
+ <packaging>war</packaging>
+
+ <properties>
+ <skip.asciidoc>false</skip.asciidoc>
+ <httpclient.version>4.5.13</httpclient.version>
+ <gson.version>2.8.0</gson.version>
+ <log4j.version>1.2.17</log4j.version>
+ <commons-io.version>2.5</commons-io.version>
+ <junit.version>4.12</junit.version>
+ <easymock.version>3.4</easymock.version>
+ <powermock-api-easymock.version>2.0.9</powermock-api-easymock.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <servlet-api>2.5</servlet-api>
+ <maven.test.skip>false</maven.test.skip>
+ <jacoco-maven-plugin.version>0.8.6</jacoco-maven-plugin.version>
+ <sonar-maven-plugin.version>3.0.2</sonar-maven-plugin.version>
+ <dependency-check-maven.version>6.1.5</dependency-check-maven.version>
+ <keycloak.version>12.0.4</keycloak.version>
+ </properties>
+
+ <profiles>
+ <profile>
+ <id>local-fast-build</id>
+ <properties>
+ <skip.asciidoc>true</skip.asciidoc>
+ <maven.test.skip>false</maven.test.skip>
+ </properties>
+ </profile>
+ <profile>
+ <id>securitycheck</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.owasp</groupId>
+ <artifactId>dependency-check-maven</artifactId>
+ <version>${dependency-check-maven.version}</version>
+ <configuration>
+ <skipProvidedScope>true</skipProvidedScope>
+ <skipRuntimeScope>true</skipRuntimeScope>
+ <failBuildOnCVSS>7</failBuildOnCVSS>
+ <assemblyAnalyzerEnabled>false</assemblyAnalyzerEnabled>
+ <suppressionFiles>${basedir}/securitycheck/suppressed.xml</suppressionFiles>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>check</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.owasp</groupId>
+ <artifactId>dependency-check-maven</artifactId>
+ <version>${dependency-check-maven.version}</version>
+ <type>maven-plugin</type>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${httpclient.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.bundles</groupId>
+ <artifactId>jaxrs-ri</artifactId>
+ <version>2.22.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <!--<dependency>
+ <groupId>com.auth0</groupId>
+ <artifactId>java-jwt</artifactId>
+ <version>3.15.0</version>
+ </dependency>-->
+
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${gson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>${log4j.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.sun.jmx</groupId>
+ <artifactId>jmxri</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>com.sun.jdmk</groupId>
+ <artifactId>jmxtools</artifactId>
+ </exclusion>
+
+ <exclusion>
+ <groupId>javax.jms</groupId>
+ <artifactId>jms</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons-io.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>${easymock.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>${powermock-api-easymock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>${powermock-api-easymock.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco-maven-plugin.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <version>3.0.2</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.3.1</version>
+ <configuration>
+ <archive>
+ <manifest>
+ <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
+ <addDefaultSpecificationEntries>true</addDefaultSpecificationEntries>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-project-info-reports-plugin</artifactId>
+ <version>2.7</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>sonar-maven-plugin</artifactId>
+ <version>${sonar-maven-plugin.version}</version>
+ </plugin>
+
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco-maven-plugin.version}</version>
+ <configuration>
+ <skip>${maven.test.skip}</skip>
+ <output>file</output>
+ <append>true</append>
+ <excludes>
+ <exclude>**/Globals.*</exclude>
+ <exclude>**/dao/**/*Dao*.java</exclude>
+ <exclude>**/controller/BackendController.java</exclude>
+ </excludes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>jacoco-initialize</id>
+ <goals>
+ <goal>prepare-agent</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>jacoco-site</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>report</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+ <plugin>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctor-maven-plugin</artifactId>
+ <version>1.5.3</version>
+ <dependencies>
+ <dependency>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctorj-pdf</artifactId>
+ <version>1.5.0-alpha.11</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jruby</groupId>
+ <artifactId>jruby-complete</artifactId>
+ <version>1.7.21</version>
+ </dependency>
+ <dependency>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctorj</artifactId>
+ <version>1.5.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.asciidoctor</groupId>
+ <artifactId>asciidoctorj-diagram</artifactId>
+ <version>1.5.4.1</version>
+ </dependency>
+ </dependencies>
+ <configuration>
+ <sourceDirectory>src/main/asciidoc</sourceDirectory>
+ <requires>
+ <require>asciidoctor-diagram</require>
+ </requires>
+ <attributes>
+ <imagesoutdir>${project.build.directory}/generated-docs/images</imagesoutdir>
+ <imagesDir>${project.build.directory}/generated-docs/images</imagesDir>
+ </attributes>
+ </configuration>
+ <executions>
+ <execution>
+ <id>output-html</id>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>process-asciidoc</goal>
+ </goals>
+ <configuration>
+ <skip>${skip.asciidoc}</skip>
+ <imagesDir>${project.build.directory}/generated-docs/images</imagesDir>
+ <requires>
+ <require>asciidoctor-diagram</require>
+ </requires>
+ <sourceHighlighter>coderay</sourceHighlighter>
+ <backend>html</backend>
+ <doctype>book</doctype>
+ <imagesDir>./images</imagesDir>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/securitycheck/suppressed.xml b/securitycheck/suppressed.xml
new file mode 100644
index 0000000..7ddc0b5
--- /dev/null
+++ b/securitycheck/suppressed.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<suppressions xmlns="https://jeremylong.github.io/DependencyCheck/dependency-suppression.1.3.xsd">
+
+ <!-- log4j wird bei uns nur lokal genutzt ohne Netzwerkkommunikation. -->
+ <suppress>
+ <notes><![CDATA[
+ file name: log4j-1.2.16.jar
+ ]]></notes>
+ <packageUrl regex="true">^pkg:maven/log4j/log4j@.*$</packageUrl>
+ <vulnerabilityName>CVE-2019-17571</vulnerabilityName>
+ </suppress>
+
+ <!-- log4j wird bei uns nur lokal genutzt ohne Netzwerkkommunikation. -->
+ <suppress>
+ <notes><![CDATA[
+ file name: log4j-1.2.16.jar
+ ]]></notes>
+ <packageUrl regex="true">^pkg:maven/log4j/log4j@.*$</packageUrl>
+ <vulnerabilityName>CVE-2020-9488</vulnerabilityName>
+ </suppress>
+</suppressions>
\ No newline at end of file
diff --git a/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc b/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc
new file mode 100644
index 0000000..3281812
--- /dev/null
+++ b/src/main/asciidoc/architectureDocumentation/auth_n_auth_architectureDocumentation.adoc
@@ -0,0 +1,958 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+openKonsequenz - Architecture of the module "portal@openK"
+==========================================================
+:Author: Frank Dietrich
+:Email: frank.dietrich@pta.de
+:Date: 2017-09-18
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+This documentation bases on ARC42-Template (v7.0):
+
+*About arc42*
+
+arc42, the Template for documentation of software and system architecture.
+
+By Dr. Gernot Starke, Dr. Peter Hruschka and contributors.
+
+Template Revision: 7.0 EN (based on asciidoc), January 2017
+
+© We acknowledge that this document uses material from the arc 42 architecture template, http://www.arc42.de.
+Created by Dr. Peter Hruschka & Dr. Gernot Starke.
+
+<<<
+
+== Introduction and Goals
+
+=== Requirements Overview
+
+ [...]
+
+
+=== Quality Goals
+
+ [...]
+
+=== Stakeholders
+
+.Stakeholders
+[options="header,footer"]
+|=========================================================
+|Role/Name|Contact|Expectations
+|Product Owner (represents the Distribution System Operators)|Gordon Pickford, Oliver Tantu|The software must fulfil their functional and nonfunctional Requirements.
+|Module Developer|Michel Allessandrini, Jonas Tewolde, Frank Dietrich|All relevant business and technical information must be available for implementing the software.
+|External Reviewer (represents the AC/QC)|Martin Jung, Anja Berschneider|The software and the documentation is realized according the Quality and Architecture Handbook of openKONSEQUENZ.
+|System Integrator||A documentation for the integration of the module in the DSO specific environments must be available.
+|=========================================================
+
+== Architecture Constraints
+
+The main architecture constraints are:
+
+ [...]
+
+=== Technical Constraints
+
+The following technical constraints are given:
+
+.Technical Contraints
+[options="header,footer"]
+|========================================================
+|Component|Constraints
+|Basis components of the reference platform|
+- Application Server Tomcat
+- JPA EclipseLink
+- Database PostgreSQL
+
+|Enterprise Service Bus|
+* ESB Talend
+* Communication via RESTful Webservices
+
+|Programming Language Frontend
+a|* Angular
+* Bootstrap
+* jQuery
+* REST/JSON Interfaces
+
+|GUI design
+a|* According to oK-GUI-Styleguide
+
+|Java QA environment|Sonarqube 5.6.6
+
+|Programming Language
+a|* Backend: Java 1.8
+* Frontend: Angular 4.0.0 (Javascript, Typescript, HTML5, CSS3)
+
+|IDE
+a|* Not restricted (Eclipse, IntelliJ, Microsoft Developer Studio, Microsoft Visual Code ...)
+
+|Build system
+a|* Backend: Maven
+* Frontend: NodeJS + Angular/cli
+
+|Libraries, Frameworks,Components
+a|* Used Libraries/Frameworks have to be compatible to the Eclipse Public License
+|Architecture Documentation|* According ARC42-Template
+|========================================================
+
+
+=== Technical Dependencies
+
+The following libraries are used:
+
+.Libraries
+[options="header,footer"]
+|=========================================================
+|Name of the library|Version|Artefact-id|Usage|License|Tier
+|org.apache.httpcomponents.httpclient|4.5.3
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.3</version>
+</dependency>
+----
+|Backend, Http-Client|Apache 2.0|Backend
+
+|org.json.json|20160810
+
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ <version>20160810</version>
+</dependency>
+----
+|Backend - Json functionality|Json|Backend
+
+|org.jboss.resteasy.resteasy-jaxrs|3.0.21_Final
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>resteasy-jaxrs</artifactId>
+ <version>3.0.21.Final</version>
+</dependency>
+----
+|Backend - RestServer|Apache 2.0 / CC0.1.0/ Public|Backend
+
+|org.jboss.resteasy.jaxrs-api|3.0.12.Final
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.jboss.resteasy</groupId>
+ <artifactId>jaxrs-api</artifactId>
+ <version>3.0.12.Final</version>
+</dependency>
+----
+|Rest-Server|Apache 2.0|Backend
+
+|javax.servlet.servlet-api|3.0.1
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>3.0.1</version>
+</dependency>
+----
+|Backend - Logging Servlet |CDDL GLP 2.0|Backend
+
+|com.google.code.gson.gson|2.8.0
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>2.8.0</version>
+</dependency>
+----
+|Backend Json de-serialization|Apache 2.0|Backend
+
+|log4j.log4j|1.2.17
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <version>1.2.17</version>
+</dependency>
+----
+|Backend logging|Apache 2.0|Backend
+
+|commons-io|2.5
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.5</version>
+</dependency>
+----
+|IO utils|Apache 2.0| Backend
+
+|junit.junit|4.12
+
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+</dependency>
+----
+|Unit testing|EPL 1.0|Backend
+
+|org.easymock.easymock|3.4
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <version>3.4</version>
+</dependency>
+----
+|Unit testing|Apache 2.0|Backend
+
+|org.powermock.powermock-api-easymock|1.6.6
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-easymock</artifactId>
+ <version>1.6.6</version>
+</dependency>
+----
+|Unit testing|Apache 2.0|Backend
+
+|org.jacoco.jacoco-maven-plugin|0.7.9
+a|
+[source,xml]
+----
+<dependency>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>0.7.9</version>
+</dependency>
+----
+|Test coverage|EPL 1.0|Backend
+
+|=========================================================
+
+== System Scope and Context
+
+=== Business Context
+
+ [...]
+
+=== Technical Context
+
+ [...]
+
+=== Solution Strategy
+
+<TODO>
+
+== Building Block View
+
+=== Whitebox Overall System
+
+The module Auth&Auth consists of the following components:
+
+.Module components
+[plantuml]
+....
+interface authAndAuthAPI
+
+node AuthAndAuthEnvironment {
+
+ component portalBE [
+ portalBackend
+ ]
+
+ component portalFE [
+ portalFrontend
+ ]
+
+ component keycloak [
+ KeyCloak
+ ]
+
+ portalFE-(0-portalBE
+ portalBE-(0-keycloak
+}
+
+node openKModule [
+ openKonsequenz module
+]
+
+
+portalBE #--authAndAuthAPI
+openKModule->authAndAuthAPI
+
+....
+
+
+. *portalFrontend* - The user interface of the portal. Consists of the login page and the module overview grid
+. *portalBackend* - Provides the services for its frontend.
+. *authAndAuthAPI* - Additionally the portalBackend provides general user and security services for
+for all openKonsequenz-Modules.
+. *KeyCloak* - KeyCloak implements most of the security aspects for the portal application and the modules.
+It provides an userinterface for user and role management of the modules and generates the JSON Web Token (JWT)
+for the session and access control.
+
+
+
+==== Auth&Auth-API
+
+The Auth&Auth needs information from the system Keycloak. Therefore, it must provide an interface for receiving the according data, see figure 1.
+
+=== Level 2
+
+==== portalFE – SPA (Frontend tier)
+
+
+The frontend component implements the concept of a single-page application (SPA). The framework used is Angular2. It divides the portalFE into three layers:
+
+
+1.Components - The components (Pages, Lists, Dialogs, Common Comp.) represent the presentation layer and the control layer. A component contains the control logic (.ts-file), an HTML-fragment as presentation description (.html-file) and a style definition (.css-file).
+
+
+2.Services - The service component communicates with the interfaces of the backend via HTTP requests by using the model component.
+
+
+3.Model - The model corresponds to the View-Model of the backend tier.
+
+.Frontend tier
+[plantuml]
+....
+
+node Backend-portalBE {
+
+ component RESTServices
+ component ViewModel
+}
+
+RESTServices.>ViewModel
+
+node Frontend-portalFE {
+
+ component services
+
+ node Components {
+ component pages
+ component commonComp
+ component dialogs
+
+ }
+ component model
+
+
+}
+
+services-(0-RESTServices
+model<->ViewModel
+services.>model
+Components.>services
+
+....
+
+
+
+==== portal.war (Backend tier)
+
+The backend tier contains five components which can be summarized in three layers:
+
+. *Presentation layer* - Represented by
+ .. REST-Srv
+ .. View Model
+. *Controller layer* - Represented by
+ .. Controller
+. *Model layer* - Represented by
+ .. auth2 (Connection to "KeyCloak")
+
+
+.Backend tier
+[plantuml]
+....
+
+node PortalFrontend [
+ PortalFrontend
+]
+
+node ESB {
+ interface Auth_n_auth
+}
+
+
+node BackendLAN {
+ left to right direction
+
+ node KeyCloak {
+ component KeyCloakImplementation
+ }
+
+ node Backend-Portal {
+
+ skinparam rectangle {
+ roundCorner 25
+ }
+ rectangle "Presentation layer" {
+ component RESTServices
+ component ViewModel
+ }
+ rectangle "Controller layer" {
+ component Controller
+ }
+ rectangle "Model layer" {
+ component auth2
+ }
+
+ RESTServices.>Controller
+ RESTServices.>ViewModel
+ Controller.>auth2
+
+ }
+
+ RESTServices -- Auth_n_auth
+
+
+
+ interface OAuth2
+ interface KeyCloakAdmin
+
+ KeyCloak -- KeyCloakAdmin
+ KeyCloak -- OAuth2
+
+
+ auth2 -> OAuth2
+ auth2 -> KeyCloakAdmin
+
+}
+
+
+
+
+PortalFrontend-->Auth_n_auth
+
+
+node openKModule [
+ openKModule
+]
+
+
+openKModule --> Auth_n_auth
+
+....
+
+KeyCloak provides different interfaces. The backend uses the *OAuth2*-Interface for authentication
+and the *KeyCloak-admin* interface for other tasks (for example for getting users). The component *auth2* provides
+functionality for the access to KeyCloak. The Presentation layer consists of the *RESTServices* and the
+*ViewModel*. The *RESTServices* access the *Controller layer* in order to perform their tasks.
+
+The whole backend provides the *Auth&Auth* interface which is used by the *portalFrontend* and
+other *openKonsequenz-Modules* for authentication and other related tasks. The *Auth&Auth* interface is
+to be exported via ESB.
+
+
+
+== Runtime View
+=== Login / Authentication
+
+.Login sequence
+[plantuml]
+....
+actor User
+participant PortalFrontend
+participant PortalBackend
+participant KeyCloak
+
+User->PortalFrontend: Login page
+PortalFrontend->PortalBackend: /login(loginCredentials)
+PortalBackend->KeyCloak: /.../realms/.../protocol/openid-connect/token(?loginInfo)
+KeyCloak --> PortalBackend: return JWT
+PortalBackend -> PortalBackend: Create Session with JWT
+PortalBackend --> PortalFrontend: return JWT
+PortalFrontend -> PortalFrontend: store JWT
+PortalFrontend --> User: Navigate to ModuleGrid
+
+....
+
+=== Logout
+
+.Logout sequence
+[plantuml]
+....
+actor User
+participant oK_Module
+participant PortalBackend
+
+
+User->oK_Module: logout
+oK_Module->PortalBackend: /logout with JWT
+PortalBackend->PortalBackend: Remove Session with JWT
+PortalBackend-->oK_Module:
+oK_Module->oK_Module: Navigate to Logout/closing page
+oK_Module-->User
+
+....
+
+=== Check authorization
+
+.CheckAuth sequence
+[plantuml]
+....
+actor User
+participant oK_Module
+participant PortalBackend
+
+
+User->oK_Module: Any action that requires an auth check
+oK_Module->PortalBackend: /checkAuth with JWT
+
+group authorize
+ PortalBackend->PortalBackend: Check if valid session with JWT exists
+
+ group check failed
+ PortalBackend-->oK_Module: raise HttpCode "Unauthorized 401"
+ end
+
+ group check succeeded
+ PortalBackend-->oK_Module: return HttpCode "Success 200"
+ end
+end
+
+oK_Module->oK_Module: react on HttpCode
+oK_Module-->User:
+
+....
+
+=== Get users for role
+.GetUsersForRole sequence
+[plantuml]
+....
+actor User
+
+participant oK_Module
+participant KeyCloak
+participant PortalBackend
+
+actor Timer_cycl
+
+group refresh usersWithRoles cache
+ Timer_cycl->PortalBackend: Get userWithRoles
+
+ PortalBackend->KeyCloak: Login with admin user
+ KeyCloak-->PortalBackend
+ PortalBackend->KeyCloak: Get realm users
+ KeyCloak-->PortalBackend
+
+ group repeat for each user
+ PortalBackend->KeyCloak:Get role-mapping for user
+ KeyCloak-->PortalBackend
+ end
+ PortalBackend->PortalBackend: update cache
+ PortalBackend-->Timer_cycl
+end
+...
+
+
+User->oK_Module: Any action that needs all users having a role
+oK_Module->PortalBackend: /usersForRole/{userRole}
+PortalBackend->PortalBackend: evaluate from usersWithRoles cache
+PortalBackend-->oK_Module: return result
+oK_Module-->User
+
+....
+
+
+
+=== Open module in portal frontend
+.Start module sequence
+[plantuml]
+....
+actor User
+
+participant PortalFE
+participant openKModule
+
+User->PortalFE: User (logged in) opens module
+PortalFE->openKModule: Open configured URL in new browser tab, providing the JWT
+....
+
+
+
+== Deployment View
+
+The Auth&Auth application consists of 3 parts regarding the deployment.
+
+. Frontend: "portalFE"-Directory
+. Backend: "portal.war"
+. Keycloak: OAuth2 and JWT Service implementation
+
+=== Deployment of the application components
+
+==== Deployment of the frontend
+
+The Frontend SPA is built as a folder, that contains all the required files for
+the application. When deploying the frontend application, the content of the "dist"-folder
+within the Frontend development-directory has to be copied into the
+target-directory of the apache-tomcat:
+
+ <Apache-Tomcat>/webapps/portalFE
+
+If the target folder does not exist, it has to be created manually.
+
+==== Deployment of the backend
+The backend REST-services are built in form of a "WAR"-file (to be found
+in the "target"-directory of the MAVEN-directory structure).
+For deployment, this file has to be copied to the directory
+
+ <Apache-Tomcat>/webapps
+
+==== Deployment of Keycloak
+
+
+. Get "Keycloak 3.2.1 Final" ("keycloak-3.2.1.Final.zip") from the Keycloak download page. +
+Download "Server Standalone server distribution": http://www.keycloak.org/archive/downloads-3.2.1.html
+
+. Extract the content.
+. To create an initial admin account for Keycloak run the script `add-user-keycloak.sh` with username 'admin'
+and a strong password.
+
+ <Keycloak-Directory>/bin/add-user-keycloak.sh -r master -u <username> -p <password>
+
+. To start Keycloak create a *Linux-Service which executes* the `standalone.sh` script to be found in the Keycloak `bin`
+directory.
+
+ <Keycloak-Directory>/bin/standalone.sh
+
+
+TIP: Keycloaks default port is 8080 you can change it to for example to port 1234 with the following
+execution parameter: -Djboss.http.port=1234
+
+ <Keycloak-Directory>/bin/standalone.sh -Djboss.http.port=1234
+
+==== Configuration of the system
+
+===== Configuration of the webserver
+
+There exists the file *context.xml* in the "conf" subdirectory (*<TOMCAT>/conf*) of the target apache tomcat installation.
+Add the following parameter and resource in order to access the correct backend configurations and to
+gain access to the database (see "Configuration of the backend" below):
+
+.context.xml
+[source,xml]
+----
+[...]
+ <!-- Uncomment this to disable session persistence across Tomcat restarts -->
+
+ <!--Manager pathname=""/>
+
+
+ <Parameter name="environment" override="false" value="Development"/-->
+
+ <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="Production"/>
+
+ <!-- Uncomment this to enable Comet connection tacking (provides events
+ on session expiration as well as webapp lifecycle) -->
+[...]
+----
+
+
+===== Configuration of the backend
+
+After the backend war file has been deployed and unpacked inside of the *<TOMCAT>/webapps* folder there are different
+ backend config files to be found in the folder *<TOMCAT>/webapps/elogbook/WEB-INF/classes*
+
+* backendConfig*.json
+* moduleConfig*.json
+
+The active configuration is chosen by parameter *OK_PORTAL_ENVIRONMENT* (see context.xml above).
+Possible values are:
+
+* *Custom* (for backendConfigCustom.json and moduleConfigCustom.json)
+* *DevLocal* (for backendConfigDevLocal.json and moduleConfigDevLocal.json)
+* *DevServer* (for backendConfigDevServer.json and moduleConfigDevServer.json)
+* *Production* (for backendConfigProduction.json and moduleConfigProduction.json)
+
+After choosing an environment the corresponding json files have to be configured:
+
+.backendConfigXXX.json
+[source,json]
+----
+{
+ "internalSessionLengthMillis": 46800000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://localhost:8080/",
+ "keycloakRealm": "OpenKRealm",
+ "keycloakClient": "OpenKClient",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "adminpwd",
+ "maxLoadUsers": 1000
+}
+----
+* *internalSessionLengthMillis* - Maximum allowed duration of inactivity, before a session ends
+* *reloadUsersInSec* - Polling interval for getting all users from keycloak
+* *authServerUrl* - Base url of the keycloak instance
+* *keycloakRealm* - Configured realm on keycloak
+* *keycloakClient* - Configured client on keycloak
+* *keycloakAdmin* - user for admin access on keycloak
+* *keycloakPW* - password of the admin user
+* *maxLoadUsers* - Sets the maximum of users that are loaded from keycloak. KC itself is limited here. The value
+should be set to the amount of *all* users in the target "keycloakRealm".
+
+
+.moduleConfigXXX.json
+[source,json]
+----
+[
+ {
+ "name": "Betriebstagebuch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://172.18.22.160:8880/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/.../m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/..../94-bereitschaftsplan",
+ "pictureLink": "https://www.openkonsequenz.de/medien/.../l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+
+ ...
+
+]
+
+----
+
+* *name* - Name/description of the module
+* *cols* - always "1"
+* *rows* - always "1"
+* *color* - always "#ffffff"
+* *link* - URL for the module
+* *pictureLink* - URL for picture belonging to the module
+* *requiredRole* - Name of the role (on keycloak) the user must have to access the module
+
+
+===== Configuration of Keycloak
+
+. Login in Keycloak
+
+.. Go to http://<KEYCLOAK-SERVER-IP>:<CONFIGURED-KEYCLOAK-PORT>/ +
+Hit the `Administration Console` -Link and login with admin account created during the Keycloak-deployment
+(see above).
+
+. Add a new realm: `MainDonauNetz`
+
+.Add a new realm overview
+[options="header,footer"]
+image::newRealm1.png[new Realm]
+
+.Add a new realm
+[options="header,footer"]
+image::newRealm2.png[new Realm]
+
+[start=3]
+. Create a client with client ID `elogbook-backend`.
+
+.Create a client overview
+[options="header,footer"]
+image::createClient.png[create Client]
+
+.Add a client
+[options="header,footer"]
+image::addClient.png[add Client]
+
+[start=4]
+. Set the client settings accordingly:
+
+.Client settings of elogbook-backend
+[options="header,footer"]
+image::clientSettings.png[Client settings]
+
+Go to tab `Mappers`. Press `Create`...
+
+.Mappers of elogbook-backend
+[option="header,footer"]
+image::CreateMapper.png[Mapper settings]
+
+and add the `role` mapping accordingly:
+
+.Role mapper
+[option="header,footer"]
+image::CreateRoleMapper.png[Role mapper settings]
+
+
+[start=5]
+. Add the roles under `Roles` press `Add Role`. Add the following Roles:
+- elogbook-normaluser
+- elogbook-superuser
+- elogbook-access
+- planning-access
+- feedin-management-access
+- planned-policies-access
+- planned-policies-normaluser
+- planned-policies-superuser
+
+. Configuring a superuser role. Under Roles, hit on a superuser(elogbook-superuser or planned-policies-superuser) or press `Edit`
+.. Switch `Composite Roles` to on.
+.. Add the Realm Role 'elogbook-normaluser' or 'planned-policies-normaluser' correspondingly from the `Available Roles`
+.. Select from the `Client Roles` Dropdown-List 'realm-management' and add the role 'view-users'.
+
+.Elogbook superuser composite role
+[options="header,footer"]
+image::rolesSuperUser.png[Elogbook superuser composite role]
+
+[start=7]
+. Adding users under `Users` press `Add User`.
+
+.Add a user
+[options="header,footer"]
+image::addingUsers.png[Add a User]
+
+.. Fill in username, First Name, Last Name, else is default and save it.
+.. Go to the `Credentials` tab and type in a new password and the confirmation as well, disable `Temporary`. Press `Reset Password`.
+Press `Change Password`.
+
+.Credentials tab
+[options="header,footer"]
+image::credentials.png[Credentials tab]
+
+[start=3]
+.. Go to the `Role Mappings` tab. +
+Here you grant rights/roles to the users:
+Select the from the previously created roles in `Available Roles` and hit `Add selected`. +
+... User right in the distinct modul elogbook (`elogbook-access` required of course):
+- elogbook-normaluser = standard user in the elogbook-app
+- elogbook-superuser = admin user in the elogbook-app
+
+... User right in the distinct modul Planned Grid Measures (`planned-policies-access` required of course):
+- planned-policies-normaluser = standard user in the plannedGridMeasures-app
+- planned-policies-superuser = admin user in the plannedGridMeasures-app
+
+... Access rights to the specific modul:
+- elogbook-access
+- planning-access
+- feedin-management-access
+- planned-policies-access
+
+.Role Mappings tab
+[options="header,footer"]
+image::roleMappings.png[Role Mapping]
+
+
+[start=4]
+.. Go back to the `Details` tab and make sure `Recquired User Actions` is empty. Delete anything which is in there with a press on the little cross.
+
+[start=8]
+. Add an admin user. (Mandatory) +
+Same procedure like adding a User (see 7.) but with the role 'elogbook-superuser' or 'planned-policies-superuser' instead of
+'elogbook-normaluser' or 'planned-policies-normaluser' correspondingly.
+
+IMPORTANT: We use this admin account (username & password) also to configure the backend. +
+See "Configuration of the backend",
+username & password from here is keycloakAdmin & keycloakPW there.
+
+
+
+=== CI- and CD-Components
+
+==== GIT-Repository
+
+<TODO>
+
+==== Hudson
+
+<TODO>
+
+==== Sonar
+
+<TODO>
+
+==== Code-Coverage of the Frontend - Karma-Istanbul-Output
+
+<TODO>
+
+=== Continuous Deployment
+
+
+
+== Design Decisions
+
+All architecture decisions based on the Architecture Committee Handbook. There are no deviations.
+
+
+== Quality Requirements
+
+TODO: Muss noch beschrieben werden
+
+=== Quality Tree
+
+TODO: Muss noch beschrieben werden
+
+=== Quality Scenarios
+
+TODO: Muss noch beschrieben werden
+
+
+
+== Risks and Technical Debts
+
+(Muss noch beschrieben werden)
+
+<<<
+
+== Glossary
+
+=== Technical Constraints
+
+.Technical Contraints
+[options="header,footer"]
+|========================================================
+|Short|Long|German|Description
+|AC|Architecture Committee|Architektur-Komittee|Gives Framework and Constraints according to architecture for oK projects.
+|CNCU|Central Network Control Unit||
+|DAO|Data Access Objects||
+|DSO|Distribution System Operator|Verteilnetz-betreiber (VNB)|Manages the distribution network for energy, gas or water.
+|EPL|Eclipse Public License||Underlying license model for Eclipse projects like elogbook@openK
+|ESB|Enterprise Service Bus||Central instance for exchange of data to overcome point-to-point connections.
+|oK|openKONSEQUENZ|openKONSEQUENZ|Name of the consortium of DSOs
+|QC|Quality Committee|Qualitätskomitee|Gives framework and constraints according to quality for oK projects.
+|SCADA|Supervisory Control and Data Acquisition|Netzleitsystem|System, that allows DSOs view/control actual parameters of their power grid.
+|========================================================
+
+
+
diff --git a/src/main/asciidoc/howto/auth_n_auth_howtoBuild.adoc b/src/main/asciidoc/howto/auth_n_auth_howtoBuild.adoc
new file mode 100644
index 0000000..f71a473
--- /dev/null
+++ b/src/main/asciidoc/howto/auth_n_auth_howtoBuild.adoc
@@ -0,0 +1,97 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+= openKonsequenz - How to build the module "portal@openK"
+:Date: 2017-11-17
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+<<<
+
+== Requirements
+* Apache Tomcat 8.0.30
+* Node.js 6.10.0
+* Angular-CLI
+* Graphviz
+
+== How to build the Backend
+To build the backend you need to have installed Apache Maven and Java (look at `/deploy/`*get_started.txt*).
+
+=== Install and Configure Apache Tomcat
+Tomcat is an open-source Java Servlet Container and provides a "pure Java" HTTP web server environment in which Java code can run.
+
+* Download Tomcat version 8.0.30 from https://archive.apache.org/dist/tomcat/tomcat-8/v8.0.30/bin/
+and extract it (apache-tomcat-8-0-30.zip).
+* Place the extracted folder on your C drive.
+* Configure Tomcat:
+** Configure the *context.xml* file. Copy the *<Parameter … >* block from the project file `deploy/conf/`*context.xml*
+and paste it in the `<tomcat>/conf/`*context.xml* in the *<Context>* block.
+** Or just paste this line there:
+
+ <Parameter name="OK_PORTAL_ENVIRONMENT" override="false" value="DevLocal"/>
+
+** Dont forget to save it.
+
+TIP: For more informations check *Deployment View* in Chapter *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_architectureDocumentation.html[auth_n_auth_architectureDocumentation]*.
+
+
+=== Install Graphviz
+Graphviz is open source graph visualization software. You need this software because of auto-generated graphics in the documentations.
+
+* Download and install Graphviz from http://www.graphviz.org/Download_windows.php
+* If not, set the PATH variable
+
+ Name of variable: GRAPHVIZ_DOT
+ Value of variable: <GRAPHVIZ_DIR>\bin\dot.exe
+
+
+== How to build the Frontend
+
+=== Install Node.js
+
+Node.js is an open-source, cross-platform JavaScript run-time environment for executing JavaScript (also Typescript which is a strongly typed form of JavaScript) code server-side.
+
+* Download Node.js 6.10.0 from https://nodejs.org/download/release/v6.10.0/ by clicking on a xxx.msi image for windows.
+* Run the downloaded Node.js .msi Installer - including accepting the license, selecting the destination, and authenticating for the install.
+This requires Administrator privileges, and you may need to authenticate
+* To ensure Node.js has been installed, run the following in your terminal - you should get something like v6.10.0
+
+[source,command]
+----
+ $ node -v
+----
+{blank}
+
+=== Update the npm Angular-CLI client
+This package manager comes bundled with Node.js and its good to have the latest version.
+
+* Open a command line and navigate to the root folder of the frontend project
+* Run the following commands (the version is defined in the package.json file):
+
+[source,command]
+----
+ $ npm install --save-dev @angular/cli
+----
+{blank}
+
+[source,command]
+----
+ $ npm install
+----
+{blank}
+
+TIP: Next Step -> Read the *auth_n_auth_howtoRun* file!
+
+
+
+
diff --git a/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc b/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc
new file mode 100644
index 0000000..bddebfc
--- /dev/null
+++ b/src/main/asciidoc/howto/auth_n_auth_howtoRun.adoc
@@ -0,0 +1,81 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+= openKonsequenz - How to run the module "portal@openK"
+:Date: 2017-11-17
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+<<<
+
+== Requirements
+* Browser (Chrome or IE11 suggested)
+
+== Prerequisites
+
+* KeyCloak 3.2.1 Final (look at the *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_architectureDocumentation.html[auth_n_auth_architectureDocumentation]* in *Deployment View* Chapter for install instructions)
+
+IMPORTANT: KeyCloak must be installed for a successful login at the application!
+
+== How to run the Backend
+To run the backend you need to have installed and configured Apache Tomcat (look at *auth_n_auth_howtoBuild*).
+
+=== Set up and start Apache Tomcat
+Tomcat needs the Web Application Archive (war) file, which is produced by building the maven project, to run the application.
+
+* Copy the *portal.war* file from the project file `/target` in the `<tomcat>/webapps` file. If there is a folder named *portal*, delete it before.
+* Navigate to `C:\apache-tomcat-8.0.30\bin` and start Tomcat by clicking on *startup.bat*.
+* Tomcat's default port is *8080*.
+
+[source,text]
+----
+If 8080 port is already in use, you have to change tomcat's port as follows:
+- Go to <tomcat>/conf folder
+- Open server.xml file and search for "Connector port"
+- Replace "8080" by your port number (for example 8181)
+- Restart tomcat server (in the same folder which startup.bat is located, you can also find a shutdown.bat file).
+----
+{blank}
+
+IMPORTANT: If you change the port number you have also adapt the port in the
+frontend project: File "<PRJ_portalFE>/proxy.conf.json". There might be other config files
+that need to be adepted as well!
+
+TIP: Look at the *http://87.128.212.254:8880/portalFE_ADoc/auth_n_auth_interfaceDocumentation.html[auth_n_auth_interfaceDocumentation]* for informations about the services.
+
+== How to run the Frontend
+To run the frontend project you need to have installed and updated Node.js and npm Angular-CLI.
+
+=== Compile the Frontend
+
+To compile say Angular-CLI to start.
+
+* Open a command line and navigate to the root folder of the frontend project
+* Run the command
+
+[source,command]
+----
+ $ npm start
+----
+{blank}
+
+* Open a browser and type:
+
+[source,http]
+----
+ http://localhost:4201
+----
+{blank}
+
+IMPORTANT: To open the *Betriebstagebuch* module you have to run the *elogbook* application too.
+
diff --git a/src/main/asciidoc/images/CreateMapper.png b/src/main/asciidoc/images/CreateMapper.png
new file mode 100644
index 0000000..0c835cb
--- /dev/null
+++ b/src/main/asciidoc/images/CreateMapper.png
Binary files differ
diff --git a/src/main/asciidoc/images/CreateRoleMapper.png b/src/main/asciidoc/images/CreateRoleMapper.png
new file mode 100644
index 0000000..19e6ea0
--- /dev/null
+++ b/src/main/asciidoc/images/CreateRoleMapper.png
Binary files differ
diff --git a/src/main/asciidoc/images/FrontendTier.png b/src/main/asciidoc/images/FrontendTier.png
new file mode 100644
index 0000000..d820cc5
--- /dev/null
+++ b/src/main/asciidoc/images/FrontendTier.png
Binary files differ
diff --git a/src/main/asciidoc/images/addClient.png b/src/main/asciidoc/images/addClient.png
new file mode 100644
index 0000000..039414b
--- /dev/null
+++ b/src/main/asciidoc/images/addClient.png
Binary files differ
diff --git a/src/main/asciidoc/images/addingUsers.png b/src/main/asciidoc/images/addingUsers.png
new file mode 100644
index 0000000..5e3511c
--- /dev/null
+++ b/src/main/asciidoc/images/addingUsers.png
Binary files differ
diff --git a/src/main/asciidoc/images/clientSettings.png b/src/main/asciidoc/images/clientSettings.png
new file mode 100644
index 0000000..44f80ab
--- /dev/null
+++ b/src/main/asciidoc/images/clientSettings.png
Binary files differ
diff --git a/src/main/asciidoc/images/createClient.png b/src/main/asciidoc/images/createClient.png
new file mode 100644
index 0000000..ea86c6d
--- /dev/null
+++ b/src/main/asciidoc/images/createClient.png
Binary files differ
diff --git a/src/main/asciidoc/images/credentials.png b/src/main/asciidoc/images/credentials.png
new file mode 100644
index 0000000..b15c2f8
--- /dev/null
+++ b/src/main/asciidoc/images/credentials.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/caution.png b/src/main/asciidoc/images/icons/caution.png
new file mode 100644
index 0000000..9a8c515
--- /dev/null
+++ b/src/main/asciidoc/images/icons/caution.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/important.png b/src/main/asciidoc/images/icons/important.png
new file mode 100644
index 0000000..be685cc
--- /dev/null
+++ b/src/main/asciidoc/images/icons/important.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/note.png b/src/main/asciidoc/images/icons/note.png
new file mode 100644
index 0000000..7c1f3e2
--- /dev/null
+++ b/src/main/asciidoc/images/icons/note.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/tip.png b/src/main/asciidoc/images/icons/tip.png
new file mode 100644
index 0000000..f087c73
--- /dev/null
+++ b/src/main/asciidoc/images/icons/tip.png
Binary files differ
diff --git a/src/main/asciidoc/images/icons/warning.png b/src/main/asciidoc/images/icons/warning.png
new file mode 100644
index 0000000..d41edb9
--- /dev/null
+++ b/src/main/asciidoc/images/icons/warning.png
Binary files differ
diff --git a/src/main/asciidoc/images/newRealm1.png b/src/main/asciidoc/images/newRealm1.png
new file mode 100644
index 0000000..0c28a5e
--- /dev/null
+++ b/src/main/asciidoc/images/newRealm1.png
Binary files differ
diff --git a/src/main/asciidoc/images/newRealm2.png b/src/main/asciidoc/images/newRealm2.png
new file mode 100644
index 0000000..b039e1b
--- /dev/null
+++ b/src/main/asciidoc/images/newRealm2.png
Binary files differ
diff --git a/src/main/asciidoc/images/roleMappings.png b/src/main/asciidoc/images/roleMappings.png
new file mode 100644
index 0000000..5528b29
--- /dev/null
+++ b/src/main/asciidoc/images/roleMappings.png
Binary files differ
diff --git a/src/main/asciidoc/images/roleSuperUser.png b/src/main/asciidoc/images/roleSuperUser.png
new file mode 100644
index 0000000..413d285
--- /dev/null
+++ b/src/main/asciidoc/images/roleSuperUser.png
Binary files differ
diff --git a/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc b/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc
new file mode 100644
index 0000000..d9aed64
--- /dev/null
+++ b/src/main/asciidoc/interfaceDocumentation/auth_n_auth_interfaceDocumentation.adoc
@@ -0,0 +1,402 @@
+////
+******************************************************************************
+* Copyright © 2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+////
+authAndAuth@openK - Backend REST-Service documentation
+======================================================
+:Author: Frank Dietrich
+:Email: frank.dietrich@pta.de
+:Date: 2017-07-12
+:Revision: 1
+:icons:
+:source-highlighter: highlightjs
+:highlightjs-theme: solarized_dark
+
+
+== Base-URL
+
+----
+http://<host>:<port>/<name-of-war>/rest/beservice
+----
+
+== Common Features
+All services may return the following http status codes:
+
+.Http-Status-Codes
+[options="header,footer"]
+|=========================================================
+|Code|Description|Usage within the application
+|200|OK|-
+|400|Bad Request|The structure of the request (for example a JSON within a post request) is not correct
+|401|Unauthorized|Login-credentials are wrong or there is an invalid session token
+|500|Internal Server Error|An unexpected error occurred
+|=========================================================
+
+If there is a special service behavior regarding the returned http status code, then it will be explained within the service description.
+
+== Protection
+
+The protection of services is implemented by a security token following the JWT (JSON Web Token) specification:
+https://jwt.io/
+
+The *“login”*-service provides a JWT, when called with valid user-credentials.
+The security token (access token) (which is part of the JWT) has always to be provided with the
+HTTP-Header-Parameter "Authorization", in order to access a secured services later on.
+
+
+=== JSON Web Token
+
+The token has several purposes. A typical client of the Auth&Auth-Service needs to use
+the following features:
+
+. *access token* to access functions of a secured service
+. *user-information* to get extended information about the own user
+. *user-roles* of the own user.
+
+Even though JWT is a defined standard, we only will describe those features inside this document,
+which are directly used by the Auth&Auth-Service.
+
+Generally JWT uses *base64-encoding*. The data, that is stored in a token is always
+encoded with *base64*.
+
+[IMPORTANT]
+====
+The data in the examples has been shortened. Real examples would be very long and hard to read.
+====
+
+==== Access token
+The *access token* can be directly found in the field "access_token" within the JWT.
+
+
+
+Example:
+[source,json]
+----
+{
+ "access_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAixxxIn0.eyBBB.eydkk",
+ "expires_in":300,
+ "refresh_expires_in":1800,
+ "refresh_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAixxxIn0.eyJqdGwLTQyMTYtOD.eydkk",
+ "token_type":"bearer",
+ "id_token":"eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2l.eyJqdGkLTRjZTItYT.oUkke",
+ "not-before-policy":1502453751,
+ "session_state":"8b4e6979-1d51-4086-9db5-d296f70b4b65"
+}
+
+----
+
+
+==== User-Information/UserRoles
+
+The 2nd part (between the first and the second period *"."* - in this example "'eyBBB'") of the access-token is called the *"access-token-payload"*. When decoded from Base64 it could
+look like this:
+
+[source,json]
+----
+{
+ "jti":"a3d15ccf-c0e3-4534-a05a-f18b3a7c778b",
+ "exp":1505736257,
+ "nbf":0,
+ "iat":1505735957,
+ "iss":"http://authserver:8080/auth/realms/elogbook",
+ "aud":"elogbook-backend",
+ "sub":"c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+ "typ":"Bearer",
+ "azp":"elogbook-backend",
+ "auth_time":0,
+ "session_state":"59ae4a68-595b-4345-873d-aadf0a3efc94",
+ "acr":"1",
+ "allowed-origins":["*"],
+ "realm_access":{"roles":["elogbook-normaluser","uma_authorization"]},
+ "resource_access":{"account":{"roles":["manage-account","manage-account-links","view-profile"]}},
+ "name":"Hugo Boss",
+ "preferred_username":"hugo",
+ "given_name":"Hugo",
+ "family_name":"Boss"
+}
+----
+
+The configured roles of the user can be determined from the json array:
+
+ * *realm_access"*
+
+Extended
+user information can be found in the fields:
+
+ * *"name"*
+ * *"perferred_username"*
+ * *"given_name"*
+ * *"family_name"*.
+
+
+== Services
+=== Receive Version Information
+This service returns the current version of the backend implementation and the version of the database structure.
+
+*URL:* /versionInfo
+
+*Method:* GET
+
+*Request-Headers*:
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+{
+ "backendVersion": "0.1.1-Snapshot"
+}
+----
+
+*Protection*: none
+
+*Remarks*:
+
+=== Login
+This service receives login credentials in order to perform the authentication. If the login succeeds,
+it provides a valid JWT, used for accessing other services later on.
+
+*URL:* /login
+
+*Method:* POST
+
+*Request-Body*:
+[source,json]
+----
+{
+ "userName": "Mustermann",
+ "password": "clearpassword"
+}
+----
+
+*Produces*: application/json
+
+*Response*:
+
+JWT (JSON Web Token)
+
+*Remarks*: See chapter "*JWT*" for detailed informations about the features of the returned token.
+
+
+=== Logout
+This services kills the server session belonging to the the given session token.
+
+*URL:* /logout
+
+*Method:* POST
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+
+*Remarks*:
+
+=== CheckAuthorization
+This services receives a JWT in the "Authorization" Http header and checks, if its still valid.
+If it is valid, it resets the inactivity time for that token.
+
+*URL:* /checkAuth
+
+*Method:* GET
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+{
+ "ret": "OK"
+}
+----
+
+*Remarks*: This service return OK when the provided token is still valid. Otherwise it returns a 401 - "Unauthorized" Http Code.
+
+=== Get user modules for the current user
+This service returns the modules for which the user is authorized.
+
+*URL:* /userModulesForUser
+
+*Method:* GET
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+[
+ {
+ "name":"Betriebstagebuch",
+ "cols":1,
+ "rows":1,
+ "color":"#ffffff",
+ "link":"http://172.18.22.160:8880/elogbookFE",
+ "pictureLink":"https://www.openkonsequenz.de/xxxelogbuch_2443636.jpg",
+ "requiredRole":"elogbook_access"
+ }
+ ,
+ {
+ "name":"Bereitschaftsplanung",
+ "cols":1,
+ "rows":1,
+ "color":"#ffffff",
+ "link":"https://www.openkonsequenz.de/anwender/xxxx/94-bereitschaftsplan",
+ "pictureLink":"https://www.openkonsequenz.de/medien/xxx/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole":"planning_access"
+ }
+ ,
+ {
+ ...
+ }
+]
+----
+
+*Remarks*: This service checks if the currently logged in user has the role "requiredRole" in its JWT and
+returns the modules he is authorized for.
+
+
+=== Get all users for a specific role
+This service returns all users belonging to the specified role.
+
+*URL:* /usersForRole/{userRole}
+
+*Method:* GET
+
+*Path-Parameter*: userRole
+
+* The role name like it is defined in Keycloak
+
+*Request-Headers*:
+
+* Authorization – Existing access token
+
+
+*Produces*: application/json
+
+*Response*:
+[source,json]
+----
+[
+ {
+ "id": "359ef9c9-77df-4a3d-a9c9-f96d837d2d57",
+ "createdTimestamp": 1501594173784,
+ "username": "admin",
+ "enabled": true,
+ "totp": false,
+ "emailVerified": false,
+ "firstName": "Administrator",
+ "lastName": "Administratowich",
+ "realmRoles": [
+ "elogbook-superuser",
+ "elogbook_access",
+ "uma_authorization",
+ "elogbook-normaluser"
+ ],
+ "disableableCredentialTypes": [
+ "password"
+ ],
+ "requiredActions": [],
+ "access": {
+ "manageGroupMembership": false,
+ "view": true,
+ "mapRoles": false,
+ "impersonate": false,
+ "manage": false
+ }
+ },
+ {
+ "id": "c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+ "createdTimestamp": 1501594239066,
+ "username": "hugo",
+ "enabled": true,
+ "totp": false,
+ "emailVerified": false,
+ "firstName": "Hugo",
+ "lastName": "Boss",
+ "realmRoles": [
+ "elogbook_access",
+ "elogbook-normaluser"
+ ],
+ "disableableCredentialTypes": [
+ "password"
+ ],
+ "requiredActions": [],
+ "access": {
+ "manageGroupMembership": false,
+ "view": true,
+ "mapRoles": false,
+ "impersonate": false,
+ "manage": false
+ }
+ },
+ {
+ ...
+ }
+]
+----
+
+*Remarks*:
+
+=== Get health state
+This service returns the health state of this module.
+
+*URL:* /healthcheck/pretty=true
+
+*Method:* GET
+
+
+
+*Request-Headers*:
+
+* Authorization – none
+
+
+*Produces*: application/json
+
+*Response*:
+
+If the module is healthy then...
+[source,json]
+----
+{"Keycloak present":{"healthy":true}}
+----
+
+If the module is *not* healthy...
+[source,json]
+----
+{
+ "Keycloak present":
+ {
+ "healthy":false,
+ "message":"<Error message>"
+ }
+}
+----
+
+
+*Remarks*:
+
+
+
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java
new file mode 100644
index 0000000..2bef7fd
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtAccount.java
@@ -0,0 +1,23 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class JwtAccount {
+ private List<String> roles;
+
+ public List<String> getRoles() {
+ return roles;
+ }
+ public void setRoles(List<String> roles) { this.roles = roles; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java
new file mode 100644
index 0000000..5518bf6
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtHeader.java
@@ -0,0 +1,25 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+public class JwtHeader {
+ private String alg;
+ private String typ;
+ private String kid;
+
+ public String getAlg() { return alg; }
+ public void setAlg(String alg) { this.alg = alg; }
+ public String getTyp() { return typ; }
+ public void setTyp(String typ) { this.typ = typ; }
+ public String getKid() { return kid; }
+ public void setKid(String kid) { this.kid = kid; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java
new file mode 100644
index 0000000..6f6ffe3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtPayload.java
@@ -0,0 +1,113 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import java.util.List;
+
+
+public class JwtPayload {
+
+ //No Sonar because variables are wrong due to jwt definition
+
+ private String jti;
+ private long exp;
+ private long nbf;
+ private long iat;
+ private String iss;
+
+ //Since Keycloak 4.8.3 "aud" Parameter is an array now
+ //Pre 4.8.3 "aud" was a single String
+ //We keep it for documentation reasons
+ //private String[] aud; //NOSONAR
+ //private String aud; //NOSONAR
+ private String sub;
+ private String typ;
+ private String azp;
+ private String nonce;
+ private Integer auth_time; //NOSONAR
+ private String session_state; //NOSONAR
+ private String acr;
+
+ @JsonProperty("allowed-origins")
+ private List<String> allowedOrigins;
+ private JwtRealmAccess realm_access; //NOSONAR
+ private JwtResourceAccess resource_access; //NOSONAR
+
+ private String name;
+ private String preferred_username; //NOSONAR
+ private String given_name; //NOSONAR
+ private String family_name; //NOSONAR
+
+ public String getJti() { return jti; }
+ public void setJti(String jti) { this.jti = jti; }
+
+ public long getExp() { return exp; }
+ public void setExp(long exp) { this.exp = exp; }
+
+ public long getNbf() { return nbf; }
+ public void setNbf(long nbf) { this.nbf = nbf; }
+
+ public long getIat() { return iat; }
+ public void setIat(long iat) { this.iat = iat; }
+
+ public String getiss() { return iss; }
+ public void setiss(String iss) { this.iss = iss; }
+
+ public String getsub() { return sub; }
+ public void setsub(String sub) { this.sub = sub; }
+
+ public String gettyp() { return typ; }
+ public void settyp(String typ) { this.typ = typ; }
+
+ public String getAzp() { return azp; }
+ public void setAzp(String azp) { this.azp = azp; }
+
+ public String getNonce() { return nonce; }
+ public void setNonce(String nonce) { this.nonce = nonce; }
+
+ public Integer getAuthTime() { return auth_time; }
+ public void setAuthTime(Integer auth_time) { this.auth_time = auth_time; } //NOSONAR
+
+ public String getSessionState() { return session_state; }
+ public void setSessionState(String session_state) { this.session_state = session_state; } //NOSONAR
+
+ public String getAcr() { return acr; }
+ public void setAcr(String acr) { this.acr = acr; }
+
+ public List<String> getAllowedOrigins() {
+ return allowedOrigins;
+ }
+ public void setAllowedOrigins(List<String> allowedOrigins) { this.allowedOrigins = allowedOrigins; }
+
+ public JwtRealmAccess getRealmAccess() { return realm_access; }
+ public void setRealmAccess(JwtRealmAccess realm_access) { this.realm_access = realm_access; } //NOSONAR
+
+ public JwtResourceAccess getResourceAccess() { return resource_access; }
+ public void setResourceAccess(JwtResourceAccess resource_access) { this.resource_access = resource_access; } //NOSONAR
+
+ public String getName() { return name; }
+ public void setName(String name) { this.name = name; }
+
+ public String getPreferredUsername() { return preferred_username; }
+ public void setPreferredUsername(String preferred_username) { this.preferred_username = preferred_username; } //NOSONAR
+
+ public String getGivenName() { return given_name; }
+ public void setGivenName(String given_name) { this.given_name = given_name; } //NOSONAR
+
+ public String getFamilyName() { return family_name; }
+ public void setFamilyName(String family_name) { this.family_name = family_name; } //NOSONAR
+
+ public boolean isInRole(String role) {
+ return this.realm_access != null && this.realm_access.isInRole(role);
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java
new file mode 100644
index 0000000..05df537
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtRealmAccess.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class JwtRealmAccess {
+ private List<String> roles;
+
+ public List<String> getRoles() {
+ return roles;
+ }
+ public void setRoles(List<String> roles) { this.roles = roles; }
+
+
+ public boolean isInRole(String role) {
+ return this.roles != null && this.roles.contains(role);
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java
new file mode 100644
index 0000000..6be7f95
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtResourceAccess.java
@@ -0,0 +1,19 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+public class JwtResourceAccess {
+ private JwtAccount account;
+
+ public JwtAccount getAccount() { return account; }
+ public void setAccount(JwtAccount account) { this.account = account; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java
new file mode 100644
index 0000000..e428466
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/JwtToken.java
@@ -0,0 +1,43 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public class JwtToken {
+
+ //No Sonar because variables are wrong due to jwt definition
+
+ private String access_token; //NOSONAR
+ private String refresh_token; //NOSONAR
+ private String token_type; //NOSONAR
+ private String session_state; //NOSONAR
+ private Integer expires_in; //NOSONAR
+ private Integer refresh_expires_in; //NOSONAR
+ @JsonProperty("not-before-policy")
+ private Integer not_before_policy; //NOSONAR
+
+ public String getAccessToken() { return access_token; }
+ public void setAccessToken(String access_token) { this.access_token = access_token; } //NOSONAR
+ public String getRefreshToken() { return refresh_token; }
+ public void setRefreshToken(String refresh_token) { this.refresh_token = refresh_token; } //NOSONAR
+ public String getTokenType() { return token_type; }
+ public void setTokenType(String token_type) { this.token_type = token_type; } //NOSONAR
+ public String getSessionState() { return session_state; }
+ public void setSessionState(String session_state) { this.session_state = session_state; } //NOSONAR
+ public Integer getExpiresIn() { return expires_in; }
+ public void setExpiresIn(Integer expires_in) { this.expires_in = expires_in; } //NOSONAR
+ public Integer getRefreshExpiresIn() { return refresh_expires_in; }
+ public void setRefreshExpiresIn(Integer refresh_expires_in) { this.refresh_expires_in = refresh_expires_in; } //NOSONAR
+ public Integer getNotBeforePolicy() { return not_before_policy; }
+ public void setNotBeforePolicy(Integer not_before_policy) { this.not_before_policy = not_before_policy; } //NOSONAR
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakClientRoles.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakClientRoles.java
new file mode 100644
index 0000000..6536a21
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakClientRoles.java
@@ -0,0 +1,45 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+
+public class KeyCloakClientRoles {
+
+ private String id;
+ private String client;
+ private List<KeyCloakRole> mappings;
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getClient() {
+ return client;
+ }
+
+ public void setClient(String client) {
+ this.client = client;
+ }
+
+ public List<KeyCloakRole> getMappings() {
+ return mappings;
+ }
+
+ public void setMappings(List<KeyCloakRole> mappings) {
+ this.mappings = mappings;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java
new file mode 100644
index 0000000..04ea3e1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRole.java
@@ -0,0 +1,79 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+public class KeyCloakRole {
+
+ private String id;
+ private String name;
+ private Boolean scopeParamRequired;
+ private Boolean composite;
+ private Boolean clientRole;
+ private String containerId;
+
+ public KeyCloakRole(String id, String name, Boolean scopeParamRequired, Boolean composite, Boolean clientRole, String containerId) {
+ this.id = id;
+ this.name = name;
+ this.scopeParamRequired = scopeParamRequired;
+ this.composite = composite;
+ this.clientRole = clientRole;
+ this.containerId = containerId;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public Boolean getScopeParamRequired() {
+ return scopeParamRequired;
+ }
+
+ public void setScopeParamRequired(Boolean scopeParamRequired) {
+ this.scopeParamRequired = scopeParamRequired;
+ }
+
+ public Boolean getComposite() {
+ return composite;
+ }
+
+ public void setComposite(Boolean composite) {
+ this.composite = composite;
+ }
+
+ public Boolean getClientRole() {
+ return clientRole;
+ }
+
+ public void setClientRole(Boolean clientRole) {
+ this.clientRole = clientRole;
+ }
+
+ public String getContainerId() {
+ return containerId;
+ }
+
+ public void setContainerId(String containerId) {
+ this.containerId = containerId;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRoles.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRoles.java
new file mode 100644
index 0000000..643b105
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakRoles.java
@@ -0,0 +1,38 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+import java.util.Map;
+
+public class KeyCloakRoles {
+
+ List<KeyCloakRole> realmMappings;
+
+ private Map<String, KeyCloakClientRoles> clientMappings;
+
+ public List<KeyCloakRole> getRealmMappings() {
+ return realmMappings;
+ }
+
+ public void setRealmMappings(List<KeyCloakRole> realmMappings) {
+ this.realmMappings = realmMappings;
+ }
+
+ public Map<String, KeyCloakClientRoles> getClientMappings() {
+ return clientMappings;
+ }
+
+ public void setClientMappings(Map<String, KeyCloakClientRoles> clientMappings) {
+ this.clientMappings = clientMappings;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java
new file mode 100644
index 0000000..58aeb90
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUser.java
@@ -0,0 +1,110 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+import java.util.List;
+import java.util.Map;
+
+public class KeyCloakUser {
+ private String id;
+ private long createdTimestamp;
+ private String username;
+ private boolean enabled;
+ private boolean totp;
+ private boolean emailVerified;
+ private String firstName;
+ private String lastName;
+ private String name;
+ private List<String> allRoles;
+ private List<String> realmRoles;
+ private Map<String, List<String>> clientRoles;
+
+ private List<String> disableableCredentialTypes;
+ private List<String> requiredActions;
+ private KeyCloakUserAccess access;
+
+ public String getId() { return id; }
+ public void setId(String id) { this.id = id; }
+
+ public long getCreatedTimestamp() { return createdTimestamp; }
+ public void setCreatedTimestamp(long createdTimestamp) { this.createdTimestamp = createdTimestamp; }
+
+ public String getUsername() { return username; }
+ public void setUsername(String username) { this.username = username; }
+
+ public void setTotp(boolean totp) { this.totp = totp; }
+
+ public void setEmailVerified(boolean emailVerified) { this.emailVerified = emailVerified; }
+
+ public String getFirstName() { return firstName; }
+ public void setFirstName(String firstName) { this.firstName = firstName; }
+
+ public String getLastName() { return lastName; }
+ public void setLastName(String lastName) { this.lastName = lastName; }
+
+ public List<String> getDisableableCredentialTypes() {
+ return disableableCredentialTypes;
+ }
+ public void setDisableableCredentialTypes(List<String> disableableCredentialTypes) { this.disableableCredentialTypes = disableableCredentialTypes; }
+
+ public List<String> getRequiredActions() {
+ return requiredActions;
+ }
+ public void setRequiredActions(List<String> requiredActions) { this.requiredActions = requiredActions; }
+
+ public KeyCloakUserAccess getAccess() { return access; }
+ public void setAccess(KeyCloakUserAccess access) { this.access = access; }
+
+ public boolean isEnabled() {
+ return enabled;
+ }
+
+ public boolean isTotp() {
+ return totp;
+ }
+
+ public boolean isEmailVerified() {
+ return emailVerified;
+ }
+
+ public List<String> getAllRoles() {
+ return allRoles;
+ }
+
+ public void setAllRoles(List<String> allRoles) {
+ this.allRoles = allRoles;
+ }
+
+ public List<String> getRealmRoles() {
+ return realmRoles;
+ }
+
+ public void setRealmRoles(List<String> realmRoles) {
+ this.realmRoles = realmRoles;
+ }
+
+ public Map<String, List<String>> getClientRoles() {
+ return clientRoles;
+ }
+
+ public void setClientRoles(Map<String, List<String>> clientRoles) {
+ this.clientRoles = clientRoles;
+ }
+
+ public void setName() {
+ if (lastName!= null && !lastName.isEmpty()){
+ this.name = firstName+ " " + lastName;
+ } else {
+ this.name = firstName;
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java
new file mode 100644
index 0000000..48b158f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/model/KeyCloakUserAccess.java
@@ -0,0 +1,31 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.model;
+
+public class KeyCloakUserAccess {
+ private boolean manageGroupMembership;
+ private boolean view;
+ private boolean mapRoles;
+ private boolean impersonate;
+ private boolean manage;
+
+ public boolean getManageGroupMembership() { return manageGroupMembership; }
+ public void setManageGroupMembership(boolean manageGroupMembership) { this.manageGroupMembership = manageGroupMembership; }
+ public boolean getView() { return view; }
+ public void setView(boolean view) { this.view = view; }
+ public boolean getMapRoles() { return mapRoles; }
+ public void setMapRoles(boolean mapRoles) { this.mapRoles = mapRoles; }
+ public boolean getImpersonate() { return impersonate; }
+ public void setImpersonate(boolean impersonate) { this.impersonate = impersonate; }
+ public boolean getManage() { return manage; }
+ public void setManage(boolean manage) { this.manage = manage; }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java b/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java
new file mode 100644
index 0000000..3d3ce96
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/auth2/util/JwtHelper.java
@@ -0,0 +1,228 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.auth2.util;
+
+import java.io.*;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.MediaType;
+import org.eclipse.openk.portal.auth2.model.JwtHeader;
+import org.eclipse.openk.portal.auth2.model.JwtPayload;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakClientRoles;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRoles;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import com.google.gson.JsonSyntaxException;
+import com.google.gson.reflect.TypeToken;
+
+import java.lang.reflect.Type;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+
+public class JwtHelper {
+
+ private static final Logger logger = Logger.getLogger(JwtHelper.class.getName());
+
+ private JwtHelper() {
+ }
+
+ public static JwtToken login(String user, String password) throws PortalInternalServerError {
+ String token = null;
+ try {
+ token = sendPost(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" +
+ BackendConfig.getInstance().getKeycloakRealm() + "/protocol/openid-connect/token",
+ "username=" + user + "&password=" + URLEncoder.encode(password, "UTF-8") + "&client_id="
+ + BackendConfig.getInstance().getKeycloakClient() + "&grant_type=password");
+ } catch (UnsupportedEncodingException e) {
+ logger.error( "Unsupported Encoding Exception: ", e);
+ throw new PortalInternalServerError(e.getMessage());
+ }
+ return getJwtTokenFromJson(token);
+ }
+
+ public static boolean serviceAvailable() throws PortalInternalServerError {
+ String jsonRet = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/realms/" +
+ BackendConfig.getInstance().getKeycloakRealm(), "", null);
+
+ return jsonRet != null ? jsonRet.contains("realm") && jsonRet.contains(BackendConfig.getInstance().getKeycloakRealm())
+ : false;
+ }
+
+ public static List<KeyCloakUser> getUsers(JwtToken jwtToken, int maxUsers) throws PortalInternalServerError {
+ String users = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users?max="+maxUsers,
+ MediaType.APPLICATION_JSON, jwtToken.getAccessToken());
+ return getUserListFromJson(users);
+ }
+
+ public static List<KeyCloakRole> getRolesForUser(JwtToken jwtToken, String id) throws PortalInternalServerError {
+ String roles = sendGet(BackendConfig.getInstance().getAuthServerUrl() + "auth/admin/realms/" + BackendConfig.getInstance().getKeycloakRealm() + "/users/" + id + "/role-mappings/",
+ MediaType.APPLICATION_JSON, jwtToken.getAccessToken());
+ return getRolesListFromJson(roles);
+ }
+
+ public static JwtHeader getJwtHeaderFromJson(String json) {
+ return JsonGeneratorBase.getGson().fromJson(json, JwtHeader.class);
+ }
+
+ public static JwtPayload getJwtPayloadFromJson(String json) {
+ return JsonGeneratorBase.getGson().fromJson(json, JwtPayload.class);
+ }
+
+ public static JwtToken getJwtTokenFromJson(String json) {
+ return JsonGeneratorBase.getGson().fromJson(json, JwtToken.class);
+ }
+
+ public static List<KeyCloakUser> getUserListFromJson(String json) throws PortalInternalServerError {
+ try {
+ Type listType = new TypeToken<List<KeyCloakUser>>() {
+ }.getType();
+ return JsonGeneratorBase.getGson().fromJson(json, listType);
+ } catch (JsonSyntaxException ex) {
+ logger.error("Error in getUserListFromJson", ex);
+ throw new PortalInternalServerError("JsonSyntaxException");
+ }
+ }
+
+ public static List<KeyCloakRole> getRolesListFromJson(String json) throws PortalInternalServerError {
+ try {
+ List<KeyCloakRole> allRoles = new ArrayList<>();
+ KeyCloakRoles keyCloakRoles = getGson().fromJson(json, KeyCloakRoles.class);
+ List<KeyCloakRole> realmRoles = keyCloakRoles.getRealmMappings();
+
+ if (realmRoles != null) {
+ allRoles.addAll(realmRoles);
+ }
+
+ Map<String, KeyCloakClientRoles> clientMappings = keyCloakRoles.getClientMappings();
+ if (clientMappings != null) {
+ KeyCloakClientRoles keyCloakClientRoles = clientMappings.get(BackendConfig.getInstance().getKeycloakClient());
+ if (keyCloakClientRoles != null){
+ List<KeyCloakRole> clientRoles = keyCloakClientRoles.getMappings();
+ allRoles.addAll(clientRoles);
+ }
+ }
+
+ return allRoles;
+ } catch (JsonSyntaxException ex) {
+ logger.error("Error in getRolesListFromJson", ex);
+ throw new PortalInternalServerError("JsonSyntaxException");
+ }
+ }
+
+ public static JwtPayload getPayLoad(JwtToken token) {
+ String[] parts = token.getAccessToken().split("[.]");
+
+ //parts[0] is the jwtHeader
+ String jwtPayload = parts[1];
+ //parts[2] is the jwtVerifySignature
+
+ // decode
+ Base64.Decoder decoder = Base64.getDecoder();
+ byte[] decoded = decoder.decode(jwtPayload);
+ jwtPayload = new String(decoded, StandardCharsets.UTF_8);
+ logger.debug(jwtPayload);
+ return getJwtPayloadFromJson(jwtPayload);
+ }
+
+ private static HttpURLConnection getHttpConnection(String targetUrl) throws PortalInternalServerError {
+ try {
+ URL url = new URL(targetUrl);
+ return (HttpURLConnection) url.openConnection();
+ } catch (IOException e) {
+ logger.error(e);
+ throw new PortalInternalServerError("HttpURLConnection IOException");
+ }
+ }
+
+ private static String sendGet(String targetUrl, String accept, String token) throws PortalInternalServerError {
+ logger.trace("sendGet");
+
+ HttpURLConnection con = getHttpConnection(targetUrl);
+ StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
+
+ try (AutoCloseable conc = con::disconnect) {
+ con.setRequestMethod("GET");
+ con.setRequestProperty("Accept", accept);
+ con.setInstanceFollowRedirects(false);
+ if (token != null) // is authenticated
+ {
+ con.setRequestProperty("Authorization", "Bearer " + token);
+ }
+ InputStream is = con.getInputStream();
+ try (BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+ String line;
+ while ((line = rd.readLine()) != null) {
+ response.append(line);
+ response.append('\r');
+ logger.trace("Got line -> " + line);
+ }
+ }
+ logger.trace("sendGet was successful");
+ return response.toString();
+ } catch (Exception e) {
+ logger.error("Error occured in sendGet: " + e);
+ return null;
+ }
+ }
+
+ private static String sendPost(String targetUrl, String urlParameters) throws PortalInternalServerError {
+ logger.debug("sendPost");
+
+ HttpURLConnection con = getHttpConnection(targetUrl);
+ StringBuilder response = new StringBuilder(); // or StringBuffer if Java version 5+
+
+ try (AutoCloseable conc = con::disconnect) {
+ con.setRequestMethod("POST");
+ con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded; charset=utf-8");
+ con.setRequestProperty("Accept", MediaType.APPLICATION_JSON);
+ con.setRequestProperty("Content-Length", Integer.toString(urlParameters.getBytes(StandardCharsets.UTF_8.name()).length));
+
+ con.setInstanceFollowRedirects(false);
+ con.setDoOutput(true);
+ // Send request
+ try (DataOutputStream wr = new DataOutputStream(con.getOutputStream())) {
+ wr.write(urlParameters.getBytes(StandardCharsets.UTF_8.name()));
+ }
+ // Get Response
+ InputStream is = con.getInputStream();
+
+ try (BufferedReader rd = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8.name()))) {
+ String line;
+ while ((line = rd.readLine()) != null) {
+ response.append(line);
+ response.append('\r');
+ }
+ }
+
+ return response.toString();
+ } catch (Exception e) {
+ logger.error("Error occured in sendPost: " + e);
+ return null;
+ }
+ }
+
+ public static String formatToken(String accessToken) {
+ return accessToken != null ? accessToken.replace("Bearer", "").trim() : "";
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java b/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java
new file mode 100644
index 0000000..4ac8a11
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/BackendConfig.java
@@ -0,0 +1,80 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+
+public class BackendConfig {
+ private static String configFileName = "backendConfigDevLocal.json";
+ private Integer internalSessionLengthMillis;
+ private Integer reloadUsersInSec;
+ private String authServerUrl;
+ private String keycloakRealm;
+ private String keycloakClient;
+ private String keycloakAdmin;
+ private String keycloakPW;
+ private Integer maxLoadUsers;
+
+ private static BackendConfig instance;
+
+ private BackendConfig() {}
+
+ public static synchronized BackendConfig getInstance() {
+ if (instance == null) {
+ String jsonConfig = loadJsonConfig();
+ instance = JsonGeneratorBase.getGson().fromJson(jsonConfig, BackendConfig.class);
+ }
+
+ return instance;
+ }
+
+ private static String loadJsonConfig() {
+ ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+ return resourceLoaderBase.loadStringFromResource(configFileName);
+ }
+
+ public Integer getInternalSessionLengthMillis() { return internalSessionLengthMillis; }
+
+ public Integer getReloadUsersInSec() { return reloadUsersInSec; }
+
+ public String getAuthServerUrl() {
+ return authServerUrl;
+ }
+
+ public String getKeycloakClient() {
+ return keycloakClient;
+ }
+
+ public String getKeycloakAdmin() {
+ return keycloakAdmin;
+ }
+
+ public String getKeycloakPW() {
+ return keycloakPW;
+ }
+
+ public String getKeycloakRealm() {
+ return keycloakRealm;
+ }
+
+ public Integer getMaxLoadUsers() {
+ return maxLoadUsers;
+ }
+
+ public static String getConfigFileName() {
+ return configFileName;
+ }
+
+ public static void setConfigFileName(String configFileName) {
+ BackendConfig.configFileName = configFileName;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/Globals.java b/src/main/java/org/eclipse/openk/portal/common/Globals.java
new file mode 100644
index 0000000..b11101b
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/Globals.java
@@ -0,0 +1,52 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+
+public final class Globals {
+ public static final String OK_STRING = "OK";
+ public static final String SESSION_TOKEN_TAG = "X-XSRF-TOKEN";
+ public static final String SESSION_COOKIE_TOKEN_TAG = "COOKIESESSION-TOKEN";
+ public static final int MAX_CREDENTIALS_LENGTH = 500;
+ public static final int MAX_NOTIFICATION_LENGTH = 16384;
+
+ public static final int HTTPSTATUS_OK = 200;
+ public static final int HTTPSTATUS_BAD_REQUEST = 400;
+ public static final int HTTPSTATUS_UNAUTHORIZED = 401;
+ public static final int HTTPSTATUS_FORBIDDEN = 403;
+ public static final int HTTPSTATUS_NOT_FOUND = 404;
+ public static final int HTTPSTATUS_GONE = 410;
+ public static final int HTTPSTATUS_LOCKED = 423;
+ public static final int HTTPSTATUS_INTERNAL_SERVER_ERROR = 500;
+ public static final int HTTPSTATUS_NOT_AVAILABLE = 503;
+ public static final int HTTPSTATUS_POLICY_NOT_FULFILLED = 420;
+ public static final int HTTPSTATUS_CONFLICT = 409;
+ public static final int HTTPSTATUS_DECISION = 900;
+
+ //For Branches: for later use in a configurable json
+ public static final String ELECTRICITY_MARK = "S";
+ public static final String GAS_MARK = "G";
+ public static final String DISTRICT_HEAT_MARK = "F";
+ public static final String WATER_MARK = "W";
+
+ //Errormessage
+ public static final String DATA_OUTDATED = "Data is outdated!";
+
+ //Suggestion: An input field on search mask as better solution? Can only be adapted by code changes.
+ public static final int FAST_SEARCH_NUMBER_OF_DAYS_BACK = -200;
+
+ //KeyCloak configuration
+ public static final String KEYCLOAK_AUTH_TAG = "Authorization";
+
+ private Globals() {}
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java b/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java
new file mode 100644
index 0000000..fd364b8
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/GsonUTCDateAdapter.java
@@ -0,0 +1,51 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.JsonDeserializationContext;
+import com.google.gson.JsonDeserializer;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonParseException;
+import com.google.gson.JsonPrimitive;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+public class GsonUTCDateAdapter implements JsonSerializer<Date>, JsonDeserializer<Date> {
+
+ private final DateFormat dateFormat;
+
+ public GsonUTCDateAdapter() {
+ dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US); //This is the format I need
+ dateFormat.setTimeZone(TimeZone.getTimeZone("UTC")); //This is the key line which converts the date to UTC which cannot be accessed with the default serializer
+ }
+
+ @Override
+ public synchronized JsonElement serialize(Date date, Type type, JsonSerializationContext jsonSerializationContext) {
+ return new JsonPrimitive(dateFormat.format(date));
+ }
+
+ @Override
+ public synchronized Date deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
+ try {
+ return dateFormat.parse(jsonElement.getAsString());
+ } catch (ParseException e) {
+ throw new JsonParseException(e);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java b/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java
new file mode 100644
index 0000000..61d7e63
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitBackendConfig.java
@@ -0,0 +1,65 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+public class InitBackendConfig extends HttpServlet {
+
+ private static final long serialVersionUID = -7882117179312471533L;
+
+ private static final Logger LOGGER = Logger.getLogger(InitBackendConfig.class.getName());
+
+ @Override
+ public void init() throws ServletException {
+ String environment = getServletContext().getInitParameter("OK_PORTAL_ENVIRONMENT");
+ setConfigFiles(environment);
+ }
+
+ private void setConfigFiles(String environment ) {
+ String env = (environment == null ? "Production": environment);
+
+ String backendConfigFile;
+ String moduleConfigFile;
+ switch (env){
+ case "DevLocal":
+ backendConfigFile="backendConfigDevLocal.json";
+ moduleConfigFile="moduleConfigDevLocal.json";
+ break;
+ case "DevServer":
+ backendConfigFile="backendConfigDevServer.json";
+ moduleConfigFile="moduleConfigDevServer.json";
+ break;
+ case "Custom":
+ backendConfigFile="backendConfigCustom.json";
+ moduleConfigFile="moduleConfigCustom.json";
+ break;
+ case "Docker":
+ backendConfigFile="backendConfigDocker.json";
+ moduleConfigFile="moduleConfigDocker.json";
+ break;
+ default:
+ backendConfigFile="backendConfigProduction.json";
+ moduleConfigFile="moduleConfigProduction.json";
+ }
+
+ BackendConfig.setConfigFileName(backendConfigFile);
+ UserModule.setConfigFileName(moduleConfigFile);
+ LOGGER.info("Portal backendendenviroment is: " +environment+ ". Setting backendConfig accordingly to: "+ backendConfigFile);
+ LOGGER.info("Portal backendendenviroment is: " +environment+ ". Setting moduleConfig accordingly to: "+ moduleConfigFile);
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java b/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java
new file mode 100644
index 0000000..0d9be8f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/InitUserCacheJob.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import java.util.Timer;
+import java.util.TimerTask;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import org.apache.log4j.Logger;
+
+public class InitUserCacheJob extends HttpServlet {
+
+ private static final long serialVersionUID = 8671326157376987023L;
+
+ private static final Logger LOGGER = Logger.getLogger(InitUserCacheJob.class.getName());
+
+
+ @Override
+ public void init() throws ServletException {
+ LOGGER.debug("InitUserCacheJob called");
+ TimerTask timerTask = new UserCacheTimerTask();
+ Timer timer = new Timer();
+ timer.scheduleAtFixedRate(timerTask, 500, BackendConfig.getInstance().getReloadUsersInSec()*1000L);
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java b/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java
new file mode 100644
index 0000000..43e0ca5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/JsonGeneratorBase.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.Date;
+
+public class JsonGeneratorBase {
+ private JsonGeneratorBase() {}
+ public static Gson getGson() {
+ return new GsonBuilder()
+ .registerTypeAdapter(Date.class, new GsonUTCDateAdapter())
+ .disableHtmlEscaping()
+ .create();
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java b/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java
new file mode 100644
index 0000000..3a192f1
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/UserCacheTimerTask.java
@@ -0,0 +1,71 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.TimerTask;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.controller.TokenManager;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+
+public class UserCacheTimerTask extends TimerTask {
+
+ private static final Logger LOGGER = Logger.getLogger(TokenManager.class.getName());
+
+ @Override
+ public void run() {
+ LOGGER.debug("UserCacheTimerTask started");
+ try {
+ JwtToken token = JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW());
+ if( token == null ) {
+ LOGGER.error("Login for getKeyCloakUsersFromToken() failed for User:"+ BackendConfig.getInstance().getKeycloakAdmin());
+ return;
+ }
+
+ List<KeyCloakUser> allUsersWithRoles = getKeyCloakUsersFromToken(token);
+
+ if( allUsersWithRoles.isEmpty()) {
+ LOGGER.warn("getKeyCloakUsersFromToken provided empty list!");
+ }
+
+ UserCache.getInstance().setKeyCloakUsers(allUsersWithRoles);
+
+ } catch (PortalInternalServerError portalInternalServerError) {
+ LOGGER.error(portalInternalServerError);
+ }
+
+ LOGGER.debug("UserCacheTimerTask finished");
+ }
+
+ private List<KeyCloakUser> getKeyCloakUsersFromToken(JwtToken token) throws PortalInternalServerError {
+ List<KeyCloakUser> allUsers = JwtHelper.getUsers(token, BackendConfig.getInstance().getMaxLoadUsers());
+ List<KeyCloakUser> allUsersWithRoles = new ArrayList<>();
+
+ for (KeyCloakUser user : allUsers) {
+ List<String> rolesList = new ArrayList<>();
+ List<KeyCloakRole> rolesForUser = JwtHelper.getRolesForUser(token, user.getId());
+ user.setName();
+ for (KeyCloakRole keyCloakRole : rolesForUser) {
+ rolesList.add(keyCloakRole.getName());
+ }
+ user.setAllRoles(rolesList);
+ allUsersWithRoles.add(user);
+ }
+ return allUsersWithRoles;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java b/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java
new file mode 100644
index 0000000..df13cbf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/HashingAlgo.java
@@ -0,0 +1,32 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common.util;
+
+import java.security.MessageDigest;
+import org.apache.commons.codec.binary.Hex;
+
+public final class HashingAlgo {
+ private HashingAlgo() {}
+
+ public static String hashIt(String pwdClear) {
+ MessageDigest cript;
+ try {
+ cript = MessageDigest.getInstance("SHA-1");
+ cript.reset();
+ cript.update(pwdClear.getBytes("utf8"));
+ return new String(Hex.encodeHex(cript.digest()));
+
+ } catch (Exception e) { //NOSONAR
+ return null;
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java b/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java
new file mode 100644
index 0000000..7262f5f
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/LoggerUtil.java
@@ -0,0 +1,82 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common.util;
+
+import java.io.IOException;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.log4j.Appender;
+import org.apache.log4j.BasicConfigurator;
+import org.apache.log4j.Layout;
+import org.apache.log4j.Level;
+import org.apache.log4j.PatternLayout;
+import org.apache.log4j.net.SyslogAppender;
+import org.apache.log4j.spi.RootLogger;
+import org.apache.log4j.xml.DOMConfigurator;
+
+/**
+ * <b>LoggerConfig</b><br>
+ * Logging Implementierung
+ */
+public final class LoggerUtil extends HttpServlet {
+ /**
+ * serialVersionUID.
+ */
+ private static final long serialVersionUID = 1L;
+
+ /*
+ * (non-Javadoc)
+ * @see javax.servlet.GenericServlet#init()
+ */
+ @Override
+ public void init() {
+ final ServletContext context = getServletContext();
+
+ if (Boolean.valueOf(context.getInitParameter("param.syslog.use"))) {
+ // configure for syslog using parameters specified in configuration descriptor
+ BasicConfigurator.resetConfiguration();
+
+ final String level = context.getInitParameter("param.syslog.level");
+ RootLogger.getRootLogger().setLevel(Level.toLevel(level));
+
+ final String host = context.getInitParameter("param.syslog.host");
+ final String facility = context.getInitParameter("param.syslog.facility");
+ final Layout layout = new PatternLayout("[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n");
+ final Appender syslogAppender = new SyslogAppender(layout, host,
+ SyslogAppender.getFacility(facility));
+ BasicConfigurator.configure(syslogAppender);
+
+ } else {
+ // configure using parameters specified in xml file
+ final String prefix = context.getRealPath("/");
+ final String file = getInitParameter("log4j-init-file");
+
+ if (prefix != null && file != null) {
+ DOMConfigurator.configure(prefix + file);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest,
+ * javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ protected void doGet(final HttpServletRequest req, final HttpServletResponse resp)
+ throws ServletException, IOException {
+ // Nothing done on purpose.
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java b/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java
new file mode 100644
index 0000000..cb5d9d3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/common/util/ResourceLoaderBase.java
@@ -0,0 +1,36 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common.util;
+
+import java.io.InputStream;
+import java.io.StringWriter;
+import org.apache.commons.io.IOUtils;
+
+public class ResourceLoaderBase {
+ private String stream2String(InputStream is) {
+ StringWriter writer = new StringWriter();
+ try {
+ IOUtils.copy(is, writer, "UTF-8");
+ } catch (Exception e) { // NOSONAR
+ return "";
+ }
+ return writer.toString();
+
+
+ }
+
+ public String loadStringFromResource(String filename) {
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+ InputStream jsonstream = classLoader.getResourceAsStream(filename);
+ return stream2String(jsonstream);
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BackendController.java b/src/main/java/org/eclipse/openk/portal/controller/BackendController.java
new file mode 100644
index 0000000..0ad7143
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendController.java
@@ -0,0 +1,113 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+
+package org.eclipse.openk.portal.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class BackendController {
+ private static final Logger LOGGER = Logger.getLogger(BackendController.class.getName());
+ private final InputDataValuator inputDataValuator = new InputDataValuator();
+
+ public List<KeyCloakUser> getUsersForRole(String roleToCheck) {
+ List<KeyCloakUser> usersWithRole = new ArrayList<>();
+ List<KeyCloakUser> keyCloakUsers = UserCache.getInstance().getKeyCloakUsers();
+
+ for (KeyCloakUser user : keyCloakUsers) {
+ List<String> allRoles = user.getAllRoles();
+ if (allRoles == null) {
+ continue;
+ }
+
+ for (String role : allRoles) {
+ if(role.equals(roleToCheck)){
+ usersWithRole.add(user);
+ break;
+ }
+ }
+ }
+
+ return usersWithRole;
+ }
+
+
+ public JwtToken authenticate(String credentials) throws PortalException {
+ LOGGER.debug("authenticate() is called");
+
+ // valuator will throw an exception if not valid
+ inputDataValuator.checkCredentials(credentials);
+
+ LoginCredentials loginCredentials = JsonGeneratorBase.getGson().fromJson(credentials, LoginCredentials.class);
+
+ JwtToken token = null;
+ String inputUsername = loginCredentials.getUserName().toLowerCase();
+ String inputPassword = loginCredentials.getPassword();
+
+ // obtain a token from keycloak
+ token = JwtHelper.login(inputUsername, inputPassword);
+
+ if( token == null ) {
+ LOGGER.debug(credentials);
+ throw new PortalUnauthorized("Unknown User/Password");
+ }
+
+ LOGGER.debug("authenticate() succeeded.");
+ return token;
+ }
+
+ public VersionInfo getVersionInfo() {
+ LOGGER.debug("getVersionInfo() is called");
+
+ String version = getClass().getPackage().getImplementationVersion();
+ VersionInfo vi = new VersionInfo();
+ vi.setBackendVersion(version);
+
+ LOGGER.debug("getVersionInfo() is finished");
+ return vi;
+ }
+
+ public List<UserModule> getUserModuleList() {
+ LOGGER.debug("getUserModuleList() is called");
+ List<UserModule> umList = new ArrayList<>();
+
+ for (int i=0; i<UserModule.getInstance().length; i++)
+ {
+ UserModule um = new UserModule();
+ um.setModuleName(UserModule.getInstance()[i].getModuleName());
+ um.setCols(UserModule.getInstance()[i].getCols());
+ um.setRows(UserModule.getInstance()[i].getRows());
+ um.setColor(UserModule.getInstance()[i].getColor());
+ um.setLink(UserModule.getInstance()[i].getLink());
+ um.setPictureLink(UserModule.getInstance()[i].getPictureLink());
+ um.setRequiredRole(UserModule.getInstance()[i].getRequiredRole());
+
+ umList.add(um);
+ }
+
+ LOGGER.debug("getUserModuleList() is finished");
+ return umList;
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java b/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java
new file mode 100644
index 0000000..cb4b50c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BackendInvokable.java
@@ -0,0 +1,39 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.exceptions.PortalException;
+
+
+public abstract class BackendInvokable {
+
+ private String modUser;
+ private int userId;
+
+ public int getUserId() {
+ return userId;
+ }
+
+ public void setUserId(int userId) {
+ this.userId = userId;
+ }
+
+ public String getModUser() {
+ return modUser;
+ }
+
+ public void setModUser(String modUser) {
+ this.modUser = modUser;
+ }
+
+ public abstract Response invoke() throws PortalException;
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java b/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java
new file mode 100644
index 0000000..fc04dc4
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/BaseWebService.java
@@ -0,0 +1,78 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.ws.rs.core.Response;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+
+public abstract class BaseWebService {
+ private final Map<String, Long> currentTimeMeasures = new HashMap<>();
+ private final Logger logger;
+
+ public BaseWebService(Logger logger) {
+ this.logger = logger;
+ }
+
+ protected abstract void assertAndRefreshToken(String token, boolean refresh) throws PortalException;
+
+ private void startProcessing(String methodName) {
+ Long lStartingTime = System.currentTimeMillis();
+ String lookupName = buildLookupId(methodName);
+ currentTimeMeasures.put(lookupName, lStartingTime);
+
+ logger.trace(this.getClass().getName() + "." + lookupName + ": Start processing...");
+ }
+
+ protected AutoCloseable perform(final String methodName) {
+ startProcessing(methodName);
+ return () -> endProcessing(methodName);
+ }
+
+ private String buildLookupId(String func) {
+ return func + "@@" + Thread.currentThread().getId();
+ }
+
+ private void endProcessing(String methodName) {
+ String lookupName = buildLookupId(methodName);
+ if (currentTimeMeasures.containsKey(lookupName)) {
+ Long lStartingTime = currentTimeMeasures.get(lookupName);
+ currentTimeMeasures.remove(lookupName);
+
+ logger.trace(this.getClass().getName() + "." + lookupName + ": Finished processing in " + (System.currentTimeMillis() - lStartingTime) + " ms");
+ }
+
+ }
+
+ protected Response invoke(String sessionId, boolean refresh, BackendInvokable invokable)
+ {
+ try (AutoCloseable ignored = perform(invokable.getClass().getName() + ".Invoke()")) { // NOSONAR
+
+ assertAndRefreshToken(sessionId, refresh);
+
+ return invokable.invoke();
+ } catch (PortalException bee) {
+ logger.debug("Caught BackendException: " + bee.getClass().getSimpleName());
+ return Response.status(bee.getHttpStatus()).entity(PortalExceptionMapper.toJson(bee))
+ .build();
+
+ } catch (Exception e) {
+ logger.error("Unexpected exception", e);
+ return Response.status(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR).build();
+ }
+
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java b/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java
new file mode 100644
index 0000000..8d3fb8e
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ControllerImplementations.java
@@ -0,0 +1,111 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import java.util.List;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+
+public class ControllerImplementations
+{
+ private ControllerImplementations() {}
+
+ public static class GetUsers extends BackendInvokable {
+
+ @Override
+ public Response invoke() throws PortalException {
+ List<KeyCloakUser> keyCloakUserList = UserCache.getInstance().getKeyCloakUsers();
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(keyCloakUserList));
+ }
+ }
+
+ public static class GetVersionInfo extends BackendInvokable {
+ private BackendController backendController;
+
+ public GetVersionInfo(BackendController backendController) {
+ this.backendController = backendController;
+ }
+
+ @Override
+ public Response invoke() throws PortalException {
+ VersionInfo vi = backendController.getVersionInfo();
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(vi));
+ }
+ }
+
+ public static class Logout extends BackendInvokable {
+ private String accessToken;
+
+ public Logout(String accessToken) {
+ this.accessToken = accessToken;
+ }
+
+ @Override
+ public Response invoke() throws PortalException {
+ TokenManager.getInstance().logout(accessToken);
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(PortalExceptionMapper.getGeneralOKJson());
+ }
+ }
+
+ public static class CheckAuth extends BackendInvokable {
+
+ public CheckAuth() {
+ /* the implemented invoke method is only called after a successfully
+ pass of assertAndRefreshToken method of the BaseWebService class which checks
+ if the Token is active and valid */
+ }
+
+ @Override
+ public Response invoke() throws PortalException {
+ //see constructor above
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(PortalExceptionMapper.getGeneralOKJson());
+ }
+ }
+
+ public static class GetUserModulesForUser extends BackendInvokable {
+ private BackendController backendController;
+
+ public GetUserModulesForUser(BackendController backendController) {
+ this.backendController = backendController;
+ }
+
+ @Override
+ public Response invoke() throws PortalException {
+ List<UserModule> um = backendController.getUserModuleList();
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(um));
+ }
+ }
+
+ public static class GetUsersForRole extends BackendInvokable {
+ private BackendController backendController;
+ private String userRole;
+
+ public GetUsersForRole(BackendController backendController, String userRole) {
+ this.backendController = backendController;
+ this.userRole = userRole;
+ }
+
+ @Override
+ public Response invoke() throws PortalException {
+ List<KeyCloakUser> keyCloakUserList = backendController.getUsersForRole(userRole);
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(JsonGeneratorBase.getGson().toJson(keyCloakUserList));
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java b/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java
new file mode 100644
index 0000000..fc094a5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/InputDataValuator.java
@@ -0,0 +1,67 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+
+public class InputDataValuator {
+ private static final Logger LOGGER = Logger.getLogger(InputDataValuator.class.getName());
+
+ private static final String WHITELIST = "[^a-zA-ZäÄöÖüÜß?0-9().,-:;_+=!%§&/'#<>\" ]";
+
+ private void checkCredentialsRaw(String credentials) throws PortalUnauthorized {
+ if (credentials == null || credentials.isEmpty()) {
+ throw new PortalUnauthorized("No credentials provided");
+ }
+ if (credentials.length() > Globals.MAX_CREDENTIALS_LENGTH) {
+ LOGGER.warn("MaxLength of credentials exceeded");
+
+ throw new PortalUnauthorized("Invalid credentials");
+ }
+ }
+
+ public void checkCredentials(String credentials) throws PortalUnauthorized {
+ checkCredentialsRaw(credentials);
+
+ LoginCredentials obj;
+ try {
+ obj = JsonGeneratorBase.getGson().fromJson(credentials, LoginCredentials.class);
+ } catch (Exception e) { // NOSONAR
+ obj = null;
+ }
+ if (obj == null || obj.getUserName() == null || obj.getUserName().isEmpty()) {
+ LOGGER.warn("Invalid credentials provided. ");
+ throw new PortalUnauthorized("Invalid credentials");
+ }
+ }
+
+ private void checkWhitelistChars(String txt) throws PortalBadRequest { // NOSONAR 24.09.2018: There's a great possibility that we need a whitebox-charecter check for security reasons again. Because of this, we leave this code
+ checkWhitelistChars(txt, false);
+ }
+
+ private void checkWhitelistChars(String txt, boolean logTextOnError) throws PortalBadRequest {
+ // empty String is ok
+ if (txt == null || txt.isEmpty()) {
+ return;
+ }
+ String tx2 = txt.replaceAll(WHITELIST, "");
+ if (!tx2.equals(txt)) {
+ LOGGER.warn("Invalid text not matching whitelist" + (logTextOnError ? ":" + txt : ""));
+ throw new PortalBadRequest("Invalid text data");
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java b/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java
new file mode 100644
index 0000000..afa57cf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapper.java
@@ -0,0 +1,60 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+
+import javax.ws.rs.core.Response;
+import java.io.UnsupportedEncodingException;
+
+public enum ResponseBuilderWrapper {
+ INSTANCE;
+
+ public Response.ResponseBuilder getResponseBuilder( String json ) throws PortalInternalServerError {
+ return getResponseBuilder(jsonStringToBytes( json ));
+
+ }
+
+ private Response.ResponseBuilder getResponseBuilder(byte[] json) {
+ return Response.status(Globals.HTTPSTATUS_OK).entity(json)
+ .header("Content-Type", "application/json; charset=utf-8")
+ .header("X-XSS-Protection", "1; mode = block")
+ .header("X-DNS-Prefetch-Control", "off")
+ .header("X-Content-Type-Options", "nosniff")
+ .header("X-Frame-Options", "sameorigin")
+ .header("Strict-Transport-Security", "max-age=15768000; includeSubDomains")
+ .header("Cache-Control", "no-cache; no-store; must-revalidate")
+ .header("Pragma", "no-cache")
+ .header("Expires", "0")
+ .header("Access-Control-Allow-Origin", "*");
+ }
+
+ private byte[] jsonStringToBytes( String jsonString ) throws PortalInternalServerError {
+ try {
+ return jsonString.getBytes("UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new PortalInternalServerError("Unexpected Error", e);
+ }
+ }
+
+ public Response buildOKResponse(String jsonString) throws PortalException {
+ return getResponseBuilder( jsonStringToBytes( jsonString)).build();
+ }
+
+
+ public Response buildOKResponse(String jsonString, String sessionToken) throws PortalException {
+ return getResponseBuilder(jsonStringToBytes(jsonString)).header(Globals.SESSION_TOKEN_TAG, sessionToken).build();
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java b/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java
new file mode 100644
index 0000000..f38e01c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/controller/TokenManager.java
@@ -0,0 +1,147 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+
+import org.eclipse.openk.portal.auth2.model.JwtPayload;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import java.util.HashMap;
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.UserAuthentication;
+
+public class TokenManager {
+ private static final Logger LOGGER = Logger.getLogger(TokenManager.class.getName());
+
+ private static long internalSessionLengthOffsetPerc = 0L;
+
+ public static class SessionItem {
+ private long sessionCreationTime;
+ private long sessionLastAccessTime;
+
+ private String sessionId;
+ private String cookieToken;
+ private UserAuthentication user;
+ private JwtToken jwtToken;
+
+ public SessionItem(long sessionCreationTime) {
+ this.sessionCreationTime = this.sessionLastAccessTime = sessionCreationTime;
+ }
+
+ public long getSessionCreationTime() {
+ return sessionCreationTime;
+ }
+
+ public void setSessionCreationTime(long sessionCreationTime) {
+ this.sessionCreationTime = sessionCreationTime;
+ }
+
+ public long getSessionLastAccessTime() {
+ return sessionLastAccessTime;
+ }
+
+ public void setSessionLastAccessTime(long sessionLastAccessTime) {
+ this.sessionLastAccessTime = sessionLastAccessTime;
+ }
+
+ public UserAuthentication getUser() {
+ return user;
+ }
+
+ public void setUser(UserAuthentication user) {
+ this.user = user;
+ }
+
+ public JwtToken getJwtToken() {
+ return jwtToken;
+ }
+
+ public void setJwtToken(JwtToken jwtToken) {
+ this.jwtToken = jwtToken;
+ }
+
+ public String getSessionId() {
+ return sessionId;
+ }
+
+ public void setSessionId(String sessionId) {
+ this.sessionId = sessionId;
+ }
+
+ public String getCookieToken() {
+ return cookieToken;
+ }
+
+ public void setCookieToken(String cookieToken) {
+ this.cookieToken = cookieToken;
+ }
+ }
+
+ private static final TokenManager INSTANCE = new TokenManager();
+ private final HashMap<String, SessionItem> registry = new HashMap<>();
+
+ private TokenManager() {
+ }
+
+ public static TokenManager getInstance() {
+ return INSTANCE;
+ }
+
+ public void registerNewSession(JwtToken jwtToken) {
+
+ String guid = jwtToken.getAccessToken();
+ SessionItem sitem = new SessionItem(System.currentTimeMillis());
+ sitem.setJwtToken(jwtToken);
+ sitem.setSessionId(guid);
+
+ LOGGER.debug("Registered Session with JWT: " + JsonGeneratorBase.getGson().toJson(jwtToken));
+ registry.put(guid, sitem);
+ }
+
+
+ private boolean sessionHasExpired(long now, SessionItem sitem) {
+ return (now - sitem.getSessionLastAccessTime()) >
+ BackendConfig.getInstance().getInternalSessionLengthMillis() * (1 + (internalSessionLengthOffsetPerc / 100L));
+ }
+
+ public void refreshSessionIsAlive(String token, boolean refresh) throws PortalUnauthorized {
+ String accesstoken = JwtHelper.formatToken(token);
+ SessionItem sitem = registry.get(accesstoken);
+ long now = System.currentTimeMillis();
+
+ if (sitem == null || sessionHasExpired(now, sitem)) {
+ if (sitem != null) {
+ JwtPayload payLoad = JwtHelper.getPayLoad(sitem.getJwtToken());
+ String user = (payLoad != null ? payLoad.getPreferredUsername() : null);
+ LOGGER.debug("Session expired for User " + user);
+ }
+ registry.remove(token); // we're done
+ LOGGER.debug("Invalid Token: " + token);
+ throw new PortalUnauthorized("Invalid Token");
+ }
+
+ if (refresh) {
+ sitem.setSessionLastAccessTime(now);
+ }
+ }
+
+ public void logout(String token) {
+ String accesstoken = JwtHelper.formatToken(token);
+ if (registry.containsKey(accesstoken)) {
+ registry.remove(accesstoken);
+ }
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java
new file mode 100644
index 0000000..28a63f5
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalBadRequest.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalBadRequest extends PortalException {
+ public PortalBadRequest() {
+ super();
+ }
+
+ public PortalBadRequest(String message) {
+ super(message);
+ }
+
+ @Override
+ public int getHttpStatus() {
+ return Globals.HTTPSTATUS_BAD_REQUEST;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java
new file mode 100644
index 0000000..3e8ba82
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalException.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+public abstract class PortalException extends Exception { // NOSONAR
+ public PortalException() {
+ super();
+ }
+
+ public PortalException(String message) {
+ super(message);
+ }
+
+ public PortalException(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+ public abstract int getHttpStatus();
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java
new file mode 100644
index 0000000..db1b187
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapper.java
@@ -0,0 +1,43 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.viewmodel.ErrorReturn;
+import org.eclipse.openk.portal.viewmodel.GeneralReturnItem;
+
+public final class PortalExceptionMapper {
+ private PortalExceptionMapper() {}
+
+ public static String unknownErrorToJson() {
+ ErrorReturn er = new ErrorReturn();
+ er.setErrorText("Unknown Error");
+ er.setErrorCode(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR);
+ return JsonGeneratorBase.getGson().toJson(er);
+ }
+
+ public static String toJson(PortalException e) {
+ ErrorReturn er = new ErrorReturn();
+ er.setErrorText(e.getMessage());
+ er.setErrorCode(e.getHttpStatus());
+ return JsonGeneratorBase.getGson().toJson(er);
+ }
+
+ public static String getGeneralErrorJson() {
+ return JsonGeneratorBase.getGson().toJson(new GeneralReturnItem("NOK"));
+ }
+
+ public static String getGeneralOKJson() {
+ return JsonGeneratorBase.getGson().toJson(new GeneralReturnItem("OK"));
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java
new file mode 100644
index 0000000..dd5937e
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalForbidden.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalForbidden extends PortalException {
+ public PortalForbidden() {
+ super();
+ }
+
+ public PortalForbidden(String message) {
+ super(message);
+ }
+
+ @Override
+ public int getHttpStatus() {
+ return Globals.HTTPSTATUS_FORBIDDEN;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java
new file mode 100644
index 0000000..5c446b3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalInternalServerError.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalInternalServerError extends PortalException {
+ public PortalInternalServerError(String message) {
+ super(message);
+ }
+
+ public PortalInternalServerError(String message, Throwable throwable) {
+ super(message, throwable);
+ }
+
+ @Override
+ public int getHttpStatus() {
+ return Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java
new file mode 100644
index 0000000..acee53c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalNotFound.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalNotFound extends PortalException {
+ public PortalNotFound() {
+ super();
+ }
+
+ public PortalNotFound(String message) {
+ super(message);
+ }
+
+ @Override
+ public int getHttpStatus() {
+ return Globals.HTTPSTATUS_NOT_FOUND;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java b/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java
new file mode 100644
index 0000000..bc264cf
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/exceptions/PortalUnauthorized.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import org.eclipse.openk.portal.common.Globals;
+
+public class PortalUnauthorized extends PortalException {
+ public PortalUnauthorized() {
+ super();
+ }
+
+ public PortalUnauthorized(String message) {
+ super(message);
+ }
+
+ @Override
+ public int getHttpStatus() {
+ return Globals.HTTPSTATUS_UNAUTHORIZED;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/HealthCheck.java b/src/main/java/org/eclipse/openk/portal/health/base/HealthCheck.java
new file mode 100644
index 0000000..f6bc66c
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/HealthCheck.java
@@ -0,0 +1,17 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+public abstract class HealthCheck {
+
+ protected abstract Result check() throws Exception; // NOSONAR
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java b/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java
new file mode 100644
index 0000000..34ebd90
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/HealthChecker.java
@@ -0,0 +1,47 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+*/
+package org.eclipse.openk.portal.health.base;
+
+import org.apache.log4j.Logger;
+
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+public class HealthChecker {
+ private static final Logger logger = Logger.getLogger(HealthChecker.class);
+
+ private List<HealthCheck> registeredHealthChecks = new LinkedList<>();
+ private Map<HealthCheck, String> namingMap = new HashMap<>();
+
+ public void register( String title, HealthCheck hc ) {
+ namingMap.put(hc, title);
+ registeredHealthChecks.add(hc);
+ }
+
+ public List<NamedHealthCheckResult> performHealthChecks() {
+ List<NamedHealthCheckResult> hcList = new LinkedList<>();
+ for( HealthCheck hc : registeredHealthChecks) {
+ try {
+ hcList.add(new NamedHealthCheckResult(namingMap.get(hc), hc.check()));
+
+ } catch (Throwable t) { // NOSONAR we definately want to catch everything here!!!
+ logger.error("Error during healthcheck", t);
+ hcList.add(new NamedHealthCheckResult(namingMap.get(hc),
+ Result.unhealthy("Exception during test: "+t+" -> See Log!")));
+ }
+ }
+ return hcList;
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java b/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java
new file mode 100644
index 0000000..9726cb9
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResult.java
@@ -0,0 +1,53 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import com.google.gson.GsonBuilder;
+
+import java.util.List;
+
+public class NamedHealthCheckResult {
+ private String name;
+ private Result result;
+
+ public NamedHealthCheckResult( String name, Result result ) {
+ this.name = name;
+ this.result = result;
+ }
+
+ public String toJson() {
+ StringBuffer buffer = new StringBuffer(); // NOSONAR - _fd we don't a new dependency because of this
+ buffer.append("\""+name+"\":");
+ buffer.append(new GsonBuilder().disableHtmlEscaping().create().toJson(result));
+ return buffer.toString();
+ }
+
+ public static String toJson(List<NamedHealthCheckResult> resultArray ) {
+ StringBuilder builder = new StringBuilder();
+ builder.append('{');
+ for( int i=0; i < resultArray.size(); i++ ) {
+ builder.append(resultArray.get(i).toJson());
+ if( i+1 < resultArray.size() ) {
+ builder.append(',');
+ }
+ }
+ return builder.append('}').toString();
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Result getResult() {
+ return result;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/base/Result.java b/src/main/java/org/eclipse/openk/portal/health/base/Result.java
new file mode 100644
index 0000000..6ff7de7
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/base/Result.java
@@ -0,0 +1,41 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+
+public class Result {
+ private boolean healthy;
+ private String message;
+
+ private Result() {}
+
+ public static Result healthy() {
+ Result res = new Result();
+ res.healthy = true;
+ return res;
+ }
+
+ public static Result unhealthy(String message) {
+ Result res = new Result();
+ res.healthy = false;
+ res.message = message;
+ return res;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public boolean isHealthy() {
+ return healthy;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java b/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java
new file mode 100644
index 0000000..80a7b52
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheck.java
@@ -0,0 +1,37 @@
+/*
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.impl;
+
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.health.base.HealthCheck;
+import org.eclipse.openk.portal.health.base.Result;
+
+public class KeyCloakPresentHealthCheck extends HealthCheck {
+
+ protected boolean checkit() throws PortalInternalServerError {
+ return JwtHelper.serviceAvailable();
+ }
+
+ @Override
+ protected Result check() throws Exception {
+ if( checkit() ) {
+ return Result.healthy();
+ }
+ else {
+ BackendConfig gc = BackendConfig.getInstance();
+ String msg = gc.getAuthServerUrl() + "/" + gc.getKeycloakRealm();
+ return Result.unhealthy("KeyCloak-Service not available: "+msg);
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java b/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java
new file mode 100644
index 0000000..4f6fb0a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/BackendRestService.java
@@ -0,0 +1,184 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.rest;
+
+import javax.ws.rs.*;
+
+import org.apache.log4j.Logger;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.controller.BackendController;
+import org.eclipse.openk.portal.controller.BaseWebService;
+import org.eclipse.openk.portal.controller.ControllerImplementations;
+import org.eclipse.openk.portal.controller.ResponseBuilderWrapper;
+import org.eclipse.openk.portal.controller.TokenManager;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalExceptionMapper;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.health.base.HealthChecker;
+import org.eclipse.openk.portal.health.base.NamedHealthCheckResult;
+import org.eclipse.openk.portal.health.impl.KeyCloakPresentHealthCheck;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+
+@Path("/beservice")
+public class BackendRestService extends BaseWebService {
+ private static final Logger logger = Logger.getLogger(BackendRestService.class.getName());
+ private static final boolean DEVELOP_MODE;
+ private static final String LET_ME_IN = "LET_ME_IN";
+
+ static {
+ // determine static VersionInfo
+ String versionString = BackendRestService.class.getPackage().getImplementationVersion().toUpperCase();
+ DEVELOP_MODE = versionString.contains("DEVELOP") || versionString.contains("SNAPSHOT");
+ }
+ @Context
+ private UriInfo uriInfo;
+
+ public BackendRestService() {
+ super(logger);
+ }
+
+ @POST
+ @Path("/login")
+ @Produces("application/json")
+ @Consumes("application/json")
+ public Response login(String loginCredentials) {
+
+ try (AutoCloseable ignored = perform("login()")) { // NOSONAR
+ JwtToken jwtToken;
+
+ if (loginCredentials == null || loginCredentials.isEmpty()) {
+ logger.info("Login Error. Empty Credentials");
+ throw new PortalUnauthorized();
+ } else {
+ // will throw exception if it fails
+ jwtToken = new BackendController().authenticate(loginCredentials);
+ TokenManager tokenManager = TokenManager.getInstance();
+ tokenManager.registerNewSession(jwtToken);
+ logger.debug("Login Success");
+ }
+
+ return createJsonResponse(jwtToken);
+ } catch (Exception e) {
+ logger.info("Login Error. Invalid KeyCloak Credentials/Settings");
+ return responseFromException(e);
+ }
+ }
+
+ private Response createJsonResponse(Object obj) throws PortalException {
+ Response.ResponseBuilder rb = ResponseBuilderWrapper.INSTANCE
+ .getResponseBuilder(obj != null ? JsonGeneratorBase.getGson().toJson(obj) : PortalExceptionMapper.getGeneralOKJson());
+
+ return rb.build();
+ }
+
+ @GET
+ @Path("/checkAuth")
+ @Produces("application/json")
+ public Response checkAuth(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+ logger.trace("checkAuth portal called");
+ return invoke(accessToken, true, new ControllerImplementations.CheckAuth());
+ }
+
+ @GET
+ @Path("/logout")
+ @Produces("application/json")
+ public Response logout(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+ return invoke(accessToken, false, new ControllerImplementations.Logout(accessToken));
+ }
+
+ @GET
+ @Path("/versionInfo/")
+ @Produces("application/json")
+ public Response getVersionInfo() {
+ try (AutoCloseable ignored = perform("getVersionInfo()")) { // NOSONAR
+ VersionInfo versionInfo = new BackendController().getVersionInfo();
+ return createJsonResponse(versionInfo);
+ } catch (Exception e) {
+ return responseFromException(e);
+ }
+ }
+
+ @GET
+ @Path("/userModulesForUser/")
+ @Produces("application/json")
+ public Response getUserModulesForUser(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+ return invoke(accessToken, false, new ControllerImplementations.GetUserModulesForUser(new BackendController()));
+ }
+
+ @GET
+ @Path("/usersForRole/{userRole}")
+ @Produces("application/json")
+ public Response getUsersForRole(@PathParam("userRole") String userRole,
+ @HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+ return invoke(accessToken, false, new ControllerImplementations.GetUsersForRole(new BackendController(),userRole));
+ }
+
+ @GET
+ @Path("/users")
+ @Produces("application/json")
+ public Response getUsers(@HeaderParam(value = Globals.KEYCLOAK_AUTH_TAG) String accessToken) {
+ return invoke(accessToken, false, new ControllerImplementations.GetUsers());
+ }
+
+ @GET
+ @Path("/healthcheck")
+ @Produces("application/json")
+ public Response getHealthCheck() {
+ HealthChecker hc = new HealthChecker();
+ hc.register("Keycloak present", new KeyCloakPresentHealthCheck());
+
+ String returnJson = NamedHealthCheckResult.toJson(hc.performHealthChecks());
+
+ try {
+ return ResponseBuilderWrapper.INSTANCE.buildOKResponse(returnJson);
+ } catch (PortalException e) {
+ logger.error("unexpected error", e);
+ return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
+ }
+ }
+
+ private boolean isBackdoor( String sessionId ) {
+ // backdoor is only available when the version(POM) contains "DEVELOP" or "SNAPSHOT"
+ return DEVELOP_MODE && LET_ME_IN.equals(sessionId);
+ }
+
+ @Override
+ protected void assertAndRefreshToken(String token, boolean refresh) throws PortalUnauthorized {
+ if (isBackdoor(token)) {
+ return;
+ }
+ TokenManager.getInstance().refreshSessionIsAlive(token, refresh);
+
+ }
+
+ private Response responseFromException(Exception e) {
+ int errcode;
+ String retJson;
+
+ if (e instanceof PortalException) {
+ logger.error("Caught BackendException", e);
+ errcode = ((PortalException) e).getHttpStatus();
+ retJson = PortalExceptionMapper.toJson((PortalException) e);
+ return Response.status(errcode).entity(retJson).build();
+ } else {
+ logger.error("Unexpected exception", e);
+ return Response.status(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR).entity(PortalExceptionMapper.getGeneralErrorJson()).build();
+ }
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java b/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java
new file mode 100644
index 0000000..42c8d50
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/rest/RestServiceConfiguration.java
@@ -0,0 +1,29 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.rest;
+
+
+import java.util.HashSet;
+import java.util.Set;
+
+public class RestServiceConfiguration extends javax.ws.rs.core.Application {
+ public RestServiceConfiguration() {
+ // Standard Contstructor needed
+ }
+
+ @Override
+ public Set<Class<?>> getClasses() {
+ Set<Class<?>> restServicesClasses = new HashSet<>();
+ restServicesClasses.add(BackendRestService.class);
+ return restServicesClasses;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java b/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java
new file mode 100644
index 0000000..1064078
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/ErrorReturn.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import java.io.Serializable;
+
+public class ErrorReturn implements Serializable {
+
+ private static final long serialVersionUID = -4653198875478337413L;
+ private String errorText;
+ private int errorCode;
+
+ public String getErrorText() {
+ return errorText;
+ }
+ public void setErrorText(String errorText) {
+ this.errorText = errorText;
+ }
+ public int getErrorCode() {
+ return errorCode;
+ }
+ public void setErrorCode(int errorCode) {
+ this.errorCode = errorCode;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java b/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java
new file mode 100644
index 0000000..a54f7d0
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItem.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+
+public class GeneralReturnItem {
+ private String ret;
+
+ public GeneralReturnItem( String ret ) {
+ this.ret = ret;
+}
+ public String getRet() {
+ return ret;
+ }
+
+ public void setRet(String ret) {
+ this.ret = ret;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java b/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java
new file mode 100644
index 0000000..6c80d69
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/LoginCredentials.java
@@ -0,0 +1,33 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+public class LoginCredentials {
+ private String userName;
+ private String password;
+
+ public String getUserName() {
+ return userName;
+ }
+
+ public void setUserName(String userName) {
+ this.userName = userName;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java
new file mode 100644
index 0000000..acb75f6
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserAuthentication.java
@@ -0,0 +1,69 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+public class UserAuthentication {
+
+ private int id;
+ private boolean selected;
+ private String username;
+ private String password;
+ private String name;
+ private boolean specialUser;
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public boolean isSelected() {
+ return selected;
+ }
+
+ public void setSelected(boolean selected) {
+ this.selected = selected;
+ }
+
+ public String getPassword() {
+ return password;
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public boolean isSpecialUser() {
+ return specialUser;
+ }
+
+ public void setSpecialUser(boolean specialUser) {
+ this.specialUser = specialUser;
+ }
+
+ public String getUsername() {
+ return username;
+ }
+ public void setUsername(String username) {
+ this.username = username;
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java
new file mode 100644
index 0000000..d1a671a
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserCache.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+
+public class UserCache {
+
+ private static final UserCache USERCACHE_INSTANCE = new UserCache();
+ private final List<KeyCloakUser> keyCloakUsers = new ArrayList<>();
+
+ private UserCache(){
+ }
+
+ public static UserCache getInstance() {
+ return USERCACHE_INSTANCE;
+ }
+
+ public List<KeyCloakUser> getKeyCloakUsers() {
+ synchronized (keyCloakUsers){
+ return keyCloakUsers;
+ }
+ }
+
+ public void setKeyCloakUsers(List<KeyCloakUser> keyCloakUsers) {
+ synchronized (this.keyCloakUsers){
+ this.keyCloakUsers.clear();
+ this.keyCloakUsers.addAll(keyCloakUsers);
+ }
+ }
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java b/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java
new file mode 100644
index 0000000..70c18d3
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/UserModule.java
@@ -0,0 +1,80 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+
+public class UserModule {
+
+ private static String configFileName = "moduleConfigDevLocal.json";
+ private String name;
+ private Integer cols;
+ private Integer rows;
+ private String color;
+ private String link;
+ private String pictureLink;
+ private String requiredRole;
+
+ private static UserModule[] instance;
+
+ public static synchronized UserModule[] getInstance() {
+ if (instance == null) {
+ String jsonConfig = loadJsonConfig();
+ instance = JsonGeneratorBase.getGson().fromJson(jsonConfig, UserModule[].class);
+ }
+
+ return instance;
+ }
+
+ private static String loadJsonConfig() {
+ ResourceLoaderBase resourceLoaderBase = new ResourceLoaderBase();
+ return resourceLoaderBase.loadStringFromResource(configFileName);
+ }
+
+ public String getModuleName() { return name; }
+
+ public void setModuleName(String name) { this.name = name; }
+
+ public Integer getCols() { return cols; }
+
+ public void setCols(Integer cols) { this.cols = cols; }
+
+ public Integer getRows() { return rows; }
+
+ public void setRows(Integer rows) { this.rows = rows; }
+
+ public String getColor() { return color; }
+
+ public void setColor(String color) { this.color = color; }
+
+ public String getLink() { return link; }
+
+ public void setLink(String link) { this.link = link; }
+
+ public String getPictureLink() { return pictureLink; }
+
+ public void setPictureLink(String pictureLink) { this.pictureLink = pictureLink; }
+
+ public String getRequiredRole() { return requiredRole; }
+
+ public void setRequiredRole(String role) { this.requiredRole = role; }
+
+ public static String getConfigFileName() {
+ return configFileName;
+ }
+
+ public static void setConfigFileName(String configFileName) {
+ UserModule.configFileName = configFileName;
+ }
+
+}
diff --git a/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java b/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java
new file mode 100644
index 0000000..57bf001
--- /dev/null
+++ b/src/main/java/org/eclipse/openk/portal/viewmodel/VersionInfo.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+public class VersionInfo {
+ private String backendVersion;
+
+ public String getBackendVersion() {
+ return backendVersion;
+ }
+
+ public void setBackendVersion(String backendVersion) {
+ this.backendVersion = backendVersion;
+ }
+
+
+}
diff --git a/src/main/resources/_backendConfigCustom.json b/src/main/resources/_backendConfigCustom.json
new file mode 100644
index 0000000..430658e
--- /dev/null
+++ b/src/main/resources/_backendConfigCustom.json
@@ -0,0 +1,10 @@
+{
+ "internalSessionLengthMillis": 3600000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://entjava002:8080/",
+ "keycloakRealm": "elogbook",
+ "keycloakClient": "elogbook-backend",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "admin",
+ "maxLoadUsers": 1000
+}
\ No newline at end of file
diff --git a/src/main/resources/_moduleConfigCustom.json b/src/main/resources/_moduleConfigCustom.json
new file mode 100644
index 0000000..61e59f1
--- /dev/null
+++ b/src/main/resources/_moduleConfigCustom.json
@@ -0,0 +1,39 @@
+[
+ {
+ "name": "Betriebstagebuch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:8088/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+ {
+ "name": "Einspeisemanagement",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+ "requiredRole": "feedin-management-access"
+ },
+ {
+ "name": "Geplante Maßnahmen",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/64-geplante-netzmassnahme",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ }
+]
diff --git a/src/main/resources/backendConfigDevLocal.json b/src/main/resources/backendConfigDevLocal.json
new file mode 100644
index 0000000..38dd236
--- /dev/null
+++ b/src/main/resources/backendConfigDevLocal.json
@@ -0,0 +1,10 @@
+{
+ "internalSessionLengthMillis": 3600000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://entopkon:8080/",
+ "keycloakRealm": "Elogbook",
+ "keycloakClient": "elogbook-backend",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "admin",
+ "maxLoadUsers": 1000
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigDevServer.json b/src/main/resources/backendConfigDevServer.json
new file mode 100644
index 0000000..04e1609
--- /dev/null
+++ b/src/main/resources/backendConfigDevServer.json
@@ -0,0 +1,10 @@
+{
+ "internalSessionLengthMillis": 3600000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://localhost:8080/",
+ "keycloakRealm": "Elogbook",
+ "keycloakClient": "elogbook-backend",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "admin",
+ "maxLoadUsers": 1000
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigDocker.json b/src/main/resources/backendConfigDocker.json
new file mode 100644
index 0000000..4820cf5
--- /dev/null
+++ b/src/main/resources/backendConfigDocker.json
@@ -0,0 +1,10 @@
+{
+ "internalSessionLengthMillis": 3600000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://172.25.0.66:8888/",
+ "keycloakRealm": "portaldocker",
+ "keycloakClient": "portal-docker",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "admin",
+ "maxLoadUsers": 1000
+}
\ No newline at end of file
diff --git a/src/main/resources/backendConfigProduction.json b/src/main/resources/backendConfigProduction.json
new file mode 100644
index 0000000..1ed733e
--- /dev/null
+++ b/src/main/resources/backendConfigProduction.json
@@ -0,0 +1,10 @@
+{
+ "internalSessionLengthMillis": 46800000,
+ "reloadUsersInSec": 300,
+ "authServerUrl": "http://localhost:8380/",
+ "keycloakRealm": "OpenKRealm",
+ "keycloakClient": "elogbook-backend",
+ "keycloakAdmin": "admin",
+ "keycloakPW": "admin",
+ "maxLoadUsers": 1000
+}
diff --git a/src/main/resources/moduleConfigDevLocal.json b/src/main/resources/moduleConfigDevLocal.json
new file mode 100644
index 0000000..5a4df1a
--- /dev/null
+++ b/src/main/resources/moduleConfigDevLocal.json
@@ -0,0 +1,76 @@
+[
+ {
+ "name": "Betriebstagebuch local 4200",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:4200/",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Betriebstagebuch local 8080",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:8080/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+ {
+ "name": "Einspeisemanagement",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+ "requiredRole": "feedin-management-access"
+ },
+ {
+ "name": "Geplante Maßnahmen",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:4220/",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ },
+ {
+ "name": "Kontaktstammdaten",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4222",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ },
+ {
+ "name": "Kontaktstammdaten local 8080",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:8080/contactdatabase",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ },
+ {
+ "name": "Kontaktstammdaten local 4200",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:4200",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ }
+]
diff --git a/src/main/resources/moduleConfigDevServer.json b/src/main/resources/moduleConfigDevServer.json
new file mode 100644
index 0000000..be2673b
--- /dev/null
+++ b/src/main/resources/moduleConfigDevServer.json
@@ -0,0 +1,121 @@
+[
+ {
+ "name": "Betriebstagebuch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:8085/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Betriebstagebuch (Web)",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://87.128.212.254:8880/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "plannedGridMeasures",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+ {
+ "name": "Einspeisemanagement",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+ "requiredRole": "feedin-management-access"
+ },
+ {
+ "name": "Geplante Maßnahmen",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://172.18.22.160:8880/plannedGridMeasures",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ },
+ {
+ "name": "Geplante Maßnahmen (Web)",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://87.128.212.254:8880/plannedGridMeasures",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ },
+ {
+ "name": "Kontaktstammdaten",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4222",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ },
+ {
+ "name": "Kontaktstammdaten Feature Branch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4224",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ },
+ {
+ "name": "SIT DEV",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4223",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ },
+ {
+ "name": "SIT Feature Branch - A",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4225",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ },
+ {
+ "name": "SIT Feature Branch - B",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4229",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ },
+ {
+ "name": "SIT Feature Backend",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://entdockergss:4226",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ },
+ {
+ "name": "SIT Localhost",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:4200",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ }
+]
diff --git a/src/main/resources/moduleConfigDocker.json b/src/main/resources/moduleConfigDocker.json
new file mode 100644
index 0000000..63832d7
--- /dev/null
+++ b/src/main/resources/moduleConfigDocker.json
@@ -0,0 +1,39 @@
+[
+ {
+ "name": "Betriebstagebuch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:8080/ElogbookFrontend",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+ {
+ "name": "Einspeisemanagement",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/20-eisman",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+ "requiredRole": "feedin-management-access"
+ },
+ {
+ "name": "Geplante Maßnahmen",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://localhost:8080/GridMeasuresFrontend",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ }
+]
diff --git a/src/main/resources/moduleConfigProduction.json b/src/main/resources/moduleConfigProduction.json
new file mode 100644
index 0000000..fd8f7fd
--- /dev/null
+++ b/src/main/resources/moduleConfigProduction.json
@@ -0,0 +1,57 @@
+[
+ {
+ "name": "Betriebstagebuch",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://169.50.13.154/elogbookFE",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg",
+ "requiredRole": "elogbook-access"
+
+ },
+ {
+ "name": "Bereitschaftsplanung",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://www.openkonsequenz.de/anwender/11-geplante-projekte/94-bereitschaftsplan",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_bereitschaftsplan_57882047.jpg",
+ "requiredRole": "planning-access"
+ },
+ {
+ "name": "Einspeisemanagement",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "https://169.50.13.154/eisman",
+ "pictureLink": "https://www.openkonsequenz.de/medien/cache/main_image/l_ok_module6.jpg",
+ "requiredRole": "feedin-management-access"
+ },
+ {
+ "name": "Geplante Maßnahmen",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://169.50.13.154/plannedGridMeasures",
+ "pictureLink": "https://www.openkonsequenz.de//components/com_flexicontent/librairies/phpthumb/phpThumb.php?src=/medien/cache/main_image/l_ok_module5.jpg",
+ "requiredRole": "planned-policies-access"
+ },
+ {
+ "name": "Kontaktstammdaten",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://169.50.13.154/contactdatabase",
+ "pictureLink": "assets/img/kontaktstammdaten_kachel.jpg",
+ "requiredRole": "kon-access"
+ },
+ {
+ "name": "Störungsinformationstool",
+ "cols": 1,
+ "rows": 1,
+ "color": "#ffffff",
+ "link": "http://169.50.13.154/gridfailureinformation",
+ "pictureLink": "assets/img/stoerungsinformation_kachel.jpg",
+ "requiredRole": "grid-failure-access"
+ }
+]
diff --git a/src/main/webapp/WEB-INF/keycloak.json b/src/main/webapp/WEB-INF/keycloak.json
new file mode 100644
index 0000000..40ff32c
--- /dev/null
+++ b/src/main/webapp/WEB-INF/keycloak.json
@@ -0,0 +1,9 @@
+{
+ "realm": "elogbook",
+ "auth-server-url": "http://entjava002:8080/auth",
+ "ssl-required": "external",
+ "resource": "elogbook-backend",
+ "public-client": true,
+ "enable-cors": true,
+ "use-resource-role-mappings": true
+}
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/logger.xml b/src/main/webapp/WEB-INF/logger.xml
new file mode 100644
index 0000000..a0b8f3b
--- /dev/null
+++ b/src/main/webapp/WEB-INF/logger.xml
@@ -0,0 +1,66 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE log4j:configuration PUBLIC
+ "-//APACHE//DTD LOG4J 1.2//EN"
+ "http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/doc-files/log4j.dtd">
+<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/">
+
+ <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
+ <param name="Threshold" value="DEBUG"/>
+ <param name="Target" value="System.out"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+ </layout>
+ </appender>
+
+ <appender name="Socket" class="org.apache.log4j.net.SocketAppender">
+ <param name="remoteHost" value="127.0.0.1"/>
+ <param name="port" value="4560"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+ </layout>
+ </appender>
+
+ <!-- Issue: das Verzeichnis muss existieren ... -->
+ <appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
+ <param name="Threshold" value="TRACE"/>
+ <param name="File" value="${catalina.base}/logs/portal-openk.backend.log"/>
+ <param name="Append" value="true"/>
+ <param name="DatePattern" value="'.'yyyy-MM-dd"/>
+ <layout class="org.apache.log4j.PatternLayout">
+ <param name="ConversionPattern" value="[%d{yyyy.MM.dd HH:mm:ss}] [%p] [%c] %m%n"/>
+ </layout>
+ </appender>
+
+ <!-- Default Logging configuration beginnend mit org.eclipse (= alle Packages) -->
+ <category name="org.eclipse">
+ <priority value="INFO"/>
+ <!--<priority value="DEBUG"/> -->
+ <!--<priority value="ERROR"/> -->
+ <appender-ref ref="CONSOLE"/>
+ <!--<appender-ref ref="Socket"/> -->
+ <!--<appender-ref ref="FILE"/> -->
+ <!--<appender-ref ref="SYSLOG"/> -->
+ <appender-ref ref="FILE"/>
+ </category>
+ <category name="org.jboss.resteasy">
+ <priority value="WARN"/>
+ <!--<priority value="DEBUG"/> -->
+ <!--<priority value="ERROR"/> -->
+ <appender-ref ref="CONSOLE"/>
+ <!--<appender-ref ref="Socket"/> -->
+ <!--<appender-ref ref="FILE"/> -->
+ <!--<appender-ref ref="SYSLOG"/> -->
+ <appender-ref ref="FILE"/>
+ </category>
+ <category name="javax.persistence.Persistence">
+ <priority value="INFO"/>
+ <!--<priority value="DEBUG"/> -->
+ <!--<priority value="ERROR"/> -->
+ <appender-ref ref="CONSOLE"/>
+ <!--<appender-ref ref="Socket"/> -->
+ <!--<appender-ref ref="FILE"/> -->
+ <!--<appender-ref ref="SYSLOG"/> -->
+ <appender-ref ref="FILE"/>
+ </category>
+
+</log4j:configuration>
\ No newline at end of file
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..2ce8042
--- /dev/null
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,49 @@
+<web-app id="WebApp_ID" version="2.4"
+ xmlns="http://java.sun.com/xml/ns/j2ee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
+ http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
+ <display-name>Restful Web Application</display-name>
+
+ <servlet>
+ <servlet-name>jersey-serlvet</servlet-name>
+ <servlet-class>
+ org.glassfish.jersey.servlet.ServletContainer
+ </servlet-class>
+ <init-param>
+ <param-name>jersey.config.server.provider.packages</param-name>
+ <param-value>org.eclipse.openk.portal.rest</param-value>
+ </init-param>
+ <load-on-startup>1</load-on-startup>
+
+ </servlet>
+
+
+ <servlet-mapping>
+ <servlet-name>jersey-serlvet</servlet-name>
+ <url-pattern>/rest/*</url-pattern>
+ </servlet-mapping>
+
+ <servlet>
+ <servlet-name>log4j-init</servlet-name>
+ <servlet-class>org.eclipse.openk.portal.common.util.LoggerUtil</servlet-class>
+ <init-param>
+ <param-name>log4j-init-file</param-name>
+ <param-value>WEB-INF/logger.xml</param-value>
+ </init-param>
+ <load-on-startup>0</load-on-startup>
+ </servlet>
+
+ <servlet>
+ <servlet-name>InitBackendConfig</servlet-name>
+ <servlet-class>org.eclipse.openk.portal.common.InitBackendConfig</servlet-class>
+ <load-on-startup>2</load-on-startup>
+ </servlet>
+
+ <servlet>
+ <servlet-name>InitUserCacheJob</servlet-name>
+ <servlet-class>org.eclipse.openk.portal.common.InitUserCacheJob</servlet-class>
+ <load-on-startup>3</load-on-startup>
+ </servlet>
+
+</web-app>
diff --git a/src/main/webapp/index.html b/src/main/webapp/index.html
new file mode 100644
index 0000000..97b5341
--- /dev/null
+++ b/src/main/webapp/index.html
@@ -0,0 +1,10 @@
+<!DOCTYPE html>
+<html>
+<head>
+<meta charset="UTF-8">
+<title>Insert title here</title>
+</head>
+<body>
+it works!
+</body>
+</html>
\ No newline at end of file
diff --git a/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java b/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java
new file mode 100644
index 0000000..a441a8a
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/BackendConfigTest.java
@@ -0,0 +1,34 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class BackendConfigTest {
+ @Test
+ public void testConfig() {
+ BackendConfig bc = BackendConfig.getInstance();
+ assertEquals( 3600000, (int)bc.getInternalSessionLengthMillis() );
+ assertEquals( 300 , (int)bc.getReloadUsersInSec());
+ assertEquals( "http://entopkon:8080/", bc.getAuthServerUrl() );
+ assertEquals( "Elogbook", bc.getKeycloakRealm());
+ assertEquals( "elogbook-backend", bc.getKeycloakClient());
+ assertEquals( "admin", bc.getKeycloakAdmin() );
+ assertEquals( "admin", bc.getKeycloakPW() );
+ assertEquals( "backendConfigDevLocal.json", BackendConfig.getConfigFileName() );
+ BackendConfig.setConfigFileName("backendConfigProduction.json");
+ assertEquals( "backendConfigProduction.json", BackendConfig.getConfigFileName() );
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java b/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java
new file mode 100644
index 0000000..f805370
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/GsonUTCDateAdapterTest.java
@@ -0,0 +1,49 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import com.google.gson.JsonElement;
+import com.google.gson.JsonSerializationContext;
+import org.junit.Test;
+
+import java.lang.reflect.Type;
+import java.util.Calendar;
+
+public class GsonUTCDateAdapterTest {
+
+ @Test
+ public void serializeTest() {
+ GsonUTCDateAdapter gsonUTCDateAdapter = new GsonUTCDateAdapter();
+ Calendar calendar = Calendar.getInstance();
+ java.util.Date date = calendar.getTime();
+ Type type = new Type() {
+ @Override
+ public String getTypeName() {
+ return null;
+ }
+ };
+ JsonSerializationContext jsonSerializationContext = new JsonSerializationContext() {
+ @Override
+ public JsonElement serialize(Object o) {
+ return null;
+ }
+
+ @Override
+ public JsonElement serialize(Object o, Type type) {
+ return null;
+ }
+ };
+
+ gsonUTCDateAdapter.serialize(date, type, jsonSerializationContext);
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java b/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java
new file mode 100644
index 0000000..983c909
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitBackendConfigTest.java
@@ -0,0 +1,49 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+public class InitBackendConfigTest {
+
+ private InitBackendConfig initBackendConfig = new InitBackendConfig();
+
+ @Test
+ public void testSetConfigFiles() throws Exception {
+ Whitebox.invokeMethod(initBackendConfig, "setConfigFiles", "DevLocal");
+ }
+
+ private void testGeneric(String environment ) throws Exception {
+ Whitebox.invokeMethod(initBackendConfig, "setConfigFiles", environment);
+ }
+
+ @Test
+ public void testCombinations() throws Exception {
+
+ testGeneric("DevLocal");
+ testGeneric("DevLocal");
+
+ testGeneric("DevServer");
+ testGeneric("DevServer");
+
+ testGeneric("Custom");
+ testGeneric("Custom");
+
+ testGeneric(null);
+ testGeneric(null);
+
+ testGeneric("");
+ testGeneric("");
+
+}
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java b/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java
new file mode 100644
index 0000000..ef2455d
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/InitUserCacheJobTest.java
@@ -0,0 +1,27 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+import javax.servlet.ServletException;
+
+public class InitUserCacheJobTest extends ResourceLoaderBase {
+
+ @Test
+ public void testInit() throws ServletException {
+ InitUserCacheJob job = new InitUserCacheJob();
+ job.init();
+ // Test only covers Code!
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java b/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java
new file mode 100644
index 0000000..cf4f250
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/UserCacheTimerTaskTest.java
@@ -0,0 +1,142 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+import static org.easymock.EasyMock.expect;
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+
+import com.google.gson.reflect.TypeToken;
+import java.lang.reflect.Type;
+import java.util.ArrayList;
+import java.util.List;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRoles;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.eclipse.openk.portal.viewmodel.UserCache;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(JwtHelper.class)
+public class UserCacheTimerTaskTest extends ResourceLoaderBase {
+
+ private UserCacheTimerTask task;
+
+ @Before
+ public void prepareTests() {
+ task = new UserCacheTimerTask();
+ }
+
+ @Test
+ public void testGetKeyCloakUsersFromToken() throws Exception {
+ String json = super.loadStringFromResource("JWTAdmin.json");
+ JwtToken jwt = getGson().fromJson(json, JwtToken.class);
+
+ String jsonKeyCloakUser = super.loadStringFromResource("testKeyCloakUsers.json");
+ Type listTypeKeyCloakUser = new TypeToken<List<KeyCloakUser>>(){}.getType();
+ List<KeyCloakUser> keyCloakUsersList = getGson().fromJson(jsonKeyCloakUser, listTypeKeyCloakUser);
+ keyCloakUsersList.remove(1);
+ keyCloakUsersList.remove(1);
+
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakClientAndRealmRoles.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ PowerMock.mockStatic(JwtHelper.class);
+ expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(jwt);
+ expect(JwtHelper.getUsers(jwt, BackendConfig.getInstance().getMaxLoadUsers())).andReturn(keyCloakUsersList);
+ expect(JwtHelper.getRolesForUser(jwt, keyCloakUsersList.get(0).getId())).andReturn(keyCloakRolesList);
+
+ PowerMock.replayAll();
+ task.run();
+ PowerMock.verifyAll();
+
+ List<KeyCloakUser> keyCloakUsersResult = UserCache.getInstance().getKeyCloakUsers();
+
+ assertEquals(1, keyCloakUsersResult.size());
+ assertEquals(18, keyCloakUsersResult.get(0).getAllRoles().size());
+ assertEquals("feedin-management-access", keyCloakUsersResult.get(0).getAllRoles().get(0));
+ assertEquals("testclientrole", keyCloakUsersResult.get(0).getAllRoles().get(17));
+ }
+
+ @Test
+ public void testGetKeyCloakUsers_EmptyToken() throws Exception {
+ PowerMock.mockStatic(JwtHelper.class);
+ List<KeyCloakUser> compList = new ArrayList<>();
+ UserCache.getInstance().setKeyCloakUsers(compList);
+
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles.json");
+ Type listTypeKeyCloakRole = new TypeToken<List<KeyCloakRole>>(){}.getType();
+ List<KeyCloakRole> keyCloakRolesList = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakRoles, listTypeKeyCloakRole);
+
+ expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(null);
+
+ PowerMock.replayAll();
+ task.run();
+ PowerMock.verifyAll();
+
+ assertTrue(UserCache.getInstance().getKeyCloakUsers().isEmpty());
+ }
+
+ @Test
+ public void testGetKeyCloakUsers_null() throws Exception {
+ PowerMock.mockStatic(JwtHelper.class);
+ List<KeyCloakUser> compList = new ArrayList<>();
+ UserCache.getInstance().setKeyCloakUsers(compList);
+
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles.json");
+ Type listTypeKeyCloakRole = new TypeToken<List<KeyCloakRole>>(){}.getType();
+ List<KeyCloakRole> keyCloakRolesList = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakRoles, listTypeKeyCloakRole);
+
+ expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(null);
+
+ PowerMock.replayAll();
+ task.run();
+ PowerMock.verifyAll();
+
+ assertTrue(UserCache.getInstance().getKeyCloakUsers().isEmpty());
+ }
+
+
+ @Test
+ public void testGetKeyCloakUsersFromToken_ListEmpty() throws Exception {
+ PowerMock.mockStatic(JwtHelper.class);
+ String jsonKeyCloakUser = super.loadStringFromResource("testKeyCloakUsers.json");
+ Type listTypeKeyCloakUser = new TypeToken<List<KeyCloakUser>>(){}.getType();
+ List<KeyCloakUser> keyCloakUsersListOrg = JsonGeneratorBase.getGson().fromJson(jsonKeyCloakUser, listTypeKeyCloakUser);
+
+ UserCache.getInstance().setKeyCloakUsers(keyCloakUsersListOrg);
+ String json = super.loadStringFromResource("JWTAdmin.json");
+ JwtToken jwt = getGson().fromJson(json, JwtToken.class);
+
+ List<KeyCloakUser> keyCloakUsersList = new ArrayList<>();
+
+ expect(JwtHelper.login(BackendConfig.getInstance().getKeycloakAdmin(), BackendConfig.getInstance().getKeycloakPW())).andReturn(jwt);
+ expect(JwtHelper.getUsers(jwt, BackendConfig.getInstance().getMaxLoadUsers())).andReturn(keyCloakUsersList);
+
+ PowerMock.replayAll();
+ task.run();
+ PowerMock.verifyAll();
+
+ assertEquals(keyCloakUsersList.size(), UserCache.getInstance().getKeyCloakUsers().size());
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java b/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java
new file mode 100644
index 0000000..fdb8400
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/HashingAlgoTest.java
@@ -0,0 +1,28 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common.util;
+
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.Objects;
+import org.junit.Test;
+
+public class HashingAlgoTest {
+ @Test
+ public void testHashIt() {
+ String hash = HashingAlgo.hashIt("TestMe");
+ assertTrue("66d565a2eb74e1a20b6c12bb2cbf84ecaade84ec".equals(hash));
+ assertTrue(!Objects.equals(HashingAlgo.hashIt("ThisIsTest"), HashingAlgo.hashIt("thisIsATest")));
+ assertNull(HashingAlgo.hashIt(null));
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java b/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java
new file mode 100644
index 0000000..9d888ef
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/common/util/ResourceLoaderBaseTest.java
@@ -0,0 +1,26 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.common.util;
+
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class ResourceLoaderBaseTest {
+ @Test
+ public void testloadStringFromResourceError() {
+ ResourceLoaderBase rlb = new ResourceLoaderBase();
+ String str = rlb.loadStringFromResource("UNKNOWN_FILE");
+ assertEquals("", str);
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java b/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java
new file mode 100644
index 0000000..8135628
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BackendControllerTest.java
@@ -0,0 +1,48 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import java.util.List;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.eclipse.openk.portal.viewmodel.LoginCredentials;
+import org.eclipse.openk.portal.viewmodel.UserAuthentication;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class BackendControllerTest extends ResourceLoaderBase {
+
+ @Test
+ public void testGetVersionInfo() {
+ BackendController bec = new BackendController();
+ VersionInfo vi = bec.getVersionInfo();
+
+ String vCurr = getClass().getPackage().getImplementationVersion();
+ assertEquals( vi.getBackendVersion(), vCurr );
+ }
+
+ @Test
+ public void getUserModuleList_TemporaryOnly() {
+ //_fd only temporarily
+ List<UserModule> modList = new BackendController().getUserModuleList();
+ assertTrue( !modList.isEmpty() );
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java b/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java
new file mode 100644
index 0000000..10a17dc
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/BaseWebServiceTest.java
@@ -0,0 +1,260 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.annotation.Annotation;
+import java.net.URI;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.GenericType;
+import javax.ws.rs.core.Link;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Assert;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class BaseWebServiceTest {
+ private static final org.apache.log4j.Logger EMPTYLOGGER = org.apache.log4j.Logger
+ .getLogger(BaseWebServiceTest.class.getName());
+
+ public static class TestWebService extends BaseWebService {
+ public String sessionId;
+ public boolean throwUnauthException = false;
+
+ public TestWebService() {
+ super(EMPTYLOGGER);
+ }
+
+ protected void assertAndRefreshToken(String sessionId, boolean refresh) throws PortalException {
+ if (throwUnauthException) {
+ throw new PortalUnauthorized();
+ } else {
+ this.sessionId = sessionId;
+ }
+ }
+ }
+
+ public static class TestInvokable extends BackendInvokable {
+ public boolean isInvoked = false;
+ public PortalException exceptionToThrow = null;
+ public boolean throwRuntime = false;
+ public Response response = null;
+
+ @Override
+ public Response invoke() throws PortalException {
+ if (exceptionToThrow != null) {
+ throw exceptionToThrow;
+ }
+ if (throwRuntime) {
+ ((String) null).equals("error"); //NOSONAR
+ }
+ isInvoked = true;
+ return response;
+ }
+ }
+
+ @Test
+ public void testInvokeException() {
+ TestWebService tws = new TestWebService();
+ TestInvokable ti = new TestInvokable();
+
+ ti.exceptionToThrow = new PortalBadRequest();
+ Response ret = tws.invoke("ssess", false, ti);
+ Assert.assertEquals(Globals.HTTPSTATUS_BAD_REQUEST, ret.getStatus());
+ }
+
+ @Test
+ public void testInvokeRuntimeException() {
+ TestWebService tws = new TestWebService();
+ TestInvokable ti = new TestInvokable();
+
+ ti.throwRuntime = true;
+ Response ret = tws.invoke("ssess", false, ti);
+ assertEquals(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR, ret.getStatus());
+ }
+
+ @Test
+ public void testUnauthException() {
+ TestWebService tws = new TestWebService();
+ TestInvokable ti = new TestInvokable();
+ tws.throwUnauthException = true;
+ Response ret = tws.invoke("ssess", false, ti);
+ assertEquals(Globals.HTTPSTATUS_UNAUTHORIZED, ret.getStatus());
+ }
+
+ @Test
+ public void testSecureTypeNone() {
+ TestWebService tws = new TestWebService();
+ TestInvokable ti = new TestInvokable();
+ Response responseForTypeNONE = tws.invoke("ssess", false, ti);
+ assertNull(responseForTypeNONE);
+ }
+
+
+ @Test
+ public void testInvokation() {
+ TestWebService tws = new TestWebService();
+ TestInvokable ti = new TestInvokable();
+ ti.response = new Response() {
+ @Override
+ public Object getEntity() {
+ return null;
+ }
+
+ @Override
+ public <T> T readEntity(Class<T> aClass) {
+ return null;
+ }
+
+ @Override
+ public <T> T readEntity(GenericType<T> genericType) {
+ return null;
+ }
+
+ @Override
+ public <T> T readEntity(Class<T> aClass, Annotation[] annotations) {
+ return null;
+ }
+
+ @Override
+ public <T> T readEntity(GenericType<T> genericType, Annotation[] annotations) {
+ return null;
+ }
+
+ @Override
+ public boolean hasEntity() {
+ return false;
+ }
+
+ @Override
+ public boolean bufferEntity() {
+ return false;
+ }
+
+ @Override
+ public void close() {
+
+ }
+
+ @Override
+ public MediaType getMediaType() {
+ return null;
+ }
+
+ @Override
+ public Locale getLanguage() {
+ return null;
+ }
+
+ @Override
+ public int getLength() {
+ return 0;
+ }
+
+ @Override
+ public Set<String> getAllowedMethods() {
+ return null;
+ }
+
+ @Override
+ public Map<String, NewCookie> getCookies() {
+ return null;
+ }
+
+ @Override
+ public EntityTag getEntityTag() {
+ return null;
+ }
+
+ @Override
+ public Date getDate() {
+ return null;
+ }
+
+ @Override
+ public Date getLastModified() {
+ return null;
+ }
+
+ @Override
+ public URI getLocation() {
+ return null;
+ }
+
+ @Override
+ public Set<Link> getLinks() {
+ return null;
+ }
+
+ @Override
+ public boolean hasLink(String s) {
+ return false;
+ }
+
+ @Override
+ public Link getLink(String s) {
+ return null;
+ }
+
+ @Override
+ public Link.Builder getLinkBuilder(String s) {
+ return null;
+ }
+
+ @Override
+ public int getStatus() {
+ return 666;
+ }
+
+ @Override
+ public StatusType getStatusInfo() {
+ return null;
+ }
+
+ @Override
+ public MultivaluedMap<String, Object> getMetadata() {
+ return null;
+ }
+
+ @Override
+ public MultivaluedMap<String, String> getStringHeaders() {
+ return null;
+ }
+
+ @Override
+ public String getHeaderString(String s) {
+ return null;
+ }
+ };
+
+ Response ret = tws.invoke("ssess", false, ti);
+ assertTrue(ti.isInvoked);
+ assertEquals("ssess", tws.sessionId);
+ assertEquals(666, ret.getStatus() );
+
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java b/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java
new file mode 100644
index 0000000..3dce81e
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ControllerImplementationsTest.java
@@ -0,0 +1,99 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.viewmodel.UserModule;
+import org.eclipse.openk.portal.viewmodel.VersionInfo;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.api.easymock.PowerMock;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static org.easymock.EasyMock.expect;
+
+
+public class ControllerImplementationsTest extends ResourceLoaderBase {
+ private BackendController beMock;
+ @Before
+ public void prepareTests() {
+ beMock = PowerMock.createNiceMock(BackendController.class);
+ }
+
+ @Test
+ public void testGetUsers() throws PortalException {
+ List<KeyCloakUser> userList = new ArrayList<>();
+ ControllerImplementations.GetUsers controllerImpl = new ControllerImplementations.GetUsers();
+ controllerImpl.setModUser("EgalUser");
+ controllerImpl.setUserId(14);
+
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ assertEquals(controllerImpl.getModUser(), "EgalUser");
+ assertEquals(controllerImpl.getUserId(), 14);
+ }
+
+ @Test
+ public void testGetVersionInfo() throws PortalException {
+ VersionInfo vi = new VersionInfo();
+ ControllerImplementations.GetVersionInfo controllerImpl = new ControllerImplementations.GetVersionInfo(beMock);
+
+ expect(beMock.getVersionInfo()).andReturn(vi);
+ PowerMock.replay(beMock);
+
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ }
+
+ @Test
+ public void testLogOut() throws PortalException {
+ ControllerImplementations.Logout controllerImpl = new ControllerImplementations.Logout("LogMeOut");
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ }
+
+ @Test
+ public void testCheckAuth() throws PortalException {
+ ControllerImplementations.CheckAuth controllerImpl = new ControllerImplementations.CheckAuth();
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ }
+
+ @Test
+ public void testGetUserModulesForUser() throws PortalException {
+ List<UserModule> userModules = new ArrayList<>();
+ ControllerImplementations.GetUserModulesForUser controllerImpl = new ControllerImplementations.GetUserModulesForUser(beMock);
+ controllerImpl.setModUser("EgalUser");
+
+ expect(beMock.getUserModuleList()).andReturn(userModules);
+ PowerMock.replay(beMock);
+
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ assertEquals(controllerImpl.getModUser(), "EgalUser");
+ }
+
+ @Test
+ public void testGetUserForRole() throws PortalException {
+ List<KeyCloakUser> keyCloakUsers = new ArrayList<>();
+ String userRole = "theBestRole";
+ ControllerImplementations.GetUsersForRole controllerImpl = new ControllerImplementations.GetUsersForRole(beMock, userRole);
+ controllerImpl.setModUser("EgalUser");
+
+ expect(beMock.getUsersForRole(userRole)).andReturn(keyCloakUsers);
+ PowerMock.replay(beMock);
+
+ assertEquals(controllerImpl.invoke().getStatus(), Globals.HTTPSTATUS_OK);
+ assertEquals(controllerImpl.getModUser(), "EgalUser");
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java b/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java
new file mode 100644
index 0000000..16f90db
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/InputValidatorTest.java
@@ -0,0 +1,83 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalBadRequest;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+public class InputValidatorTest extends ResourceLoaderBase {
+
+ // Check Credentials -------------------------------------------------------
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_Null() throws PortalUnauthorized {
+ new InputDataValuator().checkCredentials(null);
+ }
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_Empty() throws PortalUnauthorized {
+ new InputDataValuator().checkCredentials("");
+ }
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_TooLong() throws PortalUnauthorized {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < Globals.MAX_CREDENTIALS_LENGTH; i++) {
+ sb.append("W");
+ }
+ new InputDataValuator().checkCredentials(sb.toString());
+
+ }
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_Invalid() throws PortalUnauthorized {
+ new InputDataValuator().checkCredentials("{\"abc\":\"123\"}");
+ }
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_InvalidNoJson() throws PortalUnauthorized {
+ new InputDataValuator().checkCredentials("123");
+ }
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testCheckCredentials_tooLong() throws PortalUnauthorized {
+ StringBuilder sb = new StringBuilder(Globals.MAX_CREDENTIALS_LENGTH + 1);
+ for (int i = 0; i < Globals.MAX_CREDENTIALS_LENGTH + 1; i++) {
+ sb.append("@");
+ }
+ new InputDataValuator().checkCredentials(sb.toString());
+
+ }
+
+ @Test
+ public void checkWhitelistChars_ok() throws Exception {
+ callWhitelistCheck("AaBbCcäÄöÖüÜß ?0123456789(). _+ ,-:;=!§%&/'#<>\"");
+ }
+
+ @Test(expected = PortalBadRequest.class)
+ public void checkWhitelistChars_nok() throws Exception {
+ callWhitelistCheck(null);
+ callWhitelistCheck("");
+ callWhitelistCheck("AaBbCc.,{}");
+ }
+
+ private void callWhitelistCheck(String tst) throws Exception {
+ InputDataValuator idv = new InputDataValuator();
+ Whitebox.invokeMethod(idv, "checkWhitelistChars", tst, false);
+ }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java b/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java
new file mode 100644
index 0000000..a64e04e
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/ResponseBuilderWrapperTest.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+
+import static org.junit.Assert.assertEquals;
+
+import javax.ws.rs.core.Response;
+import org.eclipse.openk.portal.common.Globals;
+import org.eclipse.openk.portal.exceptions.PortalException;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.junit.Test;
+
+
+public class ResponseBuilderWrapperTest {
+ @Test
+ public void testGetResponseBuilder() throws PortalInternalServerError {
+ String json = "{ 'ret' : 'OK' }";
+ Response.ResponseBuilder rb = ResponseBuilderWrapper.INSTANCE.getResponseBuilder( json );
+ Response resp = rb.build();
+ assertEquals(Globals.HTTPSTATUS_OK, resp.getStatus());
+ }
+
+ @Test
+ public void testBuildOkResponse() throws PortalException {
+ String json = "{ 'test' : 'Value' }";
+ Response resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse( json );
+ assertEquals( Globals.HTTPSTATUS_OK, resp.getStatus());
+
+ resp = ResponseBuilderWrapper.INSTANCE.buildOKResponse(json, "ssess");
+ assertEquals( Globals.HTTPSTATUS_OK, resp.getStatus());
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java b/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java
new file mode 100644
index 0000000..1c31de2
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/controller/TokenManagerTest.java
@@ -0,0 +1,106 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.controller;
+
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.common.BackendConfig;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalUnauthorized;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import java.util.HashMap;
+import static org.junit.Assert.*;
+
+public class TokenManagerTest extends ResourceLoaderBase {
+
+ @Before
+ public void cleanUp() {
+ TokenManager sessione = TokenManager.getInstance();
+ HashMap<String, TokenManager.SessionItem> regMap = Whitebox.getInternalState(sessione, "registry");
+ regMap.clear();
+ }
+
+ @Test
+ public void testRegisterNewSession() {
+ final int COUNT = 1000;
+
+ for (int i = 0; i < COUNT; i++) {
+ TokenManager.getInstance().registerNewSession(createJWT( "T"+i ));
+ }
+ }
+
+
+ @Test(expected = PortalUnauthorized.class)
+ public void testRefreshStatusIsAlive() throws InterruptedException, PortalUnauthorized {
+ TokenManager sessione = TokenManager.getInstance();
+ JwtToken specialToken = createJWT(null);
+
+ long timeNow = System.currentTimeMillis();
+ sessione.registerNewSession(createJWT("HUGO1"));
+ sessione.registerNewSession(specialToken);
+ sessione.registerNewSession(createJWT("HUGO3"));
+
+ HashMap<String, TokenManager.SessionItem> regMap = Whitebox.getInternalState(sessione, "registry");
+
+ assertEquals(3, regMap.size());
+ assertTrue(regMap.containsKey("HUGO1"));
+ assertTrue(regMap.containsKey(specialToken.getAccessToken()));
+ assertTrue(regMap.containsKey("HUGO3"));
+
+ regMap.remove(specialToken.getAccessToken());
+ regMap.put(specialToken.getAccessToken(), new TokenManager.SessionItem(timeNow - BackendConfig.getInstance().getInternalSessionLengthMillis() - 1));
+ regMap.get(specialToken.getAccessToken()).setJwtToken(specialToken);
+ regMap.remove("HUGO3");
+ regMap.put("HUGO3", null);
+
+ Thread.sleep(50); // NOSONAR // LOCK is held
+
+ TokenManager.getInstance().refreshSessionIsAlive("HUGO1", true);
+
+ // create Time stays the same
+ TokenManager.SessionItem sit1 = regMap.get("HUGO1");
+ assertTrue(sit1.getSessionLastAccessTime() > sit1.getSessionCreationTime());
+
+ sit1.setSessionCreationTime(sit1.getSessionLastAccessTime()-200);
+ assertEquals( sit1.getSessionCreationTime()+200, sit1.getSessionLastAccessTime());
+ sit1.setUser(null);
+ assertNull(sit1.getUser());
+ assertEquals("HUGO1", sit1.getSessionId() );
+ sit1.setCookieToken("CaptainCookie");
+ assertEquals("CaptainCookie", sit1.getCookieToken());
+
+ TokenManager.getInstance().logout("HUGO1");
+ assertEquals(2, regMap.size());
+ TokenManager.getInstance().logout( "FAKE");
+ assertEquals(2, regMap.size());
+
+
+ // session out of time
+ TokenManager.getInstance().refreshSessionIsAlive(specialToken.getAccessToken(), true);
+ // fails with PortalUnauthorized
+ }
+
+ private JwtToken createJWT(String accessToken ) {
+ String json = super.loadStringFromResource("JWTAdmin.json");
+ JwtToken jwt = JsonGeneratorBase.getGson().fromJson(json, JwtToken.class);
+
+ if( accessToken != null ) {
+ jwt.setAccessToken(accessToken);
+ }
+ return jwt;
+ }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java
new file mode 100644
index 0000000..f9506e9
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionMapperTest.java
@@ -0,0 +1,54 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+
+import static junit.framework.Assert.assertEquals;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.viewmodel.ErrorReturn;
+import org.junit.Test;
+
+public class PortalExceptionMapperTest extends ResourceLoaderBase {
+ @Test
+ public void testToJson() {
+ String json = PortalExceptionMapper.toJson(new PortalNotFound("lalilu"));
+
+ ErrorReturn er = JsonGeneratorBase.getGson().fromJson(json, ErrorReturn.class);
+ assertEquals(er.getErrorCode(), 404);
+ assertEquals("lalilu", er.getErrorText());
+ }
+
+ @Test
+ public void testUnknownErrorToJson() {
+ String json = PortalExceptionMapper.unknownErrorToJson();
+
+ ErrorReturn er = JsonGeneratorBase.getGson().fromJson(json, ErrorReturn.class);
+ assertEquals(er.getErrorCode(), 500);
+ }
+
+ @Test
+ public void testGeneralOKJson() {
+ String ok = PortalExceptionMapper.getGeneralOKJson();
+ assertEquals("{\"ret\":\"OK\"}", ok);
+ }
+
+ @Test
+ public void testGeneralErrorJson() {
+ String nok = PortalExceptionMapper.getGeneralErrorJson();
+ assertEquals("{\"ret\":\"NOK\"}", nok);
+ }
+
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java
new file mode 100644
index 0000000..5cdf190
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/exceptions/PortalExceptionsTest.java
@@ -0,0 +1,40 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.exceptions;
+
+import static org.junit.Assert.assertEquals;
+
+import org.eclipse.openk.portal.common.Globals;
+import org.junit.Test;
+
+public class PortalExceptionsTest {
+
+ @Test
+ public void testConstructors() {
+ assertEquals(Globals.HTTPSTATUS_BAD_REQUEST, new PortalBadRequest().getHttpStatus() );
+ assertEquals(Globals.HTTPSTATUS_FORBIDDEN, new PortalForbidden().getHttpStatus());
+ assertEquals(Globals.HTTPSTATUS_INTERNAL_SERVER_ERROR, new PortalInternalServerError(null, null).getHttpStatus());
+ assertEquals(Globals.HTTPSTATUS_NOT_FOUND, new PortalNotFound().getHttpStatus());
+ assertEquals(Globals.HTTPSTATUS_UNAUTHORIZED, new PortalUnauthorized().getHttpStatus());
+ }
+
+
+ @Test
+ public void testConstructors2() {
+ final String extext = "ExText";
+ assertEquals(new PortalBadRequest(extext).getMessage(), extext);
+ assertEquals(new PortalForbidden(extext).getMessage(), extext);
+ assertEquals(new PortalInternalServerError(extext).getMessage(), extext);
+ assertEquals(new PortalNotFound(extext).getMessage(), extext);
+ assertEquals(new PortalUnauthorized(extext).getMessage(), extext);
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/base/HealthCheckerTest.java b/src/test/java/org/eclipse/openk/portal/health/base/HealthCheckerTest.java
new file mode 100644
index 0000000..87aed26
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/HealthCheckerTest.java
@@ -0,0 +1,93 @@
+/*
+ ******************************************************************************
+ * Copyright © 2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+*/
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.*;
+
+public class HealthCheckerTest {
+ public boolean hc1Called;
+ public boolean hc2Called;
+ public boolean hc3Called;
+
+ @Before
+ public void init() {
+ hc1Called = false;
+ hc2Called = false;
+ hc3Called = false;
+ }
+
+ @Test
+ public void test_ok() {
+ HealthCheck hc1 = new HealthCheck() {
+
+ @Override
+ protected Result check() throws Exception {
+ hc1Called = true;
+ return Result.healthy();
+ }
+ };
+
+ HealthCheck hc2 = new HealthCheck() {
+ @Override
+ protected Result check() throws Exception {
+ hc2Called = true;
+ return Result.unhealthy("because of...");
+ }
+ };
+
+ HealthChecker theChecker = new HealthChecker();
+ theChecker.register("firstTest", hc1 );
+ theChecker.register( "secondTest", hc2 );
+
+ List<NamedHealthCheckResult> retList = theChecker.performHealthChecks();
+
+ assertEquals( 2, retList.size() );
+ assertTrue( hc1Called );
+ assertTrue( hc2Called );
+ assertNull( retList.get(0).getResult().getMessage());
+ assertNotNull( retList.get(1).getResult().getMessage());
+ assertEquals( "firstTest", retList.get(0).getName());
+ assertEquals( "secondTest", retList.get(1).getName());
+ assertTrue( retList.get(0).getResult().isHealthy());
+ assertFalse( retList.get(1).getResult().isHealthy());
+ }
+
+ @Test
+ public void test_nok() {
+ HealthCheck hc1 = new HealthCheck() {
+
+ @Override
+ protected Result check() throws Exception {
+ hc3Called = true;
+ throw new Exception("Error in healthCheck");
+ }
+ };
+
+
+ HealthChecker theChecker = new HealthChecker();
+ theChecker.register("errorTest", hc1 );
+
+ List<NamedHealthCheckResult> retList = theChecker.performHealthChecks();
+
+ assertEquals( 1, retList.size() );
+ assertTrue( hc3Called );
+ assertNotNull( retList.get(0).getResult().getMessage());
+ assertFalse( retList.get(0).getResult().isHealthy());
+
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java b/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java
new file mode 100644
index 0000000..9cb9770
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/NamedHealthCheckResultTest.java
@@ -0,0 +1,36 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Test;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+
+public class NamedHealthCheckResultTest {
+ @Test
+ public void testAll() {
+ NamedHealthCheckResult h1 = new NamedHealthCheckResult("Uno", Result.healthy());
+ NamedHealthCheckResult h2 = new NamedHealthCheckResult("Due", Result.unhealthy("Darum"));
+
+ assertEquals("\"Uno\":{\"healthy\":true}", h1.toJson());
+ assertEquals("\"Due\":{\"healthy\":false,\"message\":\"Darum\"}", h2.toJson());
+
+ List<NamedHealthCheckResult> lista = new LinkedList<>();
+ lista.add(h1);
+ lista.add(h2);
+ assertEquals( "{\"Uno\":{\"healthy\":true},\"Due\":{\"healthy\":false,\"message\":\"Darum\"}}",
+ NamedHealthCheckResult.toJson(lista));
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java b/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java
new file mode 100644
index 0000000..a2056b0
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/base/ResultTest.java
@@ -0,0 +1,31 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.base;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ResultTest {
+
+ @Test
+ public void testAll() {
+ Result res1 = Result.healthy();
+ Result res2 = Result.unhealthy("Msg");
+
+ assertTrue(res1.isHealthy());
+ assertFalse(res2.isHealthy());
+ assertNull(res1.getMessage());
+ assertNotNull(res2.getMessage());
+
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java b/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java
new file mode 100644
index 0000000..25ef190
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/health/impl/KeyCloakPresentHealthCheckTest.java
@@ -0,0 +1,48 @@
+/**
+ ******************************************************************************
+ * Copyright © 2017-2018 PTA GmbH.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ *
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ ******************************************************************************
+ */
+package org.eclipse.openk.portal.health.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class KeyCloakPresentHealthCheckTest {
+ private KeyCloakPresentHealthCheck hc;
+
+ @Before
+ public void init() {
+ hc = new KeyCloakPresentHealthCheck() {
+ public boolean checkit;
+
+ @Override
+ protected boolean checkit() {
+ return checkit;
+ }
+ };
+ }
+
+ @Test
+ public void testOk() throws Exception {
+ Whitebox.setInternalState(hc, "checkit", true);
+ assertTrue(hc.check().isHealthy());
+ }
+
+ @Test
+ public void testNok() throws Exception {
+ Whitebox.setInternalState(hc, "checkit", false);
+ assertFalse(hc.check().isHealthy());
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java b/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java
new file mode 100644
index 0000000..4404351
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/util/JwtHelperTest.java
@@ -0,0 +1,118 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.util;
+
+import org.eclipse.openk.portal.auth2.model.JwtPayload;
+import org.eclipse.openk.portal.auth2.model.JwtToken;
+import org.eclipse.openk.portal.auth2.model.KeyCloakRole;
+import org.eclipse.openk.portal.auth2.util.JwtHelper;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.eclipse.openk.portal.exceptions.PortalInternalServerError;
+import org.junit.Test;
+
+import java.util.List;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertTrue;
+import static org.junit.Assert.assertNotNull;
+
+public class JwtHelperTest extends ResourceLoaderBase {
+
+ @Test
+ public void testGetJwtPayload_Base64URL() {
+ //Token Pre 4.8.3 Keycloak
+ String base64urlToken = "AA.eyJqdGkiOiI3NDVmOTc4Zi00OTYwLTRlO"+
+ "WYtYmFiMS1jNjdkZjMzODEwYjQiLCJleH"+
+ "AiOjE1MTYwMTAxNDksIm5iZiI6MCwiaWF"+
+ "0IjoxNTE2MDA5ODQ5LCJpc3MiOiJodHRw"+
+ "Oi8vbG9jYWxob3N0OjgwOTAvYXV0aC9yZ"+
+ "WFsbXMvTVZWTmV0emUiLCJhdWQiOiJlbG"+
+ "9nYm9vay1iYWNrZW5kIiwic3ViIjoiNTk"+
+ "5ZWY3NzMtNjRmYS00MzM2LWIwNDktMmEz"+
+ "Njc4NTEzZTU4IiwidHlwIjoiQmVhcmVyI"+
+ "iwiYXpwIjoiZWxvZ2Jvb2stYmFja2VuZC"+
+ "IsImF1dGhfdGltZSI6MCwic2Vzc2lvbl9"+
+ "zdGF0ZSI6ImE2OGE4MzNkLTRiNTItNDgw"+
+ "My05MDU4LTRkNjJhNmI3NzI3MCIsImFjc"+
+ "iI6IjEiLCJhbGxvd2VkLW9yaWdpbnMiOl"+
+ "siKiJdLCJyZWFsbV9hY2Nlc3MiOnsicm9"+
+ "sZXMiOlsiZWxvZ2Jvb2stYWNjZXNzIiwi"+
+ "ZWxvZ2Jvb2stbm9ybWFsdXNlciIsInVtY"+
+ "V9hdXRob3JpemF0aW9uIl19LCJyZXNvdX"+
+ "JjZV9hY2Nlc3MiOnsiYWNjb3VudCI6eyJ"+
+ "yb2xlcyI6WyJtYW5hZ2UtYWNjb3VudCIs"+
+ "Im1hbmFnZS1hY2NvdW50LWxpbmtzIiwid"+
+ "mlldy1wcm9maWxlIl19fSwicm9sZXMiOi"+
+ "JbdW1hX2F1dGhvcml6YXRpb24sIGVsb2d"+
+ "ib29rLWFjY2VzcywgZWxvZ2Jvb2stbm9y"+
+ "bWFsdXNlciwgb2ZmbGluZV9hY2Nlc3NdI"+
+ "iwibmFtZSI6IlV3ZSByb8OfIiwicHJlZm"+
+ "VycmVkX3VzZXJuYW1lIjoib3Blbmt0ZXN"+
+ "0IiwiZ2l2ZW5fbmFtZSI6IlV3ZSIsImZh"+
+ "bWlseV9uYW1lIjoicm_DnyJ9.CC";
+ //Since Keycloak 4.8.3 Aud Parameter is an array now
+ base64urlToken = "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJIRWQ4NGl4V2xaVWk2bWFSa005Tk1wSEd0amRXRU1pZGtNV0Nvbk90U1ZVIn0.eyJleHAiOjE2MTA3MzYxNDEsImlhdCI6MTYxMDczNTg0MSwianRpIjoiNGIwMTM1NGMtN2NmZC00ZmEyLThmMjQtYWM0ZmJlZWZhNTZkIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDo4MTgwL2F1dGgvcmVhbG1zL0Vsb2dib29rIiwiYXVkIjpbInJlYWxtLW1hbmFnZW1lbnQiLCJhY2NvdW50Il0sInN1YiI6IjAzNDU0MjJmLTk0MzctNDVmYy1iMmY0LTNlYTcwZDUzY2Q3NCIsInR5cCI6IkJlYXJlciIsImF6cCI6ImVsb2dib29rLWJhY2tlbmQiLCJzZXNzaW9uX3N0YXRlIjoiNDRlMWQxMTctYTU0My00NWZjLWJjNTAtZjE5MDYzZGVmOTk0IiwiYWNyIjoiMSIsImFsbG93ZWQtb3JpZ2lucyI6WyIqIl0sInJlYWxtX2FjY2VzcyI6eyJyb2xlcyI6WyJlbG9nYm9vay1ub3JtYWx1c2VyIiwicGxhbm5lZC1wb2xpY2llcy1ub3JtYWx1c2VyIiwiZWxvZ2Jvb2stYWNjZXNzIiwiZWxvZ2Jvb2stc3VwZXJ1c2VyIiwia29uLWFkbWluIiwiZ3JpZC1mYWlsdXJlLWFjY2VzcyIsIm9mZmxpbmVfYWNjZXNzIiwia29uLWFjY2VzcyIsImdyaWQtZmFpbHVyZS1hZG1pbiIsInBsYW5uZWQtcG9saWNpZXMtYWNjZXNzIiwicGxhbm5pbmctYWNjZXNzIiwidW1hX2F1dGhvcml6YXRpb24iLCJwbGFubmVkLXBvbGljaWVzLXN1cGVydXNlciJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJzY29wZSI6ImVtYWlsIHByb2ZpbGUiLCJlbWFpbF92ZXJpZmllZCI6ZmFsc2UsIm5hbWUiOiJBZG1pbiBTdHJhdG9yIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJnaXZlbl9uYW1lIjoiQWRtaW4iLCJmYW1pbHlfbmFtZSI6IlN0cmF0b3IifQ.sz5nOZZDwDHUS-WLzx1KX_KGTiWGuWTisR_bbHyReeXJyMefL6pngYwF_Qt0EPk1g0rqmqdhTN8-5IaSrwO1n0RmZrWLg19n1QnjkAs6ebF84UL07n5EEFJKh0luyWOKb_EW8JZpwRpLhaiWTG6KdXnOU6VkxJ-xX0ncmrHS8MYDh_u1LhIUPnu43trn0jJWoNAuHHVMY0rhpXNaZqc3Rq8iI3Vye87Yvs83jKTj5d1rHsFTrkaRt51bgi-2ML6IZa9GxIbCYroHZ7Idue00jisWPzmYU7F-wOpASBClBDsweTwRY9Dgr_yjrMns-1KXfYwtt4BTEc0IMKfX5gneSg";
+ // this payload contains a char with is valid in Base64URL but NOT in Base64.
+ JwtToken jt = new JwtToken();
+ jt.setAccessToken(base64urlToken);
+ JwtPayload pl = JwtHelper.getPayLoad(jt);
+ assertNotNull( pl );
+
+ }
+
+ @Test
+ public void testGetRolesListFromJson_testKeyCloakRoles_noClientRoleAtAll() throws PortalInternalServerError {
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noClientRoleAtAll.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+ assertEquals(2, keyCloakRolesList.size());
+ }
+
+ @Test
+ public void testGetRolesListFromJson_testKeyCloakRoles_noClientRoleForClient() throws PortalInternalServerError {
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noClientRoleForClient.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+ assertEquals(2, keyCloakRolesList.size());
+ }
+
+ @Test
+ public void testGetRolesListFromJson_testKeyCloakRoles_noRealmRole() throws PortalInternalServerError {
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_noRealmRole.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ assertTrue(keyCloakRolesList.isEmpty());
+ }
+
+ @Test
+ public void testGetRolesListFromJson_testKeyCloakRoles_onlyClientRole() throws PortalInternalServerError {
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_onlyClientRole.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ assertEquals("view-profile", keyCloakRolesList.get(0).getName());
+ assertTrue(keyCloakRolesList.get(0).getClientRole());
+ assertEquals(2, keyCloakRolesList.size());
+ }
+
+ @Test
+ public void testGetRolesListFromJson_testKeyCloakRoles_sameClientRealmRole() throws PortalInternalServerError {
+ String jsonKeyCloakRoles = super.loadStringFromResource("testKeyCloakRoles_sameClientRealmRole.json");
+ List<KeyCloakRole> keyCloakRolesList = JwtHelper.getRolesListFromJson(jsonKeyCloakRoles);
+
+ assertEquals("elogbook-access", keyCloakRolesList.get(0).getName());
+ assertEquals(4, keyCloakRolesList.size());
+ }
+
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java
new file mode 100644
index 0000000..b4ba312
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/ErrorReturnTest.java
@@ -0,0 +1,41 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.eclipse.openk.portal.common.JsonGeneratorBase.getGson;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class ErrorReturnTest extends ResourceLoaderBase {
+ // IMPORTANT TEST!!!
+ // Make sure, our Interface produces a DEFINED Json!
+ // Changes in the interface will HOPEFULLY crash here!!!
+
+ @Test
+ public void TestStructureAgainstJson() {
+ String json = super.loadStringFromResource("testErrorReturn.json");
+ ErrorReturn errRet = getGson().fromJson(json, ErrorReturn.class);
+ assertFalse(errRet.getErrorText().isEmpty());
+ assertEquals(999, errRet.getErrorCode());
+ }
+
+ @Test
+ public void TestSetters() {
+ ErrorReturn errRet = new ErrorReturn();
+ errRet.setErrorCode(1);
+ errRet.setErrorText("bla bla");
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java
new file mode 100644
index 0000000..217cd7d
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/GeneralReturnItemTest.java
@@ -0,0 +1,42 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class GeneralReturnItemTest extends ResourceLoaderBase {
+ // IMPORTANT TEST!!!
+ // Make sure, our Interface produces a DEFINED Json!
+ // Changes in the interface will HOPEFULLY crash here!!!
+
+ @Test
+ public void TestStructureAgainstJson() {
+ String json = super.loadStringFromResource("testGeneralReturnItem.json");
+ GeneralReturnItem gRRet = JsonGeneratorBase.getGson().fromJson(json, GeneralReturnItem.class);
+ assertEquals("It works!", gRRet.getRet());
+ }
+
+ @Test
+ public void TestSetters() {
+ GeneralReturnItem gri = new GeneralReturnItem("firstStrike");
+ assertTrue("firstStrike".equals(gri.getRet()));
+ gri.setRet("Retour");
+ assertTrue("Retour".equals(gri.getRet()));
+
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java
new file mode 100644
index 0000000..d6ad438
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/LoginCredentialsTest.java
@@ -0,0 +1,40 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class LoginCredentialsTest extends ResourceLoaderBase {
+
+ @Test
+ public void testStructureAgainstJson() {
+ String json = super.loadStringFromResource("testLoginCredentials.json");
+ LoginCredentials lc = JsonGeneratorBase.getGson().fromJson(json, LoginCredentials.class);
+ assertEquals("Carlo", lc.getUserName() );
+ assertEquals("Cottura", lc.getPassword());
+ }
+
+ @Test
+ public void testSetters() {
+ LoginCredentials lc = new LoginCredentials();
+ lc.setPassword("pwd");
+ assertTrue("pwd".equals(lc.getPassword()));
+ lc.setUserName("usr");
+ assertTrue("usr".equals(lc.getUserName()));
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java
new file mode 100644
index 0000000..92ec165
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserAuthenticationTest.java
@@ -0,0 +1,47 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class UserAuthenticationTest extends ResourceLoaderBase {
+
+ @Test
+ public void testStructureAgainstJson() {
+ String json = super.loadStringFromResource("testUserAuthentication.json");
+ UserAuthentication ua = JsonGeneratorBase.getGson().fromJson(json, UserAuthentication.class);
+ assertTrue(ua.getId() == 1 );
+ assertTrue(ua.getUsername().equals("Pedro"));
+ assertTrue(ua.getPassword().equals("pwd"));
+ assertTrue(ua.getName().equals("Pedro Pepito Sanchez"));
+ assertFalse(ua.isSpecialUser());
+ assertTrue(ua.isSelected());
+ }
+
+ @Test
+ public void testSetters() {
+ UserAuthentication ua = new UserAuthentication();
+ ua.setId(1);
+ ua.setName("Vamos-Namos");
+ ua.setPassword("passoporto");
+ ua.setUsername("VNAMOS");
+ ua.setSpecialUser(true);
+ ua.setSelected(true);
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java
new file mode 100644
index 0000000..3a54c14
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserCacheTest.java
@@ -0,0 +1,44 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.eclipse.openk.portal.auth2.model.KeyCloakUser;
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class UserCacheTest extends ResourceLoaderBase {
+ // IMPORTANT TEST!!!
+ // Make sure, our Interface produces a DEFINED Json!
+ // Changes in the interface will HOPEFULLY crash here!!!
+
+ @Test
+ public void testStructureAgainstJsonAndSettersAndGetters() {
+ String json = super.loadStringFromResource("testKeyCloakUsers.json");
+ KeyCloakUser[] keyCloakUsers = JsonGeneratorBase.getGson().fromJson(json, KeyCloakUser[].class);
+ List<KeyCloakUser> keyCloakUsersList = new ArrayList<>(Arrays.asList(keyCloakUsers));
+ UserCache uc = UserCache.getInstance();
+ uc.setKeyCloakUsers(keyCloakUsersList);
+
+ assertTrue(keyCloakUsers.length == 3);
+ assertTrue(uc.getKeyCloakUsers().get(0).getFirstName().equals("Administrator"));
+ assertTrue(uc.getKeyCloakUsers().get(2).getUsername().equals("otto"));
+
+ }
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java
new file mode 100644
index 0000000..f5f13ef
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/UserModuleTest.java
@@ -0,0 +1,36 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class UserModuleTest {
+
+ @Test
+ public void testModuleConfigProduction() {
+ UserModule[] um = UserModule.getInstance();
+ assertEquals( "Betriebstagebuch local 4200", um[0].getModuleName() );
+ assertEquals( "#ffffff", um[0].getColor() );
+ assertEquals( 1, (long)um[0].getCols() );
+ assertEquals( 1, (long)um[0].getRows() );
+ assertEquals( "http://localhost:4200/", um[0].getLink() );
+ assertEquals( "https://www.openkonsequenz.de/medien/cache/main_image/m_logbuch_2443636.jpg", um[0].getPictureLink() );
+ assertEquals( "elogbook-access", um[0].getRequiredRole() );
+
+ assertEquals( "moduleConfigDevLocal.json", UserModule.getConfigFileName());
+ UserModule.setConfigFileName("moduleConfigDevLocal.json");
+ assertEquals( "moduleConfigDevLocal.json", UserModule.getConfigFileName() );
+ }
+
+}
diff --git a/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java b/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java
new file mode 100644
index 0000000..4c64753
--- /dev/null
+++ b/src/test/java/org/eclipse/openk/portal/viewmodel/VersionInfoTest.java
@@ -0,0 +1,41 @@
+/**
+******************************************************************************
+* Copyright © 2017-2018 PTA GmbH.
+* All rights reserved. This program and the accompanying materials
+* are made available under the terms of the Eclipse Public License v1.0
+* which accompanies this distribution, and is available at
+*
+* http://www.eclipse.org/legal/epl-v10.html
+*
+******************************************************************************
+*/
+package org.eclipse.openk.portal.viewmodel;
+
+
+import static org.junit.Assert.assertTrue;
+
+import org.eclipse.openk.portal.common.JsonGeneratorBase;
+import org.eclipse.openk.portal.common.util.ResourceLoaderBase;
+import org.junit.Test;
+
+public class VersionInfoTest extends ResourceLoaderBase {
+ // IMPORTANT TEST!!!
+ // Make sure, our Interface produces a DEFINED Json!
+ // Changes in the interface will HOPEFULLY crash here!!!
+
+ @Test
+ public void testStructureAgainstJson() {
+ String json = super.loadStringFromResource("VersionInfo.json");
+ VersionInfo vi = JsonGeneratorBase.getGson().fromJson(json, VersionInfo.class);
+
+ assertTrue(vi.getBackendVersion().equals("0x.0x.xx"));
+ }
+
+ @Test
+ public void testSetters() {
+ VersionInfo vi = new VersionInfo();
+
+ vi.setBackendVersion("222");
+ }
+
+}
diff --git a/src/test/resources/JWTAdmin.json b/src/test/resources/JWTAdmin.json
new file mode 100644
index 0000000..dda65c5
--- /dev/null
+++ b/src/test/resources/JWTAdmin.json
@@ -0,0 +1,8 @@
+{
+ "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJodVl0eVByUEVLQ1phY3FfMW5sOGZscENETnFHdmZEZHctYUxGQXNoWHZVIn0.eyJqdGkiOiI4ZmY5NTlhZC02ODQ1LTRlOGEtYjRiYi02ODQ0YjAwMjU0ZjgiLCJleHAiOjE1MDY2MDA0NTAsIm5iZiI6MCwiaWF0IjoxNTA2NjAwMTUwLCJpc3MiOiJodHRwOi8vZW50amF2YTAwMjo4MDgwL2F1dGgvcmVhbG1zL2Vsb2dib29rIiwiYXVkIjoiZWxvZ2Jvb2stYmFja2VuZCIsInN1YiI6IjM1OWVmOWM5LTc3ZGYtNGEzZC1hOWM5LWY5NmQ4MzdkMmQ1NyIsInR5cCI6IkJlYXJlciIsImF6cCI6ImVsb2dib29rLWJhY2tlbmQiLCJhdXRoX3RpbWUiOjAsInNlc3Npb25fc3RhdGUiOiI5NjVmNzM1MS0yZThiLTQ1MjgtOWYzZC1lZTYyODNhOTViMTYiLCJhY3IiOiIxIiwiYWxsb3dlZC1vcmlnaW5zIjpbIioiXSwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImVsb2dib29rLXN1cGVydXNlciIsImVsb2dib29rLW5vcm1hbHVzZXIiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19LCJuYW1lIjoiQWRtaW5pc3RyYXRvciBBZG1pbmlzdHJhdG93aWNoIiwicHJlZmVycmVkX3VzZXJuYW1lIjoiYWRtaW4iLCJnaXZlbl9uYW1lIjoiQWRtaW5pc3RyYXRvciIsImZhbWlseV9uYW1lIjoiQWRtaW5pc3RyYXRvd2ljaCIsImVtYWlsIjoic2VyZ2VqLmtlcm5AcHRhLmRlIiwicm9sZXN0ZXN0IjoiW2Vsb2dib29rLXN1cGVydXNlciwgZWxvZ2Jvb2stbm9ybWFsdXNlciwgdW1hX2F1dGhvcml6YXRpb24sIG9mZmxpbmVfYWNjZXNzLCB1bWFfYXV0aG9yaXphdGlvbiwgZWxvZ2Jvb2stbm9ybWFsdXNlcl0ifQ.o94Bl43oqyLNzZRABvIq9z-XI8JQjqj2FSDdUUEZGZPTN4uwD5fyi0sONbDxmTFvgWPh_8ZhX6tlDGiupVDBY4eRH43Eettm-t4CDauL7FzB3w3dDPFMB5DhP4rrpk_kATwnY2NKLRbequnh8Z6wLXjcmQNLgrgknXB_gogWAqH29dqKexwceMNIbq-kjaeLsmHSXM9TE9q7_Ln9el04OlkpOVspVguedfINcNFg0DmYLJWyD2ORkOHLmYigN6YnyB9P2NFOnKGlLuQ87GjosI00zBniRGi3PhE9NGd51Qggdbcsm0aM8GiMaZ7SO5i8iQWL10TRFRFyTEfy6hSO8g",
+ "refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6ICJodVl0eVByUEVLQ1phY3FfMW5sOGZscENETnFHdmZEZHctYUxGQXNoWHZVIn0.eyJqdGkiOiJlZmNmNzExNS04YzRiLTQzZmQtOGM0ZS0xNjVhYTVmM2ZhZDEiLCJleHAiOjE1MDY2MDE5NTAsIm5iZiI6MCwiaWF0IjoxNTA2NjAwMTUwLCJpc3MiOiJodHRwOi8vZW50amF2YTAwMjo4MDgwL2F1dGgvcmVhbG1zL2Vsb2dib29rIiwiYXVkIjoiZWxvZ2Jvb2stYmFja2VuZCIsInN1YiI6IjM1OWVmOWM5LTc3ZGYtNGEzZC1hOWM5LWY5NmQ4MzdkMmQ1NyIsInR5cCI6IlJlZnJlc2giLCJhenAiOiJlbG9nYm9vay1iYWNrZW5kIiwiYXV0aF90aW1lIjowLCJzZXNzaW9uX3N0YXRlIjoiOTY1ZjczNTEtMmU4Yi00NTI4LTlmM2QtZWU2MjgzYTk1YjE2IiwicmVhbG1fYWNjZXNzIjp7InJvbGVzIjpbImVsb2dib29rLXN1cGVydXNlciIsImVsb2dib29rLW5vcm1hbHVzZXIiLCJ1bWFfYXV0aG9yaXphdGlvbiJdfSwicmVzb3VyY2VfYWNjZXNzIjp7InJlYWxtLW1hbmFnZW1lbnQiOnsicm9sZXMiOlsidmlldy11c2VycyIsInF1ZXJ5LWdyb3VwcyIsInF1ZXJ5LXVzZXJzIl19LCJhY2NvdW50Ijp7InJvbGVzIjpbIm1hbmFnZS1hY2NvdW50IiwibWFuYWdlLWFjY291bnQtbGlua3MiLCJ2aWV3LXByb2ZpbGUiXX19fQ.rN1f4h9t1-sHW2EXpvYs3Spo8Zxe1-qNuLWCgOwD6E3l_zDwdHOlPxJwlPLwweQ2uuHi1-blk80OdgoDueDslE3tCdkyg_5lXOXG_jVwqgIF8qP2KTlz9gjhJBwBJ94YsHYV2wwy8jvTmUk108FVzEYBvAHL7KMzoD-BJ_4QxLhLuUvhO7I2-xP9sNRnUG_4xOrXl22WhQQVNvWBWL076TOSdBsno8-1oh4zWrXsbRa_iA1GyDQ_QM5Cpf11WE6tfvTDJsEHT_6GBQ8qz8FWSh4P_YtVDTOZZhDbbdddFeZPnQdxkLWXBhpD_jw8JuuE1qR_rAUytWdJpSjz2V90mQ",
+ "token_type": "bearer",
+ "session_state": "965f7351-2e8b-4528-9f3d-ee6283a95b16",
+ "expires_in": 300,
+ "refresh_expires_in": 1800
+}
diff --git a/src/test/resources/VersionInfo.json b/src/test/resources/VersionInfo.json
new file mode 100644
index 0000000..35510d9
--- /dev/null
+++ b/src/test/resources/VersionInfo.json
@@ -0,0 +1,3 @@
+{
+ "backendVersion": "0x.0x.xx"
+}
\ No newline at end of file
diff --git a/src/test/resources/testErrorReturn.json b/src/test/resources/testErrorReturn.json
new file mode 100644
index 0000000..f5540af
--- /dev/null
+++ b/src/test/resources/testErrorReturn.json
@@ -0,0 +1,4 @@
+{
+ "errorText": "TESTAT",
+ "errorCode": 999
+}
diff --git a/src/test/resources/testGeneralReturnItem.json b/src/test/resources/testGeneralReturnItem.json
new file mode 100644
index 0000000..34f9d39
--- /dev/null
+++ b/src/test/resources/testGeneralReturnItem.json
@@ -0,0 +1,3 @@
+{
+ "ret" : "It works!"
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakClientAndRealmRoles.json b/src/test/resources/testKeyCloakClientAndRealmRoles.json
new file mode 100644
index 0000000..a39cb11
--- /dev/null
+++ b/src/test/resources/testKeyCloakClientAndRealmRoles.json
@@ -0,0 +1,159 @@
+{
+ "realmMappings": [
+ {
+ "id": "7a145be5-20ba-4992-ad54-17c28d0bc0f9",
+ "name": "feedin-management-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "37d42cc3-0157-4ab6-b9fe-8be50de37da8",
+ "name": "planned-policies-executor",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "b1cf034b-bce3-4d29-9e9d-692bf420ce83",
+ "name": "planned-policies-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "baf44fc2-7888-4888-beaa-79288e9268a0",
+ "name": "planning-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "a1760267-b72d-4cef-bb2a-91c0d4a24cd7",
+ "name": "planned-policies-measureplanner",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "f41f6144-f788-434d-be7a-ee3190099f5d",
+ "name": "planned-policies-superuser",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "f8fa3a84-b7d8-4ad7-98c5-3c77ca6c1a33",
+ "name": "kon_admin",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "1e41d089-72ea-4b22-a88c-56037b9680d8",
+ "name": "planned-policies-measureapplicant",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "e423626e-4616-45b7-9c3d-10a7f0acab8c",
+ "name": "elogbook-superuser",
+ "description": "",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "69cd9f7d-bd7b-473d-9ae2-8ca8665fa9bf",
+ "name": "planned-policies-requester",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "7533b166-79da-44f6-bb84-fe6a3916c9cd",
+ "name": "planned-policies-measureapprover",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "dc84c3f4-2509-4894-9b91-772b67d1d470",
+ "name": "planned-policies-completion",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "061827bc-771d-4ce1-9123-3d211686c078",
+ "name": "planned-policies-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "27b9578f-416b-4f67-8259-60464636f457",
+ "name": "planned-policies-clearance",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "7b977153-1107-4a7d-b2b3-dc6daa461c15",
+ "name": "kon-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+ "name": "elogbook-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+ "name": "elogbook-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ }
+ ],
+ "clientMappings": {
+ "elogbook-backend": {
+ "id": "e9904530-1ced-4d6b-96dc-fd1f3ce6420c",
+ "client": "elogbook-backend",
+ "mappings": [
+ {
+ "id": "f9971606-b587-41d0-a903-4e97b103e3b2",
+ "name": "testclientrole",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": true,
+ "containerId": "e9904530-1ced-4d6b-96dc-fd1f3ce6420c"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles.json b/src/test/resources/testKeyCloakRoles.json
new file mode 100644
index 0000000..04088f1
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles.json
@@ -0,0 +1,70 @@
+[
+ {
+ "id": "e423626e-4616-45b7-9c3d-10a7f0acab8c",
+ "name": "elogbook-superuser",
+ "description": "Darf sehr sehr viel",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "7a145be5-20ba-4992-ad54-17c28d0bc0f9",
+ "name": "feedin-management-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "b1cf034b-bce3-4d29-9e9d-692bf420ce83",
+ "name": "planned-policies-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "baf44fc2-7888-4888-beaa-79288e9268a0",
+ "name": "planning-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "b20abd6d-f202-41d5-91e2-f3e8266bd1fb",
+ "name": "offline_access",
+ "description": "${role_offline-access}",
+ "scopeParamRequired": true,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "173ed3dd-7c83-4202-bec8-c2f2ab9919fc",
+ "name": "uma_authorization",
+ "description": "${role_uma_authorization}",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+ "name": "elogbook-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+ "name": "elogbook-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ }
+]
diff --git a/src/test/resources/testKeyCloakRoles_noClientRoleAtAll.json b/src/test/resources/testKeyCloakRoles_noClientRoleAtAll.json
new file mode 100644
index 0000000..760a6a1
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noClientRoleAtAll.json
@@ -0,0 +1,21 @@
+{
+ "realmMappings": [
+ {
+ "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+ "name": "elogbook-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+ "name": "elogbook-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json b/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json
new file mode 100644
index 0000000..d11bef0
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noClientRoleForClient.json
@@ -0,0 +1,47 @@
+{
+ "realmMappings": [
+ {
+ "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+ "name": "elogbook-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+ "name": "elogbook-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ }
+ ],
+ "clientMappings": {
+ "account": {
+ "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+ "client": "account",
+ "mappings": [
+ {
+ "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ },
+ {
+ "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_noRealmRole.json b/src/test/resources/testKeyCloakRoles_noRealmRole.json
new file mode 100644
index 0000000..66470b2
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_noRealmRole.json
@@ -0,0 +1,28 @@
+{
+ "clientMappings": {
+ "account": {
+ "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+ "client": "account",
+ "mappings": [
+ {
+ "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ },
+ {
+ "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_onlyClientRole.json b/src/test/resources/testKeyCloakRoles_onlyClientRole.json
new file mode 100644
index 0000000..24aff34
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_onlyClientRole.json
@@ -0,0 +1,28 @@
+{
+ "clientMappings": {
+ "elogbook-backend": {
+ "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+ "client": "elogbook-backend",
+ "mappings": [
+ {
+ "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+ "name": "view-profile",
+ "description": "${role_view-profile}",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ },
+ {
+ "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json b/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json
new file mode 100644
index 0000000..2141a33
--- /dev/null
+++ b/src/test/resources/testKeyCloakRoles_sameClientRealmRole.json
@@ -0,0 +1,47 @@
+{
+ "realmMappings": [
+ {
+ "id": "384e7a68-8e70-41aa-bbbd-1a0ffb293335",
+ "name": "elogbook-access",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ },
+ {
+ "id": "6b8d2da8-220c-4f83-8e15-889004e66359",
+ "name": "elogbook-normaluser",
+ "description": "Darf vieles, aber nicht alles",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": false,
+ "containerId": "elogbook"
+ }
+ ],
+ "clientMappings": {
+ "elogbook-backend": {
+ "id": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed",
+ "client": "elogbook-backend",
+ "mappings": [
+ {
+ "id": "bfcf9034-7921-4200-ad2a-bf3f9c0d3f38",
+ "name": "elogbook-access",
+ "description": "${role_view-profile}",
+ "scopeParamRequired": false,
+ "composite": false,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ },
+ {
+ "id": "0706bea7-d53b-4075-a4ab-d0b175cd660f",
+ "name": "manage-account",
+ "description": "${role_manage-account}",
+ "scopeParamRequired": false,
+ "composite": true,
+ "clientRole": true,
+ "containerId": "ab5b5dd0-e943-4cef-bb86-5f17031ca6ed"
+ }
+ ]
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/test/resources/testKeyCloakUsers.json b/src/test/resources/testKeyCloakUsers.json
new file mode 100644
index 0000000..c590535
--- /dev/null
+++ b/src/test/resources/testKeyCloakUsers.json
@@ -0,0 +1,90 @@
+[
+ {
+ "id": "359ef9c9-77df-4a3d-a9c9-f96d837d2d57",
+ "createdTimestamp": 1501594173784,
+ "username": "admin",
+ "enabled": true,
+ "totp": false,
+ "emailVerified": false,
+ "firstName": "Administrator",
+ "lastName": "Administratowich",
+ "realmRoles": [
+ "elogbook-superuser",
+ "elogbook_access",
+ "feedin_management_access",
+ "planned_policies_access",
+ "offline_access",
+ "uma_authorization",
+ "planning_access",
+ "elogbook-normaluser"
+ ],
+ "disableableCredentialTypes": [
+ "password"
+ ],
+ "requiredActions": [],
+ "access": {
+ "manageGroupMembership": false,
+ "view": true,
+ "mapRoles": false,
+ "impersonate": false,
+ "manage": false
+ }
+ },
+ {
+ "id": "c4b78aa7-91d2-45d7-8ca3-163156d9ee40",
+ "createdTimestamp": 1501594239066,
+ "username": "hugo",
+ "enabled": true,
+ "totp": false,
+ "emailVerified": false,
+ "firstName": "Hugo",
+ "lastName": "Boss",
+ "realmRoles": [
+ "elogbook_access",
+ "feedin_management_access",
+ "planned_policies_access",
+ "offline_access",
+ "uma_authorization",
+ "planning_access",
+ "elogbook-normaluser"
+ ],
+ "disableableCredentialTypes": [
+ "password"
+ ],
+ "requiredActions": [],
+ "access": {
+ "manageGroupMembership": false,
+ "view": true,
+ "mapRoles": false,
+ "impersonate": false,
+ "manage": false
+ }
+ },
+ {
+ "id": "c2e9d7ae-2bfa-4578-b09e-f5dc5f09a879",
+ "createdTimestamp": 1501594273661,
+ "username": "otto",
+ "enabled": true,
+ "totp": false,
+ "emailVerified": false,
+ "firstName": "Otto",
+ "lastName": "Normalverbraucher",
+ "realmRoles": [
+ "elogbook_access",
+ "offline_access",
+ "uma_authorization",
+ "elogbook-normaluser"
+ ],
+ "disableableCredentialTypes": [
+ "password"
+ ],
+ "requiredActions": [],
+ "access": {
+ "manageGroupMembership": false,
+ "view": true,
+ "mapRoles": false,
+ "impersonate": false,
+ "manage": false
+ }
+ }
+]
\ No newline at end of file
diff --git a/src/test/resources/testLoginCredentials.json b/src/test/resources/testLoginCredentials.json
new file mode 100644
index 0000000..88974c6
--- /dev/null
+++ b/src/test/resources/testLoginCredentials.json
@@ -0,0 +1,4 @@
+{
+ "userName": "Carlo",
+ "password": "Cottura"
+}
\ No newline at end of file
diff --git a/src/test/resources/testUserAuthentication.json b/src/test/resources/testUserAuthentication.json
new file mode 100644
index 0000000..2cdef21
--- /dev/null
+++ b/src/test/resources/testUserAuthentication.json
@@ -0,0 +1,8 @@
+{
+ "id": 1,
+ "selected": true,
+ "username": "Pedro",
+ "password": "pwd",
+ "name": "Pedro Pepito Sanchez",
+ "specialUser": false
+}