First Commit
This commit is contained in:
commit
09b028d42a
|
@ -0,0 +1,18 @@
|
|||
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
|
||||
# For additional information regarding the format and rule options, please see:
|
||||
# https://github.com/browserslist/browserslist#queries
|
||||
|
||||
# For the full list of supported browsers by the Angular framework, please see:
|
||||
# https://angular.io/guide/browser-support
|
||||
|
||||
# You can see what browsers were selected by your queries by running:
|
||||
# npx browserslist
|
||||
|
||||
last 1 Chrome version
|
||||
last 1 Firefox version
|
||||
last 2 Edge major versions
|
||||
last 2 Safari major versions
|
||||
last 2 iOS major versions
|
||||
Firefox ESR
|
||||
not IE 9-10 # Angular support for IE 9-10 has been deprecated and will be removed as of Angular v11. To opt-in, remove the 'not' prefix on this line.
|
||||
not IE 11 # Angular supports IE 11 only as an opt-in. To opt-in, remove the 'not' prefix on this line.
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
|
||||
<attributes>
|
||||
<attribute name="test" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-11">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
|
||||
<attributes>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" path="target/generated-sources/annotations">
|
||||
<attributes>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
|
||||
<attributes>
|
||||
<attribute name="optional" value="true"/>
|
||||
<attribute name="maven.pomderived" value="true"/>
|
||||
<attribute name="ignore_optional_problems" value="true"/>
|
||||
<attribute name="m2e-apt" value="true"/>
|
||||
<attribute name="test" value="true"/>
|
||||
</attributes>
|
||||
</classpathentry>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
|
@ -0,0 +1,25 @@
|
|||
# See here for image contents: https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/java/.devcontainer/base.Dockerfile
|
||||
|
||||
# [Choice] Java version (use -bullseye variants on local arm64/Apple Silicon): 11, 17, 11-bullseye, 17-bullseye, 11-buster, 17-buster
|
||||
ARG VARIANT="11"
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/java:0-${VARIANT}
|
||||
|
||||
# [Option] Install Maven
|
||||
ARG INSTALL_MAVEN="false"
|
||||
ARG MAVEN_VERSION=""
|
||||
# [Option] Install Gradle
|
||||
ARG INSTALL_GRADLE="false"
|
||||
ARG GRADLE_VERSION=""
|
||||
RUN if [ "${INSTALL_MAVEN}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install maven \"${MAVEN_VERSION}\""; fi \
|
||||
&& if [ "${INSTALL_GRADLE}" = "true" ]; then su vscode -c "umask 0002 && . /usr/local/sdkman/bin/sdkman-init.sh && sdk install gradle \"${GRADLE_VERSION}\""; fi
|
||||
|
||||
# [Choice] Node.js version: none, lts/*, 16, 14, 12, 10
|
||||
ARG NODE_VERSION="none"
|
||||
RUN if [ "${NODE_VERSION}" != "none" ]; then su vscode -c "umask 0002 && . /usr/local/share/nvm/nvm.sh && nvm install ${NODE_VERSION} 2>&1"; fi
|
||||
|
||||
# [Optional] Uncomment this section to install additional OS packages.
|
||||
# RUN apt-get update && export DEBIAN_FRONTEND=noninteractive \
|
||||
# && apt-get -y install --no-install-recommends <your-package-list-here>
|
||||
|
||||
# [Optional] Uncomment this line to install global node packages.
|
||||
# RUN su vscode -c "source /usr/local/share/nvm/nvm.sh && npm install -g <your-package-here>" 2>&1
|
|
@ -0,0 +1,48 @@
|
|||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the README at:
|
||||
// https://github.com/microsoft/vscode-dev-containers/tree/v0.209.6/containers/java
|
||||
{
|
||||
"name": "Informationsystemmonitor",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": {
|
||||
// Update the VARIANT arg to pick a Java version: 11, 17
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use the -bullseye variants on local arm64/Apple Silicon.
|
||||
"VARIANT": "11",
|
||||
// Options
|
||||
"INSTALL_MAVEN": "true",
|
||||
"INSTALL_GRADLE": "false",
|
||||
"NODE_VERSION": "lts/*"
|
||||
}
|
||||
},
|
||||
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"java.home": "/docker-java-home"
|
||||
},
|
||||
|
||||
// Add the IDs of extensions you want installed when the container is created.
|
||||
"extensions": [
|
||||
"angular.ng-template",
|
||||
"christian-kohler.npm-intellisense",
|
||||
"firsttris.vscode-jest-runner",
|
||||
"ms-vscode.vscode-typescript-tslint-plugin",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"vscjava.vscode-java-pack",
|
||||
"pivotal.vscode-boot-dev-pack",
|
||||
"esbenp.prettier-vscode"
|
||||
],
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
"forwardPorts": [4200, 3001, 9000, 8080],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
// "postCreateCommand": "java -version",
|
||||
|
||||
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
|
||||
"remoteUser": "vscode",
|
||||
"features": {
|
||||
"docker-in-docker": "latest",
|
||||
"docker-from-docker": "latest"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
# EditorConfig helps developers define and maintain consistent
|
||||
# coding styles between different editors and IDEs
|
||||
# editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
|
||||
# We recommend you to keep these unchanged
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# Change these settings to your own preference
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[*.{ts,tsx,js,jsx,json,css,scss,yml,html,vue}]
|
||||
indent_size = 2
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
|
@ -0,0 +1,8 @@
|
|||
node_modules/
|
||||
src/main/docker/
|
||||
jest.conf.js
|
||||
webpack/
|
||||
target/
|
||||
build/
|
||||
node/
|
||||
postcss.config.js
|
|
@ -0,0 +1,99 @@
|
|||
{
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"plugins": ["@angular-eslint/eslint-plugin", "@typescript-eslint"],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:@angular-eslint/recommended",
|
||||
"prettier",
|
||||
"eslint-config-prettier"
|
||||
],
|
||||
"env": {
|
||||
"browser": true,
|
||||
"es6": true,
|
||||
"commonjs": true
|
||||
},
|
||||
"parserOptions": {
|
||||
"ecmaVersion": 2018,
|
||||
"sourceType": "module",
|
||||
"project": ["./tsconfig.app.json", "./tsconfig.spec.json"]
|
||||
},
|
||||
"rules": {
|
||||
"@angular-eslint/component-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "element",
|
||||
"prefix": "jhi",
|
||||
"style": "kebab-case"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/directive-selector": [
|
||||
"error",
|
||||
{
|
||||
"type": "attribute",
|
||||
"prefix": "jhi",
|
||||
"style": "camelCase"
|
||||
}
|
||||
],
|
||||
"@angular-eslint/relative-url-prefix": "error",
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
"extendDefaults": true,
|
||||
"types": {
|
||||
"{}": false
|
||||
}
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", { "allowExpressions": true }],
|
||||
"@typescript-eslint/explicit-module-boundary-types": "off",
|
||||
"@typescript-eslint/member-ordering": [
|
||||
"error",
|
||||
{
|
||||
"default": [
|
||||
"public-static-field",
|
||||
"protected-static-field",
|
||||
"private-static-field",
|
||||
"public-instance-field",
|
||||
"protected-instance-field",
|
||||
"private-instance-field",
|
||||
"constructor",
|
||||
"public-static-method",
|
||||
"protected-static-method",
|
||||
"private-static-method",
|
||||
"public-instance-method",
|
||||
"protected-instance-method",
|
||||
"private-instance-method"
|
||||
]
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/no-explicit-any": "off",
|
||||
"@typescript-eslint/no-floating-promises": "off",
|
||||
"@typescript-eslint/no-non-null-assertion": "off",
|
||||
"@typescript-eslint/no-parameter-properties": ["warn", { "allows": ["public", "private", "protected"] }],
|
||||
"@typescript-eslint/no-shadow": ["error"],
|
||||
"@typescript-eslint/no-unnecessary-condition": "error",
|
||||
"@typescript-eslint/no-unsafe-argument": "off",
|
||||
"@typescript-eslint/no-unsafe-assignment": "off",
|
||||
"@typescript-eslint/no-unsafe-call": "off",
|
||||
"@typescript-eslint/no-unsafe-member-access": "off",
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "error",
|
||||
"@typescript-eslint/prefer-optional-chain": "error",
|
||||
"@typescript-eslint/unbound-method": "off",
|
||||
"arrow-body-style": "error",
|
||||
"curly": "error",
|
||||
"eqeqeq": ["error", "always", { "null": "ignore" }],
|
||||
"guard-for-in": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-caller": "error",
|
||||
"no-console": ["error", { "allow": ["warn", "error"] }],
|
||||
"no-eval": "error",
|
||||
"no-labels": "error",
|
||||
"no-new": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"object-shorthand": ["error", "always", { "avoidExplicitReturnArrows": true }],
|
||||
"radix": "error",
|
||||
"spaced-comment": ["warn", "always"]
|
||||
}
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
<factorypath>
|
||||
<factorypathentry kind="VARJAR" id="M2_REPO/org/projectlombok/lombok/1.18.24/lombok-1.18.24.jar" enabled="true" runInBatchMode="false"/>
|
||||
<factorypathentry kind="VARJAR" id="M2_REPO/org/springframework/boot/spring-boot-configuration-processor/2.7.3/spring-boot-configuration-processor-2.7.3.jar" enabled="true" runInBatchMode="false"/>
|
||||
<factorypathentry kind="VARJAR" id="M2_REPO/org/mapstruct/mapstruct-processor/1.5.2.Final/mapstruct-processor-1.5.2.Final.jar" enabled="true" runInBatchMode="false"/>
|
||||
</factorypath>
|
|
@ -0,0 +1,2 @@
|
|||
/target/
|
||||
/node_modules/
|
|
@ -0,0 +1 @@
|
|||
|
Binary file not shown.
|
@ -0,0 +1,18 @@
|
|||
# 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
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
|
|
@ -0,0 +1,8 @@
|
|||
node_modules
|
||||
target
|
||||
build
|
||||
package-lock.json
|
||||
.git
|
||||
.mvn
|
||||
gradle
|
||||
.gradle
|
|
@ -0,0 +1,18 @@
|
|||
# Prettier configuration
|
||||
|
||||
printWidth: 140
|
||||
singleQuote: true
|
||||
tabWidth: 2
|
||||
useTabs: false
|
||||
|
||||
# js and ts rules:
|
||||
arrowParens: avoid
|
||||
|
||||
# jsx and tsx rules:
|
||||
bracketSameLine: false
|
||||
|
||||
# java rules:
|
||||
overrides:
|
||||
- files: "*.java"
|
||||
options:
|
||||
tabWidth: 4
|
|
@ -0,0 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>informationsystemmonitor</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.boot.validation.springbootbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.m2e.core.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
<nature>org.eclipse.m2e.core.maven2Nature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
|
@ -0,0 +1,6 @@
|
|||
eclipse.preferences.version=1
|
||||
encoding//src/main/java=UTF-8
|
||||
encoding//src/main/resources=UTF-8
|
||||
encoding//src/test/java=UTF-8
|
||||
encoding//src/test/resources=UTF-8
|
||||
encoding/<project>=UTF-8
|
|
@ -0,0 +1,4 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.apt.aptEnabled=true
|
||||
org.eclipse.jdt.apt.genSrcDir=target/generated-sources/annotations
|
||||
org.eclipse.jdt.apt.genTestSrcDir=target/generated-test-sources/test-annotations
|
|
@ -0,0 +1,9 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=11
|
||||
org.eclipse.jdt.core.compiler.compliance=11
|
||||
org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures=disabled
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.problem.reportPreviewFeatures=ignore
|
||||
org.eclipse.jdt.core.compiler.processAnnotations=enabled
|
||||
org.eclipse.jdt.core.compiler.release=disabled
|
||||
org.eclipse.jdt.core.compiler.source=11
|
|
@ -0,0 +1,4 @@
|
|||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
|
@ -0,0 +1,2 @@
|
|||
boot.validation.initialized=true
|
||||
eclipse.preferences.version=1
|
|
@ -0,0 +1,8 @@
|
|||
{
|
||||
"generator-jhipster:7.9.3": {
|
||||
"promptValues": {
|
||||
"packageName": "org.gcube.fullstackapps.informationsystemmonitor",
|
||||
"nativeLanguage": "en"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
{
|
||||
"generator-jhipster": {
|
||||
"applicationType": "monolith",
|
||||
"authenticationType": "oauth2",
|
||||
"baseName": "informationsystemmonitor",
|
||||
"blueprints": [],
|
||||
"buildTool": "maven",
|
||||
"cacheProvider": "no",
|
||||
"clientFramework": "angularX",
|
||||
"clientPackageManager": "npm",
|
||||
"clientTheme": "none",
|
||||
"clientThemeVariant": "",
|
||||
"creationTimestamp": 1687526025362,
|
||||
"databaseType": "no",
|
||||
"devDatabaseType": "no",
|
||||
"devServerPort": 4200,
|
||||
"dtoSuffix": "DTO",
|
||||
"enableGradleEnterprise": false,
|
||||
"enableHibernateCache": false,
|
||||
"enableSwaggerCodegen": true,
|
||||
"enableTranslation": true,
|
||||
"entitySuffix": "",
|
||||
"jhiPrefix": "jhi",
|
||||
"jhipsterVersion": "7.9.3",
|
||||
"languages": ["en"],
|
||||
"messageBroker": false,
|
||||
"microfrontend": false,
|
||||
"microfrontends": [],
|
||||
"monorepository": true,
|
||||
"nativeLanguage": "en",
|
||||
"otherModules": [],
|
||||
"packageName": "org.gcube.fullstackapps.informationsystemmonitor",
|
||||
"pages": [],
|
||||
"prodDatabaseType": "no",
|
||||
"reactive": false,
|
||||
"searchEngine": false,
|
||||
"serverPort": "8080",
|
||||
"serverSideOptions": ["enableSwaggerCodegen:true"],
|
||||
"serviceDiscoveryType": "no",
|
||||
"skipCheckLengthOfIdentifier": false,
|
||||
"skipClient": false,
|
||||
"skipCommitHook": true,
|
||||
"skipFakeData": false,
|
||||
"skipUserManagement": true,
|
||||
"testFrameworks": [],
|
||||
"websocket": false,
|
||||
"withAdminUi": true
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
# Changelog for "informationsystemmonitor"
|
||||
|
||||
|
||||
## [v1.0.0-SNAPSHOT]
|
||||
|
||||
- First Release
|
|
@ -0,0 +1,26 @@
|
|||
# Acknowledgments
|
||||
|
||||
The projects leading to this software have received funding from a series of European Union programmes including:
|
||||
|
||||
- the Sixth Framework Programme for Research and Technological Development
|
||||
- [DILIGENT](https://cordis.europa.eu/project/id/004260) (grant no. 004260).
|
||||
- the Seventh Framework Programme for research, technological development and demonstration
|
||||
- [D4Science](https://cordis.europa.eu/project/id/212488) (grant no. 212488);
|
||||
- [D4Science-II](https://cordis.europa.eu/project/id/239019) (grant no.239019);
|
||||
- [ENVRI](https://cordis.europa.eu/project/id/283465) (grant no. 283465);
|
||||
- [iMarine](https://cordis.europa.eu/project/id/283644) (grant no. 283644);
|
||||
- [EUBrazilOpenBio](https://cordis.europa.eu/project/id/288754) (grant no. 288754).
|
||||
- the H2020 research and innovation programme
|
||||
- [SoBigData](https://cordis.europa.eu/project/id/654024) (grant no. 654024);
|
||||
- [PARTHENOS](https://cordis.europa.eu/project/id/654119) (grant no. 654119);
|
||||
- [EGI-Engage](https://cordis.europa.eu/project/id/654142) (grant no. 654142);
|
||||
- [ENVRI PLUS](https://cordis.europa.eu/project/id/654182) (grant no. 654182);
|
||||
- [BlueBRIDGE](https://cordis.europa.eu/project/id/675680) (grant no. 675680);
|
||||
- [PerformFISH](https://cordis.europa.eu/project/id/727610) (grant no. 727610);
|
||||
- [AGINFRA PLUS](https://cordis.europa.eu/project/id/731001) (grant no. 731001);
|
||||
- [DESIRA](https://cordis.europa.eu/project/id/818194) (grant no. 818194);
|
||||
- [ARIADNEplus](https://cordis.europa.eu/project/id/823914) (grant no. 823914);
|
||||
- [RISIS 2](https://cordis.europa.eu/project/id/824091) (grant no. 824091);
|
||||
- [EOSC-Pillar](https://cordis.europa.eu/project/id/857650) (grant no. 857650);
|
||||
- [Blue Cloud](https://cordis.europa.eu/project/id/862409) (grant no. 862409);
|
||||
- [SoBigData-PlusPlus](https://cordis.europa.eu/project/id/871042) (grant no. 871042);
|
|
@ -0,0 +1,311 @@
|
|||
# European Union Public Licence V. 1.1
|
||||
|
||||
|
||||
EUPL © the European Community 2007
|
||||
|
||||
|
||||
This European Union Public Licence (the “EUPL”) applies to the Work or Software
|
||||
(as defined below) which is provided under the terms of this Licence. Any use of
|
||||
the Work, other than as authorised under this Licence is prohibited (to the
|
||||
extent such use is covered by a right of the copyright holder of the Work).
|
||||
|
||||
The Original Work is provided under the terms of this Licence when the Licensor
|
||||
(as defined below) has placed the following notice immediately following the
|
||||
copyright notice for the Original Work:
|
||||
|
||||
Licensed under the EUPL V.1.1
|
||||
|
||||
or has expressed by any other mean his willingness to license under the EUPL.
|
||||
|
||||
|
||||
|
||||
## 1. Definitions
|
||||
|
||||
In this Licence, the following terms have the following meaning:
|
||||
|
||||
- The Licence: this Licence.
|
||||
|
||||
- The Original Work or the Software: the software distributed and/or
|
||||
communicated by the Licensor under this Licence, available as Source Code and
|
||||
also as Executable Code as the case may be.
|
||||
|
||||
- Derivative Works: the works or software that could be created by the Licensee,
|
||||
based upon the Original Work or modifications thereof. This Licence does not
|
||||
define the extent of modification or dependence on the Original Work required
|
||||
in order to classify a work as a Derivative Work; this extent is determined by
|
||||
copyright law applicable in the country mentioned in Article 15.
|
||||
|
||||
- The Work: the Original Work and/or its Derivative Works.
|
||||
|
||||
- The Source Code: the human-readable form of the Work which is the most
|
||||
convenient for people to study and modify.
|
||||
|
||||
- The Executable Code: any code which has generally been compiled and which is
|
||||
meant to be interpreted by a computer as a program.
|
||||
|
||||
- The Licensor: the natural or legal person that distributes and/or communicates
|
||||
the Work under the Licence.
|
||||
|
||||
- Contributor(s): any natural or legal person who modifies the Work under the
|
||||
Licence, or otherwise contributes to the creation of a Derivative Work.
|
||||
|
||||
- The Licensee or “You”: any natural or legal person who makes any usage of the
|
||||
Software under the terms of the Licence.
|
||||
|
||||
- Distribution and/or Communication: any act of selling, giving, lending,
|
||||
renting, distributing, communicating, transmitting, or otherwise making
|
||||
available, on-line or off-line, copies of the Work or providing access to its
|
||||
essential functionalities at the disposal of any other natural or legal
|
||||
person.
|
||||
|
||||
|
||||
|
||||
## 2. Scope of the rights granted by the Licence
|
||||
|
||||
The Licensor hereby grants You a world-wide, royalty-free, non-exclusive,
|
||||
sub-licensable licence to do the following, for the duration of copyright vested
|
||||
in the Original Work:
|
||||
|
||||
- use the Work in any circumstance and for all usage, reproduce the Work, modify
|
||||
- the Original Work, and make Derivative Works based upon the Work, communicate
|
||||
- to the public, including the right to make available or display the Work or
|
||||
- copies thereof to the public and perform publicly, as the case may be, the
|
||||
- Work, distribute the Work or copies thereof, lend and rent the Work or copies
|
||||
- thereof, sub-license rights in the Work or copies thereof.
|
||||
|
||||
Those rights can be exercised on any media, supports and formats, whether now
|
||||
known or later invented, as far as the applicable law permits so.
|
||||
|
||||
In the countries where moral rights apply, the Licensor waives his right to
|
||||
exercise his moral right to the extent allowed by law in order to make effective
|
||||
the licence of the economic rights here above listed.
|
||||
|
||||
The Licensor grants to the Licensee royalty-free, non exclusive usage rights to
|
||||
any patents held by the Licensor, to the extent necessary to make use of the
|
||||
rights granted on the Work under this Licence.
|
||||
|
||||
|
||||
|
||||
## 3. Communication of the Source Code
|
||||
|
||||
The Licensor may provide the Work either in its Source Code form, or as
|
||||
Executable Code. If the Work is provided as Executable Code, the Licensor
|
||||
provides in addition a machine-readable copy of the Source Code of the Work
|
||||
along with each copy of the Work that the Licensor distributes or indicates, in
|
||||
a notice following the copyright notice attached to the Work, a repository where
|
||||
the Source Code is easily and freely accessible for as long as the Licensor
|
||||
continues to distribute and/or communicate the Work.
|
||||
|
||||
|
||||
|
||||
## 4. Limitations on copyright
|
||||
|
||||
Nothing in this Licence is intended to deprive the Licensee of the benefits from
|
||||
any exception or limitation to the exclusive rights of the rights owners in the
|
||||
Original Work or Software, of the exhaustion of those rights or of other
|
||||
applicable limitations thereto.
|
||||
|
||||
|
||||
|
||||
## 5. Obligations of the Licensee
|
||||
|
||||
The grant of the rights mentioned above is subject to some restrictions and
|
||||
obligations imposed on the Licensee. Those obligations are the following:
|
||||
|
||||
Attribution right: the Licensee shall keep intact all copyright, patent or
|
||||
trademarks notices and all notices that refer to the Licence and to the
|
||||
disclaimer of warranties. The Licensee must include a copy of such notices and a
|
||||
copy of the Licence with every copy of the Work he/she distributes and/or
|
||||
communicates. The Licensee must cause any Derivative Work to carry prominent
|
||||
notices stating that the Work has been modified and the date of modification.
|
||||
|
||||
Copyleft clause: If the Licensee distributes and/or communicates copies of the
|
||||
Original Works or Derivative Works based upon the Original Work, this
|
||||
Distribution and/or Communication will be done under the terms of this Licence
|
||||
or of a later version of this Licence unless the Original Work is expressly
|
||||
distributed only under this version of the Licence. The Licensee (becoming
|
||||
Licensor) cannot offer or impose any additional terms or conditions on the Work
|
||||
or Derivative Work that alter or restrict the terms of the Licence.
|
||||
|
||||
Compatibility clause: If the Licensee Distributes and/or Communicates Derivative
|
||||
Works or copies thereof based upon both the Original Work and another work
|
||||
licensed under a Compatible Licence, this Distribution and/or Communication can
|
||||
be done under the terms of this Compatible Licence. For the sake of this clause,
|
||||
“Compatible Licence” refers to the licences listed in the appendix attached to
|
||||
this Licence. Should the Licensee’s obligations under the Compatible Licence
|
||||
conflict with his/her obligations under this Licence, the obligations of the
|
||||
Compatible Licence shall prevail.
|
||||
|
||||
Provision of Source Code: When distributing and/or communicating copies of the
|
||||
Work, the Licensee will provide a machine-readable copy of the Source Code or
|
||||
indicate a repository where this Source will be easily and freely available for
|
||||
as long as the Licensee continues to distribute and/or communicate the Work.
|
||||
|
||||
Legal Protection: This Licence does not grant permission to use the trade names,
|
||||
trademarks, service marks, or names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the copyright notice.
|
||||
|
||||
|
||||
|
||||
## 6. Chain of Authorship
|
||||
|
||||
The original Licensor warrants that the copyright in the Original Work granted
|
||||
hereunder is owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
|
||||
Each Contributor warrants that the copyright in the modifications he/she brings
|
||||
to the Work are owned by him/her or licensed to him/her and that he/she has the
|
||||
power and authority to grant the Licence.
|
||||
|
||||
Each time You accept the Licence, the original Licensor and subsequent
|
||||
Contributors grant You a licence to their contributions to the Work, under the
|
||||
terms of this Licence.
|
||||
|
||||
|
||||
|
||||
## 7. Disclaimer of Warranty
|
||||
|
||||
The Work is a work in progress, which is continuously improved by numerous
|
||||
contributors. It is not a finished work and may therefore contain defects or
|
||||
“bugs” inherent to this type of software development.
|
||||
|
||||
For the above reason, the Work is provided under the Licence on an “as is” basis
|
||||
and without warranties of any kind concerning the Work, including without
|
||||
limitation merchantability, fitness for a particular purpose, absence of defects
|
||||
or errors, accuracy, non-infringement of intellectual property rights other than
|
||||
copyright as stated in Article 6 of this Licence.
|
||||
|
||||
This disclaimer of warranty is an essential part of the Licence and a condition
|
||||
for the grant of any rights to the Work.
|
||||
|
||||
|
||||
|
||||
## 8. Disclaimer of Liability
|
||||
|
||||
Except in the cases of wilful misconduct or damages directly caused to natural
|
||||
persons, the Licensor will in no event be liable for any direct or indirect,
|
||||
material or moral, damages of any kind, arising out of the Licence or of the use
|
||||
of the Work, including without limitation, damages for loss of goodwill, work
|
||||
stoppage, computer failure or malfunction, loss of data or any commercial
|
||||
damage, even if the Licensor has been advised of the possibility of such
|
||||
damage. However, the Licensor will be liable under statutory product liability
|
||||
laws as far such laws apply to the Work.
|
||||
|
||||
|
||||
|
||||
## 9. Additional agreements
|
||||
|
||||
While distributing the Original Work or Derivative Works, You may choose to
|
||||
conclude an additional agreement to offer, and charge a fee for, acceptance of
|
||||
support, warranty, indemnity, or other liability obligations and/or services
|
||||
consistent with this Licence. However, in accepting such obligations, You may
|
||||
act only on your own behalf and on your sole responsibility, not on behalf of
|
||||
the original Licensor or any other Contributor, and only if You agree to
|
||||
indemnify, defend, and hold each Contributor harmless for any liability incurred
|
||||
by, or claims asserted against such Contributor by the fact You have accepted
|
||||
any such warranty or additional liability.
|
||||
|
||||
|
||||
|
||||
## 10. Acceptance of the Licence
|
||||
|
||||
The provisions of this Licence can be accepted by clicking on an icon “I agree”
|
||||
placed under the bottom of a window displaying the text of this Licence or by
|
||||
affirming consent in any other similar way, in accordance with the rules of
|
||||
applicable law. Clicking on that icon indicates your clear and irrevocable
|
||||
acceptance of this Licence and all of its terms and conditions.
|
||||
|
||||
Similarly, you irrevocably accept this Licence and all of its terms and
|
||||
conditions by exercising any rights granted to You by Article 2 of this Licence,
|
||||
such as the use of the Work, the creation by You of a Derivative Work or the
|
||||
Distribution and/or Communication by You of the Work or copies thereof.
|
||||
|
||||
|
||||
|
||||
## 11. Information to the public
|
||||
|
||||
In case of any Distribution and/or Communication of the Work by means of
|
||||
electronic communication by You (for example, by offering to download the Work
|
||||
from a remote location) the distribution channel or media (for example, a
|
||||
website) must at least provide to the public the information requested by the
|
||||
applicable law regarding the Licensor, the Licence and the way it may be
|
||||
accessible, concluded, stored and reproduced by the Licensee.
|
||||
|
||||
|
||||
|
||||
## 12. Termination of the Licence
|
||||
|
||||
The Licence and the rights granted hereunder will terminate automatically upon
|
||||
any breach by the Licensee of the terms of the Licence.
|
||||
|
||||
Such a termination will not terminate the licences of any person who has
|
||||
received the Work from the Licensee under the Licence, provided such persons
|
||||
remain in full compliance with the Licence.
|
||||
|
||||
|
||||
|
||||
## 13. Miscellaneous
|
||||
|
||||
Without prejudice of Article 9 above, the Licence represents the complete
|
||||
agreement between the Parties as to the Work licensed hereunder.
|
||||
|
||||
If any provision of the Licence is invalid or unenforceable under applicable
|
||||
law, this will not affect the validity or enforceability of the Licence as a
|
||||
whole. Such provision will be construed and/or reformed so as necessary to make
|
||||
it valid and enforceable.
|
||||
|
||||
The European Commission may publish other linguistic versions and/or new
|
||||
versions of this Licence, so far this is required and reasonable, without
|
||||
reducing the scope of the rights granted by the Licence. New versions of the
|
||||
Licence will be published with a unique version number.
|
||||
|
||||
All linguistic versions of this Licence, approved by the European Commission,
|
||||
have identical value. Parties can take advantage of the linguistic version of
|
||||
their choice.
|
||||
|
||||
|
||||
|
||||
## 14. Jurisdiction
|
||||
|
||||
Any litigation resulting from the interpretation of this License, arising
|
||||
between the European Commission, as a Licensor, and any Licensee, will be
|
||||
subject to the jurisdiction of the Court of Justice of the European Communities,
|
||||
as laid down in article 238 of the Treaty establishing the European Community.
|
||||
|
||||
Any litigation arising between Parties, other than the European Commission, and
|
||||
resulting from the interpretation of this License, will be subject to the
|
||||
exclusive jurisdiction of the competent court where the Licensor resides or
|
||||
conducts its primary business.
|
||||
|
||||
|
||||
|
||||
## 15. Applicable Law
|
||||
|
||||
This Licence shall be governed by the law of the European Union country where
|
||||
the Licensor resides or has his registered office.
|
||||
|
||||
This licence shall be governed by the Belgian law if:
|
||||
|
||||
- a litigation arises between the European Commission, as a Licensor, and any
|
||||
- Licensee; the Licensor, other than the European Commission, has no residence
|
||||
- or registered office inside a European Union country.
|
||||
|
||||
|
||||
|
||||
## Appendix
|
||||
|
||||
|
||||
|
||||
“Compatible Licences” according to article 5 EUPL are:
|
||||
|
||||
|
||||
- GNU General Public License (GNU GPL) v. 2
|
||||
|
||||
- Open Software License (OSL) v. 2.1, v. 3.0
|
||||
|
||||
- Common Public License v. 1.0
|
||||
|
||||
- Eclipse Public License v. 1.0
|
||||
|
||||
- Cecill v. 2.0
|
|
@ -0,0 +1,39 @@
|
|||
# Information System Monitor
|
||||
|
||||
Information System Monitor is a administration tool for monitoring and displaying resources data concerning the D4Science Infrastructure.
|
||||
|
||||
## Structure of the project
|
||||
|
||||
* The source code is present in the src folder.
|
||||
|
||||
## Built With
|
||||
|
||||
* [OpenJDK](https://openjdk.java.net/) - The JDK used
|
||||
* [Maven](https://maven.apache.org/) - Dependency Management
|
||||
|
||||
## Documentation
|
||||
|
||||
* Use of this application is is described on [Wiki](https://wiki.gcube-system.org/gcube/InformationSytemMonitor).
|
||||
|
||||
## Change log
|
||||
|
||||
See [Releases](https://code-repo.d4science.org/gCubeSystem/informationsystemmonitor/releases).
|
||||
|
||||
## Authors
|
||||
|
||||
* **Maria Teresa Paratore** ([ORCID](http://orcid.org/0000-0001-8375-6644)) - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
|
||||
* **Giancarlo Panichi** ([ORCID](http://orcid.org/0000-0001-8375-6644)) - [ISTI-CNR Infrascience Group](http://nemis.isti.cnr.it/groups/infrascience)
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the EUPL V.1.1 License - see the [LICENSE.md](LICENSE.md) file for details.
|
||||
|
||||
|
||||
## About the gCube Framework
|
||||
This software is part of the [gCubeFramework](https://www.gcube-system.org/ "gCubeFramework"): an
|
||||
open-source software toolkit used for building and operating Hybrid Data
|
||||
Infrastructures enabling the dynamic deployment of Virtual Research Environments
|
||||
by favouring the realisation of reuse oriented policies.
|
||||
|
||||
The projects leading to this software have received funding from a series of European Union programmes see [FUNDING.md](FUNDING.md)
|
|
@ -0,0 +1,396 @@
|
|||
# informationsystemmonitor
|
||||
|
||||
This application was generated using JHipster 7.9.3, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v7.9.3](https://www.jhipster.tech/documentation-archive/v7.9.3).
|
||||
|
||||
## Project Structure
|
||||
|
||||
Node is required for generation and recommended for development. `package.json` is always generated for a better development experience with prettier, commit hooks, scripts and so on.
|
||||
|
||||
In the project root, JHipster generates configuration files for tools like git, prettier, eslint, husky, and others that are well known and you can find references in the web.
|
||||
|
||||
`/src/*` structure follows default Java structure.
|
||||
|
||||
- `.yo-rc.json` - Yeoman configuration file
|
||||
JHipster configuration is stored in this file at `generator-jhipster` key. You may find `generator-jhipster-*` for specific blueprints configuration.
|
||||
- `.yo-resolve` (optional) - Yeoman conflict resolver
|
||||
Allows to use a specific action when conflicts are found skipping prompts for files that matches a pattern. Each line should match `[pattern] [action]` with pattern been a [Minimatch](https://github.com/isaacs/minimatch#minimatch) pattern and action been one of skip (default if ommited) or force. Lines starting with `#` are considered comments and are ignored.
|
||||
- `.jhipster/*.json` - JHipster entity configuration files
|
||||
|
||||
- `npmw` - wrapper to use locally installed npm.
|
||||
JHipster installs Node and npm locally using the build tool by default. This wrapper makes sure npm is installed locally and uses it avoiding some differences different versions can cause. By using `./npmw` instead of the traditional `npm` you can configure a Node-less environment to develop or test your application.
|
||||
- `/src/main/docker` - Docker configurations for the application and services that the application depends on
|
||||
|
||||
## Development
|
||||
|
||||
Before you can build this project, you must install and configure the following dependencies on your machine:
|
||||
|
||||
1. [Node.js][]: We use Node to run a development web server and build the project.
|
||||
Depending on your system, you can install Node either from source or as a pre-packaged bundle.
|
||||
|
||||
After installing Node, you should be able to run the following command to install development tools.
|
||||
You will only need to run this command when dependencies change in [package.json](package.json).
|
||||
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
We use npm scripts and [Angular CLI][] with [Webpack][] as our build system.
|
||||
|
||||
Run the following commands in two separate terminals to create a blissful development experience where your browser
|
||||
auto-refreshes when files change on your hard drive.
|
||||
|
||||
```
|
||||
./mvnw
|
||||
npm start
|
||||
```
|
||||
|
||||
Npm is also used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by
|
||||
specifying a newer version in [package.json](package.json). You can also run `npm update` and `npm install` to manage dependencies.
|
||||
Add the `help` flag on any command to see how you can use it. For example, `npm help update`.
|
||||
|
||||
The `npm run` command will list all of the scripts available to run for this project.
|
||||
|
||||
### PWA Support
|
||||
|
||||
JHipster ships with PWA (Progressive Web App) support, and it's turned off by default. One of the main components of a PWA is a service worker.
|
||||
|
||||
The service worker initialization code is disabled by default. To enable it, uncomment the following code in `src/main/webapp/app/app.module.ts`:
|
||||
|
||||
```typescript
|
||||
ServiceWorkerModule.register('ngsw-worker.js', { enabled: false }),
|
||||
```
|
||||
|
||||
### Managing dependencies
|
||||
|
||||
For example, to add [Leaflet][] library as a runtime dependency of your application, you would run following command:
|
||||
|
||||
```
|
||||
npm install --save --save-exact leaflet
|
||||
```
|
||||
|
||||
To benefit from TypeScript type definitions from [DefinitelyTyped][] repository in development, you would run following command:
|
||||
|
||||
```
|
||||
npm install --save-dev --save-exact @types/leaflet
|
||||
```
|
||||
|
||||
Then you would import the JS and CSS files specified in library's installation instructions so that [Webpack][] knows about them:
|
||||
Edit [src/main/webapp/app/app.module.ts](src/main/webapp/app/app.module.ts) file:
|
||||
|
||||
```
|
||||
import 'leaflet/dist/leaflet.js';
|
||||
```
|
||||
|
||||
Edit [src/main/webapp/content/scss/vendor.scss](src/main/webapp/content/scss/vendor.scss) file:
|
||||
|
||||
```
|
||||
@import '~leaflet/dist/leaflet.css';
|
||||
```
|
||||
|
||||
Note: There are still a few other things remaining to do for Leaflet that we won't detail here.
|
||||
|
||||
For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][].
|
||||
|
||||
### Using Angular CLI
|
||||
|
||||
You can also use [Angular CLI][] to generate some custom client code.
|
||||
|
||||
For example, the following command:
|
||||
|
||||
```
|
||||
ng generate component my-component
|
||||
```
|
||||
|
||||
will generate few files:
|
||||
|
||||
```
|
||||
create src/main/webapp/app/my-component/my-component.component.html
|
||||
create src/main/webapp/app/my-component/my-component.component.ts
|
||||
update src/main/webapp/app/app.module.ts
|
||||
```
|
||||
|
||||
### JHipster Control Center
|
||||
|
||||
JHipster Control Center can help you manage and control your application(s). You can start a local control center server (accessible on http://localhost:7419) with:
|
||||
|
||||
```
|
||||
docker-compose -f src/main/docker/jhipster-control-center.yml up
|
||||
```
|
||||
|
||||
### OAuth 2.0 / OpenID Connect
|
||||
|
||||
Congratulations! You've selected an excellent way to secure your JHipster application. If you're not sure what OAuth and OpenID Connect (OIDC) are, please see [What the Heck is OAuth?](https://developer.okta.com/blog/2017/06/21/what-the-heck-is-oauth)
|
||||
|
||||
To log in to your app, you'll need to have [Keycloak](https://keycloak.org) up and running. The JHipster Team has created a Docker container for you that has the default users and roles. Start Keycloak using the following command.
|
||||
|
||||
```
|
||||
docker-compose -f src/main/docker/keycloak.yml up
|
||||
```
|
||||
|
||||
The security settings in `src/main/resources/config/application.yml` are configured for this image.
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
...
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
provider:
|
||||
oidc:
|
||||
issuer-uri: http://localhost:9080/realms/jhipster
|
||||
registration:
|
||||
oidc:
|
||||
client-id: web_app
|
||||
client-secret: web_app
|
||||
scope: openid,profile,email
|
||||
```
|
||||
|
||||
Some of Keycloak configuration is now done in build time and the other part before running the app, here is the [list](https://www.keycloak.org/server/all-config) of all build and configuration options.
|
||||
|
||||
Before moving to production, please make sure to follow this [guide](https://www.keycloak.org/server/configuration) for better security and performance.
|
||||
|
||||
Also, you should never use `start-dev` nor `KC_DB=dev-file` in production.
|
||||
|
||||
When using Kubernetes, importing should be done using init-containers (with a volume when using `db=dev-file`).
|
||||
|
||||
### Okta
|
||||
|
||||
If you'd like to use Okta instead of Keycloak, it's pretty quick using the [Okta CLI](https://cli.okta.com/). After you've installed it, run:
|
||||
|
||||
```shell
|
||||
okta register
|
||||
```
|
||||
|
||||
Then, in your JHipster app's directory, run `okta apps create` and select **JHipster**. This will set up an Okta app for you, create `ROLE_ADMIN` and `ROLE_USER` groups, create a `.okta.env` file with your Okta settings, and configure a `groups` claim in your ID token.
|
||||
|
||||
Run `source .okta.env` and start your app with Maven or Gradle. You should be able to sign in with the credentials you registered with.
|
||||
|
||||
If you're on Windows, you should install [WSL](https://docs.microsoft.com/en-us/windows/wsl/install-win10) so the `source` command will work.
|
||||
|
||||
If you'd like to configure things manually through the Okta developer console, see the instructions below.
|
||||
|
||||
First, you'll need to create a free developer account at <https://developer.okta.com/signup/>. After doing so, you'll get your own Okta domain, that has a name like `https://dev-123456.okta.com`.
|
||||
|
||||
Modify `src/main/resources/config/application.yml` to use your Okta settings.
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
...
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
provider:
|
||||
oidc:
|
||||
issuer-uri: https://{yourOktaDomain}/oauth2/default
|
||||
registration:
|
||||
oidc:
|
||||
client-id: {clientId}
|
||||
client-secret: {clientSecret}
|
||||
security:
|
||||
```
|
||||
|
||||
Create an OIDC App in Okta to get a `{clientId}` and `{clientSecret}`. To do this, log in to your Okta Developer account and navigate to **Applications** > **Add Application**. Click **Web** and click the **Next** button. Give the app a name you’ll remember, specify `http://localhost:8080` as a Base URI, and `http://localhost:8080/login/oauth2/code/oidc` as a Login Redirect URI. Click **Done**, then Edit and add `http://localhost:8080` as a Logout redirect URI. Copy and paste the client ID and secret into your `application.yml` file.
|
||||
|
||||
Create a `ROLE_ADMIN` and `ROLE_USER` group and add users into them. Modify e2e tests to use this account when running integration tests. You'll need to change credentials in `src/test/javascript/e2e/account/account.spec.ts` and `src/test/javascript/e2e/admin/administration.spec.ts`.
|
||||
|
||||
Navigate to **API** > **Authorization Servers**, click the **Authorization Servers** tab and edit the default one. Click the **Claims** tab and **Add Claim**. Name it "groups", and include it in the ID Token. Set the value type to "Groups" and set the filter to be a Regex of `.*`.
|
||||
|
||||
After making these changes, you should be good to go! If you have any issues, please post them to [Stack Overflow](https://stackoverflow.com/questions/tagged/jhipster). Make sure to tag your question with "jhipster" and "okta".
|
||||
|
||||
### Auth0
|
||||
|
||||
If you'd like to use [Auth0](https://auth0.com/) instead of Keycloak, follow the configuration steps below:
|
||||
|
||||
- Create a free developer account at <https://auth0.com/signup>. After successful sign-up, your account will be associated with a unique domain like `dev-xxx.us.auth0.com`
|
||||
- Create a new application of type `Regular Web Applications`. Switch to the `Settings` tab, and configure your application settings like:
|
||||
- Allowed Callback URLs: `http://localhost:8080/login/oauth2/code/oidc`
|
||||
- Allowed Logout URLs: `http://localhost:8080/`
|
||||
- Navigate to **User Management** > **Roles** and create new roles named `ROLE_ADMIN`, and `ROLE_USER`.
|
||||
- Navigate to **User Management** > **Users** and create a new user account. Click on the **Role** tab to assign roles to the newly created user account.
|
||||
- Navigate to **Auth Pipeline** > **Rules** and create a new Rule. Choose `Empty rule` template. Provide a meaningful name like `JHipster claims` and replace `Script` content with the following and Save.
|
||||
|
||||
```javascript
|
||||
function (user, context, callback) {
|
||||
user.preferred_username = user.email;
|
||||
const roles = (context.authorization || {}).roles;
|
||||
|
||||
function prepareCustomClaimKey(claim) {
|
||||
return `https://www.jhipster.tech/${claim}`;
|
||||
}
|
||||
|
||||
const rolesClaim = prepareCustomClaimKey('roles');
|
||||
|
||||
if (context.idToken) {
|
||||
context.idToken[rolesClaim] = roles;
|
||||
}
|
||||
|
||||
if (context.accessToken) {
|
||||
context.accessToken[rolesClaim] = roles;
|
||||
}
|
||||
|
||||
callback(null, user, context);
|
||||
}
|
||||
```
|
||||
|
||||
- In your `JHipster` application, modify `src/main/resources/config/application.yml` to use your Auth0 application settings:
|
||||
|
||||
```yaml
|
||||
spring:
|
||||
...
|
||||
security:
|
||||
oauth2:
|
||||
client:
|
||||
provider:
|
||||
oidc:
|
||||
# make sure to include the ending slash!
|
||||
issuer-uri: https://{your-auth0-domain}/
|
||||
registration:
|
||||
oidc:
|
||||
client-id: {clientId}
|
||||
client-secret: {clientSecret}
|
||||
scope: openid,profile,email
|
||||
jhipster:
|
||||
...
|
||||
security:
|
||||
oauth2:
|
||||
audience:
|
||||
- https://{your-auth0-domain}/api/v2/
|
||||
```
|
||||
|
||||
### Doing API-First development using openapi-generator-cli
|
||||
|
||||
[OpenAPI-Generator]() is configured for this application. You can generate API code from the `src/main/resources/swagger/api.yml` definition file by running:
|
||||
|
||||
```bash
|
||||
./mvnw generate-sources
|
||||
```
|
||||
|
||||
Then implements the generated delegate classes with `@Service` classes.
|
||||
|
||||
To edit the `api.yml` definition file, you can use a tool such as [Swagger-Editor](). Start a local instance of the swagger-editor using docker by running: `docker-compose -f src/main/docker/swagger-editor.yml up -d`. The editor will then be reachable at [http://localhost:7742](http://localhost:7742).
|
||||
|
||||
Refer to [Doing API-First development][] for more details.
|
||||
|
||||
## Building for production
|
||||
|
||||
### Packaging as jar
|
||||
|
||||
To build the final jar and optimize the informationsystemmonitor application for production, run:
|
||||
|
||||
```
|
||||
./mvnw -Pprod clean verify
|
||||
```
|
||||
|
||||
This will concatenate and minify the client CSS and JavaScript files. It will also modify `index.html` so it references these new files.
|
||||
To ensure everything worked, run:
|
||||
|
||||
```
|
||||
java -jar target/*.jar
|
||||
```
|
||||
|
||||
Then navigate to [http://localhost:8080](http://localhost:8080) in your browser.
|
||||
|
||||
Refer to [Using JHipster in production][] for more details.
|
||||
|
||||
### Packaging as war
|
||||
|
||||
To package your application as a war in order to deploy it to an application server, run:
|
||||
|
||||
```
|
||||
./mvnw -Pprod,war clean verify
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
To launch your application's tests, run:
|
||||
|
||||
```
|
||||
./mvnw verify
|
||||
```
|
||||
|
||||
### Client tests
|
||||
|
||||
Unit tests are run by [Jest][]. They're located in [src/test/javascript/](src/test/javascript/) and can be run with:
|
||||
|
||||
```
|
||||
npm test
|
||||
```
|
||||
|
||||
For more information, refer to the [Running tests page][].
|
||||
|
||||
### Code quality
|
||||
|
||||
Sonar is used to analyse code quality. You can start a local Sonar server (accessible on http://localhost:9001) with:
|
||||
|
||||
```
|
||||
docker-compose -f src/main/docker/sonar.yml up -d
|
||||
```
|
||||
|
||||
Note: we have turned off authentication in [src/main/docker/sonar.yml](src/main/docker/sonar.yml) for out of the box experience while trying out SonarQube, for real use cases turn it back on.
|
||||
|
||||
You can run a Sonar analysis with using the [sonar-scanner](https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) or by using the maven plugin.
|
||||
|
||||
Then, run a Sonar analysis:
|
||||
|
||||
```
|
||||
./mvnw -Pprod clean verify sonar:sonar
|
||||
```
|
||||
|
||||
If you need to re-run the Sonar phase, please be sure to specify at least the `initialize` phase since Sonar properties are loaded from the sonar-project.properties file.
|
||||
|
||||
```
|
||||
./mvnw initialize sonar:sonar
|
||||
```
|
||||
|
||||
For more information, refer to the [Code quality page][].
|
||||
|
||||
## Using Docker to simplify development (optional)
|
||||
|
||||
You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
|
||||
|
||||
You can also fully dockerize your application and all the services that it depends on.
|
||||
To achieve this, first build a docker image of your app by running:
|
||||
|
||||
```
|
||||
npm run java:docker
|
||||
```
|
||||
|
||||
Or build a arm64 docker image when using an arm64 processor os like MacOS with M1 processor family running:
|
||||
|
||||
```
|
||||
npm run java:docker:arm64
|
||||
```
|
||||
|
||||
Then run:
|
||||
|
||||
```
|
||||
docker-compose -f src/main/docker/app.yml up -d
|
||||
```
|
||||
|
||||
When running Docker Desktop on MacOS Big Sur or later, consider enabling experimental `Use the new Virtualization framework` for better processing performance ([disk access performance is worse](https://github.com/docker/roadmap/issues/7)).
|
||||
|
||||
For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`jhipster docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
|
||||
|
||||
## Continuous Integration (optional)
|
||||
|
||||
To configure CI for your project, run the ci-cd sub-generator (`jhipster ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information.
|
||||
|
||||
[jhipster homepage and latest documentation]: https://www.jhipster.tech
|
||||
[jhipster 7.9.3 archive]: https://www.jhipster.tech/documentation-archive/v7.9.3
|
||||
[using jhipster in development]: https://www.jhipster.tech/documentation-archive/v7.9.3/development/
|
||||
[using docker and docker-compose]: https://www.jhipster.tech/documentation-archive/v7.9.3/docker-compose
|
||||
[using jhipster in production]: https://www.jhipster.tech/documentation-archive/v7.9.3/production/
|
||||
[running tests page]: https://www.jhipster.tech/documentation-archive/v7.9.3/running-tests/
|
||||
[code quality page]: https://www.jhipster.tech/documentation-archive/v7.9.3/code-quality/
|
||||
[setting up continuous integration]: https://www.jhipster.tech/documentation-archive/v7.9.3/setting-up-ci/
|
||||
[node.js]: https://nodejs.org/
|
||||
[npm]: https://www.npmjs.com/
|
||||
[webpack]: https://webpack.github.io/
|
||||
[browsersync]: https://www.browsersync.io/
|
||||
[jest]: https://facebook.github.io/jest/
|
||||
[leaflet]: https://leafletjs.com/
|
||||
[definitelytyped]: https://definitelytyped.org/
|
||||
[angular cli]: https://cli.angular.io/
|
||||
[openapi-generator]: https://openapi-generator.tech
|
||||
[swagger-editor]: https://editor.swagger.io
|
||||
[doing api-first development]: https://www.jhipster.tech/documentation-archive/v7.9.3/doing-api-first-development/
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"informationsystemmonitor": {
|
||||
"projectType": "application",
|
||||
"schematics": {
|
||||
"@schematics/angular:component": {
|
||||
"style": "scss"
|
||||
},
|
||||
"@schematics/angular:application": {
|
||||
"strict": true
|
||||
}
|
||||
},
|
||||
"root": "",
|
||||
"sourceRoot": "src/main/webapp",
|
||||
"prefix": "jhi",
|
||||
"architect": {
|
||||
"build": {
|
||||
"builder": "@angular-builders/custom-webpack:browser",
|
||||
"options": {
|
||||
"customWebpackConfig": {
|
||||
"path": "./webpack/webpack.custom.js"
|
||||
},
|
||||
"outputPath": "target/classes/static/",
|
||||
"index": "src/main/webapp/index.html",
|
||||
"main": "src/main/webapp/main.ts",
|
||||
"polyfills": "src/main/webapp/polyfills.ts",
|
||||
"tsConfig": "tsconfig.app.json",
|
||||
"inlineStyleLanguage": "scss",
|
||||
"assets": [
|
||||
"src/main/webapp/content",
|
||||
"src/main/webapp/favicon.ico",
|
||||
"src/main/webapp/manifest.webapp",
|
||||
"src/main/webapp/robots.txt"
|
||||
],
|
||||
"styles": ["src/main/webapp/content/scss/vendor.scss", "src/main/webapp/content/scss/global.scss"],
|
||||
"scripts": []
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"optimization": true,
|
||||
"outputHashing": "all",
|
||||
"sourceMap": false,
|
||||
"namedChunks": false,
|
||||
"extractLicenses": true,
|
||||
"vendorChunk": false,
|
||||
"buildOptimizer": true,
|
||||
"serviceWorker": true,
|
||||
"ngswConfigPath": "ngsw-config.json",
|
||||
"budgets": [
|
||||
{
|
||||
"type": "initial",
|
||||
"maximumWarning": "500kb",
|
||||
"maximumError": "1mb"
|
||||
},
|
||||
{
|
||||
"type": "anyComponentStyle",
|
||||
"maximumWarning": "2kb",
|
||||
"maximumError": "4kb"
|
||||
}
|
||||
]
|
||||
},
|
||||
"development": {
|
||||
"buildOptimizer": false,
|
||||
"optimization": false,
|
||||
"vendorChunk": true,
|
||||
"extractLicenses": false,
|
||||
"sourceMap": true,
|
||||
"namedChunks": true
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "production"
|
||||
},
|
||||
"serve": {
|
||||
"builder": "@angular-builders/custom-webpack:dev-server",
|
||||
"options": {
|
||||
"browserTarget": "informationsystemmonitor:build:development",
|
||||
"port": 4200
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "informationsystemmonitor:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "informationsystemmonitor:build:development"
|
||||
}
|
||||
},
|
||||
"defaultConfiguration": "development"
|
||||
},
|
||||
"test": {
|
||||
"builder": "@angular-builders/jest:run",
|
||||
"options": {
|
||||
"configPath": "jest.conf.js"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cli": {
|
||||
"cache": {
|
||||
"enabled": true,
|
||||
"path": "./target/angular/",
|
||||
"environment": "all"
|
||||
},
|
||||
"packageManager": "npm"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"https://checkstyle.org/dtds/configuration_1_3.dtd">
|
||||
<module name="Checker">
|
||||
|
||||
<!-- Configure checker to use UTF-8 encoding -->
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<!-- Configure checker to run on files with these extensions -->
|
||||
<property name="fileExtensions" value=""/>
|
||||
<!-- For detailed checkstyle configuration, see https://github.com/spring-io/nohttp/tree/master/nohttp-checkstyle -->
|
||||
<module name="io.spring.nohttp.checkstyle.check.NoHttpCheck">
|
||||
<property name="allowlist" value="^\Qhttp://maven.apache.org/POM/4.0.0 ^\Qhttp://www.w3.org/2001/XMLSchema-instance"/>
|
||||
</module>
|
||||
<!-- Allow suppression with comments
|
||||
// CHECKSTYLE:OFF
|
||||
... ignored content ...
|
||||
// CHECKSTYLE:ON
|
||||
-->
|
||||
<module name="SuppressWithPlainTextCommentFilter"/>
|
||||
</module>
|
|
@ -0,0 +1,29 @@
|
|||
const { pathsToModuleNameMapper } = require('ts-jest');
|
||||
|
||||
const {
|
||||
compilerOptions: { paths = {}, baseUrl = './' },
|
||||
} = require('./tsconfig.json');
|
||||
const environment = require('./webpack/environment');
|
||||
|
||||
module.exports = {
|
||||
transformIgnorePatterns: ['node_modules/(?!.*\\.mjs$|dayjs/esm)'],
|
||||
resolver: 'jest-preset-angular/build/resolvers/ng-jest-resolver.js',
|
||||
globals: {
|
||||
...environment,
|
||||
},
|
||||
roots: ['<rootDir>', `<rootDir>/${baseUrl}`],
|
||||
modulePaths: [`<rootDir>/${baseUrl}`],
|
||||
setupFiles: ['jest-date-mock'],
|
||||
cacheDirectory: '<rootDir>/target/jest-cache',
|
||||
coverageDirectory: '<rootDir>/target/test-results/',
|
||||
moduleNameMapper: pathsToModuleNameMapper(paths, { prefix: `<rootDir>/${baseUrl}/` }),
|
||||
reporters: [
|
||||
'default',
|
||||
['jest-junit', { outputDirectory: '<rootDir>/target/test-results/', outputName: 'TESTS-results-jest.xml' }],
|
||||
['jest-sonar', { outputDirectory: './target/test-results/jest', outputName: 'TESTS-results-sonar.xml' }],
|
||||
],
|
||||
testMatch: ['<rootDir>/src/main/webapp/app/**/@(*.)@(spec.ts)'],
|
||||
testEnvironmentOptions: {
|
||||
url: 'https://jhipster.tech',
|
||||
},
|
||||
};
|
|
@ -0,0 +1,316 @@
|
|||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# 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.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||
. /usr/local/etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -0,0 +1,188 @@
|
|||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM http://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% ^
|
||||
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||
%MAVEN_OPTS% ^
|
||||
%MAVEN_DEBUG_OPTS% ^
|
||||
-classpath %WRAPPER_JAR% ^
|
||||
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||
|
||||
cmd /C exit /B %ERROR_CODE%
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/service-worker/config/schema.json",
|
||||
"index": "/index.html",
|
||||
"assetGroups": [
|
||||
{
|
||||
"name": "app",
|
||||
"installMode": "prefetch",
|
||||
"resources": {
|
||||
"files": ["/favicon.ico", "/index.html", "/manifest.webapp", "/*.css", "/*.js"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "assets",
|
||||
"installMode": "lazy",
|
||||
"updateMode": "prefetch",
|
||||
"resources": {
|
||||
"files": ["/content/**", "/*.(eot|svg|cur|jpg|png|webp|gif|otf|ttf|woff|woff2|ani)"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/sh
|
||||
|
||||
basedir=`dirname "$0"`
|
||||
|
||||
if [ -f "$basedir/mvnw" ]; then
|
||||
bindir="$basedir/target/node"
|
||||
repodir="$basedir/target/node/node_modules"
|
||||
installCommand="$basedir/mvnw -Pwebapp frontend:install-node-and-npm@install-node-and-npm"
|
||||
|
||||
PATH="$basedir/$builddir/:$PATH"
|
||||
NPM_EXE="$basedir/$builddir/node_modules/npm/bin/npm-cli.js"
|
||||
NODE_EXE="$basedir/$builddir/node"
|
||||
elif [ -f "$basedir/gradlew" ]; then
|
||||
bindir="$basedir/build/node/bin"
|
||||
repodir="$basedir/build/node/lib/node_modules"
|
||||
installCommand="$basedir/gradlew npmSetup"
|
||||
else
|
||||
echo "Using npm installed globally"
|
||||
exec npm "$@"
|
||||
fi
|
||||
|
||||
NPM_EXE="$repodir/npm/bin/npm-cli.js"
|
||||
NODE_EXE="$bindir/node"
|
||||
|
||||
if [ ! -x "$NPM_EXE" ] || [ ! -x "$NODE_EXE" ]; then
|
||||
$installCommand || true
|
||||
fi
|
||||
|
||||
if [ -x "$NODE_EXE" ]; then
|
||||
echo "Using node installed locally $($NODE_EXE --version)"
|
||||
PATH="$bindir:$PATH"
|
||||
else
|
||||
NODE_EXE='node'
|
||||
fi
|
||||
|
||||
if [ ! -x "$NPM_EXE" ]; then
|
||||
echo "Local npm not found, using npm installed globally"
|
||||
npm "$@"
|
||||
else
|
||||
echo "Using npm installed locally $($NODE_EXE $NPM_EXE --version)"
|
||||
$NODE_EXE $NPM_EXE "$@"
|
||||
fi
|
|
@ -0,0 +1,31 @@
|
|||
@echo off
|
||||
|
||||
setlocal
|
||||
|
||||
set NPMW_DIR=%~dp0
|
||||
|
||||
if exist "%NPMW_DIR%mvnw.cmd" (
|
||||
set NODE_EXE=^"^"
|
||||
set NODE_PATH=%NPMW_DIR%target\node\
|
||||
set NPM_EXE=^"%NPMW_DIR%target\node\npm.cmd^"
|
||||
set INSTALL_NPM_COMMAND=^"%NPMW_DIR%mvnw.cmd^" -Pwebapp frontend:install-node-and-npm@install-node-and-npm
|
||||
) else (
|
||||
set NODE_EXE=^"%NPMW_DIR%build\node\bin\node.exe^"
|
||||
set NODE_PATH=%NPMW_DIR%build\node\bin\
|
||||
set NPM_EXE=^"%NPMW_DIR%build\node\lib\node_modules\npm\bin\npm-cli.js^"
|
||||
set INSTALL_NPM_COMMAND=^"%NPMW_DIR%gradlew.bat^" npmSetup
|
||||
)
|
||||
|
||||
if not exist %NPM_EXE% (
|
||||
call %INSTALL_NPM_COMMAND%
|
||||
)
|
||||
|
||||
if exist %NODE_EXE% (
|
||||
Rem execute local npm with local node, whilst adding local node location to the PATH for this CMD session
|
||||
endlocal & echo "%PATH%"|find /i "%NODE_PATH%;">nul || set "PATH=%NODE_PATH%;%PATH%" & call %NODE_EXE% %NPM_EXE% %*
|
||||
) else if exist %NPM_EXE% (
|
||||
Rem execute local npm, whilst adding local npm location to the PATH for this CMD session
|
||||
endlocal & echo "%PATH%"|find /i "%NODE_PATH%;">nul || set "PATH=%NODE_PATH%;%PATH%" & call %NPM_EXE% %*
|
||||
) else (
|
||||
call npm %*
|
||||
)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,150 @@
|
|||
{
|
||||
"name": "informationsystemmonitor",
|
||||
"version": "0.0.1-SNAPSHOT",
|
||||
"private": true,
|
||||
"description": "Description for informationsystemmonitor",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"app:start": "./mvnw",
|
||||
"backend:build-cache": "./mvnw dependency:go-offline",
|
||||
"backend:debug": "./mvnw -Dspring-boot.run.jvmArguments=\"-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000\"",
|
||||
"backend:doc:test": "./mvnw -ntp javadoc:javadoc --batch-mode",
|
||||
"backend:info": "./mvnw -ntp enforcer:display-info --batch-mode",
|
||||
"backend:nohttp:test": "./mvnw -ntp checkstyle:check --batch-mode",
|
||||
"backend:start": "./mvnw -Dskip.installnodenpm -Dskip.npm",
|
||||
"backend:unit:test": "./mvnw -ntp -Dskip.installnodenpm -Dskip.npm verify --batch-mode -Dlogging.level.ROOT=OFF -Dlogging.level.org.zalando=OFF -Dlogging.level.tech.jhipster=OFF -Dlogging.level.org.gcube.fullstackapps.informationsystemmonitor=OFF -Dlogging.level.org.springframework=OFF -Dlogging.level.org.springframework.web=OFF -Dlogging.level.org.springframework.security=OFF",
|
||||
"build": "npm run webapp:prod --",
|
||||
"build-watch": "concurrently 'npm run webapp:build:dev -- --watch' npm:backend:start",
|
||||
"ci:backend:test": "npm run backend:info && npm run backend:doc:test && npm run backend:nohttp:test && npm run backend:unit:test -- -P$npm_package_config_default_environment",
|
||||
"ci:e2e:package": "npm run java:$npm_package_config_packaging:$npm_package_config_default_environment -- -Pe2e -Denforcer.skip=true",
|
||||
"ci:e2e:prepare": "npm run ci:e2e:prepare:docker",
|
||||
"ci:e2e:prepare:docker": "npm run docker:db:up && npm run docker:others:up && docker ps -a",
|
||||
"preci:e2e:server:start": "npm run docker:db:await --if-present && npm run docker:others:await --if-present",
|
||||
"ci:e2e:server:start": "java -jar target/e2e.$npm_package_config_packaging --spring.profiles.active=e2e,$npm_package_config_default_environment -Dlogging.level.ROOT=OFF -Dlogging.level.org.zalando=OFF -Dlogging.level.tech.jhipster=OFF -Dlogging.level.org.gcube.fullstackapps.informationsystemmonitor=OFF -Dlogging.level.org.springframework=OFF -Dlogging.level.org.springframework.web=OFF -Dlogging.level.org.springframework.security=OFF --logging.level.org.springframework.web=ERROR",
|
||||
"ci:e2e:teardown": "npm run ci:e2e:teardown:docker",
|
||||
"ci:e2e:teardown:docker": "npm run docker:db:down --if-present && npm run docker:others:down && docker ps -a",
|
||||
"ci:frontend:build": "npm run webapp:build:$npm_package_config_default_environment",
|
||||
"ci:frontend:test": "npm run ci:frontend:build && npm test",
|
||||
"clean-www": "rimraf target/classes/static/app/{src,target/}",
|
||||
"cleanup": "rimraf target/classes/static/",
|
||||
"docker:app:up": "docker-compose -f src/main/docker/app.yml up -d",
|
||||
"docker:db:up": "echo \"Docker for db no not configured for application informationsystemmonitor\"",
|
||||
"docker:keycloak:await": "echo \"Waiting for keycloak to start\" && wait-on -t 180000 http-get://localhost:9080/realms/jhipster && echo \"keycloak started\" || echo \"keycloak not running, make sure oauth2 server is running\"",
|
||||
"docker:keycloak:down": "docker-compose -f src/main/docker/keycloak.yml down -v",
|
||||
"docker:keycloak:up": "docker-compose -f src/main/docker/keycloak.yml up -d",
|
||||
"docker:others:await": "npm run docker:keycloak:await",
|
||||
"docker:others:down": "npm run docker:keycloak:down",
|
||||
"predocker:others:up": "",
|
||||
"docker:others:up": "npm run docker:keycloak:up",
|
||||
"java:docker": "./mvnw -ntp verify -DskipTests -Pprod jib:dockerBuild",
|
||||
"java:docker:arm64": "npm run java:docker -- -Djib-maven-plugin.architecture=arm64",
|
||||
"java:docker:dev": "npm run java:docker -- -Pdev,webapp",
|
||||
"java:docker:prod": "npm run java:docker -- -Pprod",
|
||||
"java:jar": "./mvnw -ntp verify -DskipTests --batch-mode",
|
||||
"java:jar:dev": "npm run java:jar -- -Pdev,webapp",
|
||||
"java:jar:prod": "npm run java:jar -- -Pprod",
|
||||
"java:war": "./mvnw -ntp verify -DskipTests --batch-mode -Pwar",
|
||||
"java:war:dev": "npm run java:war -- -Pdev,webapp",
|
||||
"java:war:prod": "npm run java:war -- -Pprod",
|
||||
"jest": "jest --coverage --logHeapUsage --maxWorkers=2 --config jest.conf.js",
|
||||
"lint": "eslint . --ext .js,.ts",
|
||||
"lint:fix": "npm run lint -- --fix",
|
||||
"prettier:check": "prettier --check \"{,src/**/,webpack/,.blueprint/**/}*.{md,json,yml,html,cjs,mjs,js,ts,tsx,css,scss,java}\"",
|
||||
"prettier:format": "prettier --write \"{,src/**/,webpack/,.blueprint/**/}*.{md,json,yml,html,cjs,mjs,js,ts,tsx,css,scss,java}\"",
|
||||
"serve": "npm run start --",
|
||||
"start": "ng serve --hmr",
|
||||
"start-tls": "npm run webapp:dev-ssl",
|
||||
"pretest": "npm run lint",
|
||||
"test": "ng test --coverage --log-heap-usage -w=2",
|
||||
"test:watch": "npm run test -- --watch",
|
||||
"watch": "concurrently npm:start npm:backend:start",
|
||||
"webapp:build": "npm run clean-www && npm run webapp:build:dev",
|
||||
"webapp:build:dev": "ng build --configuration development",
|
||||
"webapp:build:prod": "ng build --configuration production",
|
||||
"webapp:dev": "ng serve",
|
||||
"webapp:dev-ssl": "ng serve --ssl",
|
||||
"webapp:dev-verbose": "ng serve --verbose",
|
||||
"webapp:prod": "npm run clean-www && npm run webapp:build:prod",
|
||||
"webapp:test": "npm run test --"
|
||||
},
|
||||
"config": {
|
||||
"backend_port": "8080",
|
||||
"default_environment": "prod",
|
||||
"packaging": "jar"
|
||||
},
|
||||
"dependencies": {
|
||||
"@angular/common": "14.2.0",
|
||||
"@angular/compiler": "14.2.0",
|
||||
"@angular/core": "14.2.0",
|
||||
"@angular/forms": "14.2.0",
|
||||
"@angular/localize": "14.2.0",
|
||||
"@angular/platform-browser": "14.2.0",
|
||||
"@angular/platform-browser-dynamic": "14.2.0",
|
||||
"@angular/router": "14.2.0",
|
||||
"@fortawesome/angular-fontawesome": "0.11.1",
|
||||
"@fortawesome/fontawesome-svg-core": "6.2.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.2.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "13.0.0",
|
||||
"@ngx-translate/core": "14.0.0",
|
||||
"@ngx-translate/http-loader": "7.0.0",
|
||||
"@popperjs/core": "2.11.6",
|
||||
"bootstrap": "5.2.0",
|
||||
"cytoscape": "3.25.0",
|
||||
"dayjs": "1.11.5",
|
||||
"ngx-infinite-scroll": "14.0.0",
|
||||
"ngx-webstorage": "10.0.1",
|
||||
"rxjs": "7.5.6",
|
||||
"tslib": "2.4.0",
|
||||
"zone.js": "0.11.6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "14.0.1",
|
||||
"@angular-builders/jest": "14.0.1",
|
||||
"@angular-devkit/build-angular": "14.2.1",
|
||||
"@angular-eslint/eslint-plugin": "14.0.3",
|
||||
"@angular/cli": "14.2.1",
|
||||
"@angular/compiler-cli": "14.2.0",
|
||||
"@angular/service-worker": "14.2.0",
|
||||
"@types/cytoscape": "3.19.10",
|
||||
"@types/jest": "28.1.8",
|
||||
"@types/node": "16.11.56",
|
||||
"@typescript-eslint/eslint-plugin": "5.36.1",
|
||||
"@typescript-eslint/parser": "5.36.1",
|
||||
"browser-sync": "2.27.10",
|
||||
"browser-sync-webpack-plugin": "2.3.0",
|
||||
"concurrently": "7.3.0",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"eslint": "8.23.0",
|
||||
"eslint-config-prettier": "8.5.0",
|
||||
"eslint-webpack-plugin": "3.2.0",
|
||||
"folder-hash": "4.0.2",
|
||||
"generator-jhipster": "7.9.3",
|
||||
"jest": "28.1.3",
|
||||
"jest-date-mock": "1.0.8",
|
||||
"jest-environment-jsdom": "28.1.3",
|
||||
"jest-junit": "14.0.1",
|
||||
"jest-preset-angular": "12.2.2",
|
||||
"jest-sonar": "0.2.12",
|
||||
"merge-jsons-webpack-plugin": "2.0.1",
|
||||
"prettier": "2.7.1",
|
||||
"prettier-plugin-java": "1.6.2",
|
||||
"prettier-plugin-packagejson": "2.2.18",
|
||||
"rimraf": "3.0.2",
|
||||
"swagger-ui-dist": "4.14.0",
|
||||
"ts-jest": "28.0.8",
|
||||
"typescript": "4.8.2",
|
||||
"wait-on": "6.0.1",
|
||||
"webpack-bundle-analyzer": "4.6.1",
|
||||
"webpack-merge": "5.8.0",
|
||||
"webpack-notifier": "1.15.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16.17.0"
|
||||
},
|
||||
"cacheDirectories": [
|
||||
"node_modules"
|
||||
],
|
||||
"overrides": {
|
||||
"webpack": "5.74.0"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
sonar.projectKey=informationsystemmonitor
|
||||
sonar.projectName=informationsystemmonitor generated by jhipster
|
||||
|
||||
# Typescript tests files must be inside sources and tests, othewise `INFO: Test execution data ignored for 80 unknown files, including:` is shown.
|
||||
sonar.sources=src
|
||||
sonar.tests=src
|
||||
sonar.host.url=http://localhost:9001
|
||||
|
||||
sonar.test.inclusions=src/test/**/*.*, src/main/webapp/app/**/*.spec.ts
|
||||
sonar.coverage.jacoco.xmlReportPaths=target/site/**/jacoco*.xml
|
||||
sonar.java.codeCoveragePlugin=jacoco
|
||||
sonar.junit.reportPaths=target/surefire-reports,target/failsafe-reports
|
||||
sonar.testExecutionReportPaths=target/test-results/jest/TESTS-results-sonar.xml
|
||||
sonar.javascript.lcov.reportPaths=target/test-results/lcov.info
|
||||
|
||||
sonar.sourceEncoding=UTF-8
|
||||
sonar.exclusions=src/main/webapp/content/**/*.*, src/main/webapp/i18n/*.js, target/classes/static/**/*.*
|
||||
|
||||
sonar.issue.ignore.multicriteria=S3437,S4684,S5145,UndocumentedApi
|
||||
# Rule https://rules.sonarsource.com/java/RSPEC-3437 is ignored, as a JPA-managed field cannot be transient
|
||||
sonar.issue.ignore.multicriteria.S3437.resourceKey=src/main/java/**/*
|
||||
sonar.issue.ignore.multicriteria.S3437.ruleKey=squid:S3437
|
||||
# Rule https://rules.sonarsource.com/java/RSPEC-4684
|
||||
sonar.issue.ignore.multicriteria.S4684.resourceKey=src/main/java/**/*
|
||||
sonar.issue.ignore.multicriteria.S4684.ruleKey=java:S4684
|
||||
# Rule https://rules.sonarsource.com/java/RSPEC-5145 log filter is applied
|
||||
sonar.issue.ignore.multicriteria.S5145.resourceKey=src/main/java/**/*
|
||||
sonar.issue.ignore.multicriteria.S5145.ruleKey=javasecurity:S5145
|
||||
# Rule https://rules.sonarsource.com/java/RSPEC-1176 is ignored, as we want to follow "clean code" guidelines and classes, methods and arguments names should be self-explanatory
|
||||
sonar.issue.ignore.multicriteria.UndocumentedApi.resourceKey=src/main/java/**/*
|
||||
sonar.issue.ignore.multicriteria.UndocumentedApi.ruleKey=squid:UndocumentedApi
|
|
@ -0,0 +1,34 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
informationsystemmonitor-app:
|
||||
image: informationsystemmonitor
|
||||
environment:
|
||||
- _JAVA_OPTIONS=-Xmx512m -Xms256m
|
||||
- SPRING_PROFILES_ACTIVE=prod,api-docs
|
||||
- MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED=true
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER_URI=http://keycloak:9080/realms/jhipster
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_ID=web_app
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_SECRET=web_app
|
||||
- JHIPSTER_SLEEP=30 # gives time for other services to boot before the application
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:8080:8080
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:19.0.1
|
||||
command: ['start-dev --import-realm']
|
||||
volumes:
|
||||
- ./realm-config:/opt/keycloak/data/import
|
||||
environment:
|
||||
- KC_DB=dev-file
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=admin
|
||||
- KC_FEATURES=scripts
|
||||
- KC_HTTP_PORT=9080
|
||||
- KC_HTTPS_PORT=9443
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:9080:9080
|
||||
- 127.0.0.1:9443:9443
|
|
@ -0,0 +1 @@
|
|||
# Central configuration sources details
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,11 @@
|
|||
apiVersion: 1
|
||||
|
||||
providers:
|
||||
- name: 'Prometheus'
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
disableDeletion: false
|
||||
editable: true
|
||||
options:
|
||||
path: /etc/grafana/provisioning/dashboards
|
|
@ -0,0 +1,50 @@
|
|||
apiVersion: 1
|
||||
|
||||
# list of datasources that should be deleted from the database
|
||||
deleteDatasources:
|
||||
- name: Prometheus
|
||||
orgId: 1
|
||||
|
||||
# list of datasources to insert/update depending
|
||||
# whats available in the database
|
||||
datasources:
|
||||
# <string, required> name of the datasource. Required
|
||||
- name: Prometheus
|
||||
# <string, required> datasource type. Required
|
||||
type: prometheus
|
||||
# <string, required> access mode. direct or proxy. Required
|
||||
access: proxy
|
||||
# <int> org id. will default to orgId 1 if not specified
|
||||
orgId: 1
|
||||
# <string> url
|
||||
# On MacOS, replace localhost by host.docker.internal
|
||||
url: http://localhost:9090
|
||||
# <string> database password, if used
|
||||
password:
|
||||
# <string> database user, if used
|
||||
user:
|
||||
# <string> database name, if used
|
||||
database:
|
||||
# <bool> enable/disable basic auth
|
||||
basicAuth: false
|
||||
# <string> basic auth username
|
||||
basicAuthUser: admin
|
||||
# <string> basic auth password
|
||||
basicAuthPassword: admin
|
||||
# <bool> enable/disable with credentials headers
|
||||
withCredentials:
|
||||
# <bool> mark as default datasource. Max one per org
|
||||
isDefault: true
|
||||
# <map> fields that will be converted to json and stored in json_data
|
||||
jsonData:
|
||||
graphiteVersion: '1.1'
|
||||
tlsAuth: false
|
||||
tlsAuthWithCACert: false
|
||||
# <string> json object of data that will be encrypted.
|
||||
secureJsonData:
|
||||
tlsCACert: '...'
|
||||
tlsClientCert: '...'
|
||||
tlsClientKey: '...'
|
||||
version: 1
|
||||
# <bool> allow users to edit datasources from the UI.
|
||||
editable: true
|
|
@ -0,0 +1,53 @@
|
|||
## How to use JHCC docker compose
|
||||
# To allow JHCC to reach JHipster application from a docker container note that we set the host as host.docker.internal
|
||||
# To reach the application from a browser, you need to add '127.0.0.1 host.docker.internal' to your hosts file.
|
||||
### Discovery mode
|
||||
# JHCC support 3 kinds of discovery mode: Consul, Eureka and static
|
||||
# In order to use one, please set SPRING_PROFILES_ACTIVE to one (and only one) of this values: consul,eureka,static
|
||||
### Discovery properties
|
||||
# According to the discovery mode choose as Spring profile, you have to set the right properties
|
||||
# please note that current properties are set to run JHCC with default values, personalize them if needed
|
||||
# and remove those from other modes. You can only have one mode active.
|
||||
#### Eureka
|
||||
# - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:admin@host.docker.internal:8761/eureka/
|
||||
#### Consul
|
||||
# - SPRING_CLOUD_CONSUL_HOST=host.docker.internal
|
||||
# - SPRING_CLOUD_CONSUL_PORT=8500
|
||||
#### Static
|
||||
# Add instances to "MyApp"
|
||||
# - SPRING_CLOUD_DISCOVERY_CLIENT_SIMPLE_INSTANCES_MYAPP_0_URI=http://host.docker.internal:8081
|
||||
# - SPRING_CLOUD_DISCOVERY_CLIENT_SIMPLE_INSTANCES_MYAPP_1_URI=http://host.docker.internal:8082
|
||||
# Or add a new application named MyNewApp
|
||||
# - SPRING_CLOUD_DISCOVERY_CLIENT_SIMPLE_INSTANCES_MYNEWAPP_0_URI=http://host.docker.internal:8080
|
||||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
|
||||
#### IMPORTANT
|
||||
# If you choose Consul or Eureka mode:
|
||||
# Do not forget to remove the prefix "127.0.0.1" in front of their port in order to expose them.
|
||||
# This is required because JHCC need to communicate with Consul or Eureka.
|
||||
# - In Consul mode, the ports are in the consul.yml file.
|
||||
# - In Eureka mode, the ports are in the jhipster-registry.yml file.
|
||||
|
||||
version: '3.8'
|
||||
services:
|
||||
jhipster-control-center:
|
||||
image: 'jhipster/jhipster-control-center:v0.5.0'
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
# Patch /etc/hosts to support resolving host.docker.internal to the internal IP address used by the host in all OSes
|
||||
- echo "`ip route | grep default | cut -d ' ' -f3` host.docker.internal" | tee -a /etc/hosts > /dev/null && java -jar /jhipster-control-center.jar
|
||||
environment:
|
||||
- _JAVA_OPTIONS=-Xmx512m -Xms256m
|
||||
- SPRING_PROFILES_ACTIVE=prod,api-docs,static,oauth2
|
||||
- JHIPSTER_SLEEP=30 # gives time for other services to boot before the application
|
||||
# For keycloak to work, you need to add '127.0.0.1 keycloak' to your hosts file
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_PROVIDER_OIDC_ISSUER_URI=http://keycloak:9080/realms/jhipster
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_ID=jhipster-control-center
|
||||
- SPRING_SECURITY_OAUTH2_CLIENT_REGISTRATION_OIDC_CLIENT_SECRET=jhipster-control-center
|
||||
- SPRING_CLOUD_DISCOVERY_CLIENT_SIMPLE_INSTANCES_INFORMATIONSYSTEMMONITOR_0_URI=http://host.docker.internal:8080
|
||||
- LOGGING_FILE_NAME=/tmp/jhipster-control-center.log
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:7419:7419
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP}
|
||||
|
||||
# usage: file_env VAR [DEFAULT]
|
||||
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
|
||||
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
|
||||
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
if [[ ${!var:-} && ${!fileVar:-} ]]; then
|
||||
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
local val="$def"
|
||||
if [[ ${!var:-} ]]; then
|
||||
val="${!var}"
|
||||
elif [[ ${!fileVar:-} ]]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
|
||||
if [[ -n $val ]]; then
|
||||
export "$var"="$val"
|
||||
fi
|
||||
|
||||
unset "$fileVar"
|
||||
}
|
||||
|
||||
file_env 'SPRING_DATASOURCE_URL'
|
||||
file_env 'SPRING_DATASOURCE_USERNAME'
|
||||
file_env 'SPRING_DATASOURCE_PASSWORD'
|
||||
file_env 'SPRING_LIQUIBASE_URL'
|
||||
file_env 'SPRING_LIQUIBASE_USER'
|
||||
file_env 'SPRING_LIQUIBASE_PASSWORD'
|
||||
file_env 'JHIPSTER_REGISTRY_PASSWORD'
|
||||
|
||||
exec java ${JAVA_OPTS} -noverify -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "org.gcube.fullstackapps.informationsystemmonitor.InformationsystemmonitorApp" "$@"
|
|
@ -0,0 +1,20 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
keycloak:
|
||||
image: quay.io/keycloak/keycloak:19.0.1
|
||||
command: ['start-dev --import-realm']
|
||||
volumes:
|
||||
- ./realm-config:/opt/keycloak/data/import
|
||||
environment:
|
||||
- KC_DB=dev-file
|
||||
- KEYCLOAK_ADMIN=admin
|
||||
- KEYCLOAK_ADMIN_PASSWORD=admin
|
||||
- KC_FEATURES=scripts
|
||||
- KC_HTTP_PORT=9080
|
||||
- KC_HTTPS_PORT=9443
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:9080:9080
|
||||
- 127.0.0.1:9443:9443
|
|
@ -0,0 +1,31 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
informationsystemmonitor-prometheus:
|
||||
image: prom/prometheus:v2.38.0
|
||||
volumes:
|
||||
- ./prometheus/:/etc/prometheus/
|
||||
command:
|
||||
- '--config.file=/etc/prometheus/prometheus.yml'
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:9090:9090
|
||||
# On MacOS, remove next line and replace localhost by host.docker.internal in prometheus/prometheus.yml and
|
||||
# grafana/provisioning/datasources/datasource.yml
|
||||
network_mode: 'host' # to test locally running service
|
||||
informationsystemmonitor-grafana:
|
||||
image: grafana/grafana:9.1.0
|
||||
volumes:
|
||||
- ./grafana/provisioning/:/etc/grafana/provisioning/
|
||||
environment:
|
||||
- GF_SECURITY_ADMIN_PASSWORD=admin
|
||||
- GF_USERS_ALLOW_SIGN_UP=false
|
||||
- GF_INSTALL_PLUGINS=grafana-piechart-panel
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:3000:3000
|
||||
# On MacOS, remove next line and replace localhost by host.docker.internal in prometheus/prometheus.yml and
|
||||
# grafana/provisioning/datasources/datasource.yml
|
||||
network_mode: 'host' # to test locally running service
|
|
@ -0,0 +1,31 @@
|
|||
# Sample global config for monitoring JHipster applications
|
||||
global:
|
||||
scrape_interval: 15s # By default, scrape targets every 15 seconds.
|
||||
evaluation_interval: 15s # By default, scrape targets every 15 seconds.
|
||||
# scrape_timeout is set to the global default (10s).
|
||||
|
||||
# Attach these labels to any time series or alerts when communicating with
|
||||
# external systems (federation, remote storage, Alertmanager).
|
||||
external_labels:
|
||||
monitor: 'jhipster'
|
||||
|
||||
# A scrape configuration containing exactly one endpoint to scrape:
|
||||
# Here it's Prometheus itself.
|
||||
scrape_configs:
|
||||
# The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
|
||||
- job_name: 'prometheus'
|
||||
|
||||
# Override the global default and scrape targets from this job every 5 seconds.
|
||||
scrape_interval: 5s
|
||||
|
||||
# scheme defaults to 'http' enable https in case your application is server via https
|
||||
#scheme: https
|
||||
# basic auth is not needed by default. See https://www.jhipster.tech/monitoring/#configuring-metrics-forwarding for details
|
||||
#basic_auth:
|
||||
# username: admin
|
||||
# password: admin
|
||||
metrics_path: /management/prometheus
|
||||
static_configs:
|
||||
- targets:
|
||||
# On MacOS, replace localhost by host.docker.internal
|
||||
- localhost:8080
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,13 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
informationsystemmonitor-sonar:
|
||||
image: sonarqube:9.6.0-community
|
||||
# Authentication is turned off for out of the box experience while trying out SonarQube
|
||||
# For real use cases delete sonar.forceAuthentication variable or set sonar.forceAuthentication=true
|
||||
environment:
|
||||
- sonar.forceAuthentication=false
|
||||
# If you want to expose these ports outside your dev PC,
|
||||
# remove the "127.0.0.1:" prefix
|
||||
ports:
|
||||
- 127.0.0.1:9001:9000
|
|
@ -0,0 +1,7 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
swagger-editor:
|
||||
image: swaggerapi/swagger-editor:latest
|
||||
ports:
|
||||
- 127.0.0.1:7742:8080
|
|
@ -0,0 +1,7 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
version: '3.8'
|
||||
services:
|
||||
zipkin:
|
||||
image: openzipkin/zipkin:2.23
|
||||
ports:
|
||||
- 127.0.0.1:9411:9411
|
|
@ -0,0 +1,19 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor;
|
||||
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
|
||||
import tech.jhipster.config.DefaultProfileUtil;
|
||||
|
||||
/**
|
||||
* This is a helper Java class that provides an alternative to creating a {@code web.xml}.
|
||||
* This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
|
||||
*/
|
||||
public class ApplicationWebXml extends SpringBootServletInitializer {
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
// set a default to use when no profile is configured.
|
||||
DefaultProfileUtil.addDefaultProfile(application.application());
|
||||
return application.sources(InformationsystemmonitorApp.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import javax.annotation.Generated;
|
||||
|
||||
@Generated(value = "JHipster", comments = "Generated by JHipster 7.9.3")
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface GeneratedByJHipster {
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import javax.annotation.PostConstruct;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.ApplicationProperties;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.CRLFLogConverter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.core.env.Environment;
|
||||
import tech.jhipster.config.DefaultProfileUtil;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableConfigurationProperties({ ApplicationProperties.class })
|
||||
public class InformationsystemmonitorApp {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InformationsystemmonitorApp.class);
|
||||
|
||||
private final Environment env;
|
||||
|
||||
public InformationsystemmonitorApp(Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes informationsystemmonitor.
|
||||
* <p>
|
||||
* Spring profiles can be configured with a program argument --spring.profiles.active=your-active-profile
|
||||
* <p>
|
||||
* You can find more information on how profiles work with JHipster on <a href="https://www.jhipster.tech/profiles/">https://www.jhipster.tech/profiles/</a>.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initApplication() {
|
||||
Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
|
||||
if (
|
||||
activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) &&
|
||||
activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)
|
||||
) {
|
||||
log.error(
|
||||
"You have misconfigured your application! It should not run " + "with both the 'dev' and 'prod' profiles at the same time."
|
||||
);
|
||||
}
|
||||
if (
|
||||
activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) &&
|
||||
activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)
|
||||
) {
|
||||
log.error(
|
||||
"You have misconfigured your application! It should not " + "run with both the 'dev' and 'cloud' profiles at the same time."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main method, used to run the application.
|
||||
*
|
||||
* @param args the command line arguments.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
SpringApplication app = new SpringApplication(InformationsystemmonitorApp.class);
|
||||
DefaultProfileUtil.addDefaultProfile(app);
|
||||
Environment env = app.run(args).getEnvironment();
|
||||
logApplicationStartup(env);
|
||||
}
|
||||
|
||||
private static void logApplicationStartup(Environment env) {
|
||||
String protocol = Optional.ofNullable(env.getProperty("server.ssl.key-store")).map(key -> "https").orElse("http");
|
||||
String serverPort = env.getProperty("server.port");
|
||||
String contextPath = Optional
|
||||
.ofNullable(env.getProperty("server.servlet.context-path"))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.orElse("/");
|
||||
String hostAddress = "localhost";
|
||||
try {
|
||||
hostAddress = InetAddress.getLocalHost().getHostAddress();
|
||||
} catch (UnknownHostException e) {
|
||||
log.warn("The host name could not be determined, using `localhost` as fallback");
|
||||
}
|
||||
log.info(
|
||||
CRLFLogConverter.CRLF_SAFE_MARKER,
|
||||
"\n----------------------------------------------------------\n\t" +
|
||||
"Application '{}' is running! Access URLs:\n\t" +
|
||||
"Local: \t\t{}://localhost:{}{}\n\t" +
|
||||
"External: \t{}://{}:{}{}\n\t" +
|
||||
"Profile(s): \t{}\n----------------------------------------------------------",
|
||||
env.getProperty("spring.application.name"),
|
||||
protocol,
|
||||
serverPort,
|
||||
contextPath,
|
||||
protocol,
|
||||
hostAddress,
|
||||
serverPort,
|
||||
contextPath,
|
||||
env.getActiveProfiles().length == 0 ? env.getDefaultProfiles() : env.getActiveProfiles()
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.aop.logging;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.aspectj.lang.JoinPoint;
|
||||
import org.aspectj.lang.ProceedingJoinPoint;
|
||||
import org.aspectj.lang.annotation.AfterThrowing;
|
||||
import org.aspectj.lang.annotation.Around;
|
||||
import org.aspectj.lang.annotation.Aspect;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.core.env.Profiles;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
|
||||
/**
|
||||
* Aspect for logging execution of service and repository Spring components.
|
||||
*
|
||||
* By default, it only runs with the "dev" profile.
|
||||
*/
|
||||
@Aspect
|
||||
public class LoggingAspect {
|
||||
|
||||
private final Environment env;
|
||||
|
||||
public LoggingAspect(Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pointcut that matches all repositories, services and Web REST endpoints.
|
||||
*/
|
||||
@Pointcut(
|
||||
"within(@org.springframework.stereotype.Repository *)" +
|
||||
" || within(@org.springframework.stereotype.Service *)" +
|
||||
" || within(@org.springframework.web.bind.annotation.RestController *)"
|
||||
)
|
||||
public void springBeanPointcut() {
|
||||
// Method is empty as this is just a Pointcut, the implementations are in the advices.
|
||||
}
|
||||
|
||||
/**
|
||||
* Pointcut that matches all Spring beans in the application's main packages.
|
||||
*/
|
||||
@Pointcut(
|
||||
"within(org.gcube.fullstackapps.informationsystemmonitor.repository..*)" +
|
||||
" || within(org.gcube.fullstackapps.informationsystemmonitor.service..*)" +
|
||||
" || within(org.gcube.fullstackapps.informationsystemmonitor.web.rest..*)"
|
||||
)
|
||||
public void applicationPackagePointcut() {
|
||||
// Method is empty as this is just a Pointcut, the implementations are in the advices.
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the {@link Logger} associated to the given {@link JoinPoint}.
|
||||
*
|
||||
* @param joinPoint join point we want the logger for.
|
||||
* @return {@link Logger} associated to the given {@link JoinPoint}.
|
||||
*/
|
||||
private Logger logger(JoinPoint joinPoint) {
|
||||
return LoggerFactory.getLogger(joinPoint.getSignature().getDeclaringTypeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Advice that logs methods throwing exceptions.
|
||||
*
|
||||
* @param joinPoint join point for advice.
|
||||
* @param e exception.
|
||||
*/
|
||||
@AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
|
||||
public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
|
||||
if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) {
|
||||
logger(joinPoint)
|
||||
.error(
|
||||
"Exception in {}() with cause = '{}' and exception = '{}'",
|
||||
joinPoint.getSignature().getName(),
|
||||
e.getCause() != null ? e.getCause() : "NULL",
|
||||
e.getMessage(),
|
||||
e
|
||||
);
|
||||
} else {
|
||||
logger(joinPoint)
|
||||
.error(
|
||||
"Exception in {}() with cause = {}",
|
||||
joinPoint.getSignature().getName(),
|
||||
e.getCause() != null ? e.getCause() : "NULL"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Advice that logs when a method is entered and exited.
|
||||
*
|
||||
* @param joinPoint join point for advice.
|
||||
* @return result.
|
||||
* @throws Throwable throws {@link IllegalArgumentException}.
|
||||
*/
|
||||
@Around("applicationPackagePointcut() && springBeanPointcut()")
|
||||
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||
Logger log = logger(joinPoint);
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
|
||||
}
|
||||
try {
|
||||
Object result = joinPoint.proceed();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Exit: {}() with result = {}", joinPoint.getSignature().getName(), result);
|
||||
}
|
||||
return result;
|
||||
} catch (IllegalArgumentException e) {
|
||||
log.error("Illegal argument: {} in {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName());
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties specific to Informationsystemmonitor.
|
||||
* <p>
|
||||
* Properties are configured in the {@code application.yml} file.
|
||||
* See {@link tech.jhipster.config.JHipsterProperties} for a good example.
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
|
||||
public class ApplicationProperties {
|
||||
// jhipster-needle-application-properties-property
|
||||
// jhipster-needle-application-properties-property-getter
|
||||
// jhipster-needle-application-properties-property-class
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
|
||||
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
|
||||
import org.springframework.boot.autoconfigure.task.TaskExecutionProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.scheduling.annotation.AsyncConfigurer;
|
||||
import org.springframework.scheduling.annotation.EnableAsync;
|
||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
||||
import tech.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
|
||||
|
||||
@Configuration
|
||||
@EnableAsync
|
||||
@EnableScheduling
|
||||
@Profile("!testdev & !testprod")
|
||||
public class AsyncConfiguration implements AsyncConfigurer {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
|
||||
|
||||
private final TaskExecutionProperties taskExecutionProperties;
|
||||
|
||||
public AsyncConfiguration(TaskExecutionProperties taskExecutionProperties) {
|
||||
this.taskExecutionProperties = taskExecutionProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Bean(name = "taskExecutor")
|
||||
public Executor getAsyncExecutor() {
|
||||
log.debug("Creating Async Task Executor");
|
||||
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
|
||||
executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize());
|
||||
executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize());
|
||||
executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity());
|
||||
executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix());
|
||||
return new ExceptionHandlingAsyncTaskExecutor(executor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
|
||||
return new SimpleAsyncUncaughtExceptionHandler();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import ch.qos.logback.core.pattern.CompositeConverter;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
import org.springframework.boot.ansi.AnsiColor;
|
||||
import org.springframework.boot.ansi.AnsiElement;
|
||||
import org.springframework.boot.ansi.AnsiOutput;
|
||||
import org.springframework.boot.ansi.AnsiStyle;
|
||||
|
||||
public class CRLFLogConverter extends CompositeConverter<ILoggingEvent> {
|
||||
|
||||
public static final Marker CRLF_SAFE_MARKER = MarkerFactory.getMarker("CRLF_SAFE");
|
||||
|
||||
private static final String[] SAFE_LOGGERS = { "org.hibernate" };
|
||||
private static final Map<String, AnsiElement> ELEMENTS;
|
||||
|
||||
static {
|
||||
Map<String, AnsiElement> ansiElements = new HashMap<>();
|
||||
ansiElements.put("faint", AnsiStyle.FAINT);
|
||||
ansiElements.put("red", AnsiColor.RED);
|
||||
ansiElements.put("green", AnsiColor.GREEN);
|
||||
ansiElements.put("yellow", AnsiColor.YELLOW);
|
||||
ansiElements.put("blue", AnsiColor.BLUE);
|
||||
ansiElements.put("magenta", AnsiColor.MAGENTA);
|
||||
ansiElements.put("cyan", AnsiColor.CYAN);
|
||||
ELEMENTS = Collections.unmodifiableMap(ansiElements);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String transform(ILoggingEvent event, String in) {
|
||||
AnsiElement element = ELEMENTS.get(getFirstOption());
|
||||
if ((event.getMarker() != null && event.getMarker().contains(CRLF_SAFE_MARKER)) || isLoggerSafe(event)) {
|
||||
return in;
|
||||
}
|
||||
String replacement = element == null ? "_" : toAnsiString("_", element);
|
||||
return in.replaceAll("[\n\r\t]", replacement);
|
||||
}
|
||||
|
||||
protected boolean isLoggerSafe(ILoggingEvent event) {
|
||||
for (String safeLogger : SAFE_LOGGERS) {
|
||||
if (event.getLoggerName().startsWith(safeLogger)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String toAnsiString(String in, AnsiElement element) {
|
||||
return AnsiOutput.toString(element, in);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
/**
|
||||
* Application constants.
|
||||
*/
|
||||
public final class Constants {
|
||||
|
||||
// Regex for acceptable logins
|
||||
public static final String LOGIN_REGEX = "^(?>[a-zA-Z0-9!$&*+=?^_`{|}~.-]+@[a-zA-Z0-9-]+(?:\\.[a-zA-Z0-9-]+)*)|(?>[_.@A-Za-z0-9-]+)$";
|
||||
|
||||
public static final String SYSTEM = "system";
|
||||
public static final String DEFAULT_LANGUAGE = "en";
|
||||
|
||||
private Constants() {}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
/**
|
||||
* Configure the converters to use the ISO format for dates by default.
|
||||
*/
|
||||
@Configuration
|
||||
public class DateTimeFormatConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Override
|
||||
public void addFormatters(FormatterRegistry registry) {
|
||||
DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
|
||||
registrar.setUseIsoFormat(true);
|
||||
registrar.registerFormatters(registry);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
|
||||
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.zalando.problem.jackson.ProblemModule;
|
||||
import org.zalando.problem.violations.ConstraintViolationProblemModule;
|
||||
|
||||
@Configuration
|
||||
public class JacksonConfiguration {
|
||||
|
||||
/**
|
||||
* Support for Java date and time API.
|
||||
* @return the corresponding Jackson module.
|
||||
*/
|
||||
@Bean
|
||||
public JavaTimeModule javaTimeModule() {
|
||||
return new JavaTimeModule();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Jdk8Module jdk8TimeModule() {
|
||||
return new Jdk8Module();
|
||||
}
|
||||
|
||||
/*
|
||||
* Module for serialization/deserialization of RFC7807 Problem.
|
||||
*/
|
||||
@Bean
|
||||
public ProblemModule problemModule() {
|
||||
return new ProblemModule();
|
||||
}
|
||||
|
||||
/*
|
||||
* Module for serialization/deserialization of ConstraintViolationProblem.
|
||||
*/
|
||||
@Bean
|
||||
public ConstraintViolationProblemModule constraintViolationProblemModule() {
|
||||
return new ConstraintViolationProblemModule();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.*;
|
||||
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
|
||||
import tech.jhipster.config.locale.AngularCookieLocaleResolver;
|
||||
|
||||
@Configuration
|
||||
public class LocaleConfiguration implements WebMvcConfigurer {
|
||||
|
||||
@Bean
|
||||
public LocaleResolver localeResolver() {
|
||||
AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
|
||||
cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
|
||||
return cookieLocaleResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
|
||||
localeChangeInterceptor.setParamName("language");
|
||||
registry.addInterceptor(localeChangeInterceptor);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.aop.logging.LoggingAspect;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.core.env.Environment;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
|
||||
@Configuration
|
||||
@EnableAspectJAutoProxy
|
||||
public class LoggingAspectConfiguration {
|
||||
|
||||
@Bean
|
||||
@Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
|
||||
public LoggingAspect loggingAspect(Environment env) {
|
||||
return new LoggingAspect(env);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import static tech.jhipster.config.logging.LoggingUtils.*;
|
||||
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
/*
|
||||
* Configures the console and Logstash log appenders from the app properties
|
||||
*/
|
||||
@Configuration
|
||||
public class LoggingConfiguration {
|
||||
|
||||
public LoggingConfiguration(
|
||||
@Value("${spring.application.name}") String appName,
|
||||
@Value("${server.port}") String serverPort,
|
||||
JHipsterProperties jHipsterProperties,
|
||||
ObjectMapper mapper
|
||||
) throws JsonProcessingException {
|
||||
LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
Map<String, String> map = new HashMap<>();
|
||||
map.put("app_name", appName);
|
||||
map.put("app_port", serverPort);
|
||||
String customFields = mapper.writeValueAsString(map);
|
||||
|
||||
JHipsterProperties.Logging loggingProperties = jHipsterProperties.getLogging();
|
||||
JHipsterProperties.Logging.Logstash logstashProperties = loggingProperties.getLogstash();
|
||||
|
||||
if (loggingProperties.isUseJsonFormat()) {
|
||||
addJsonConsoleAppender(context, customFields);
|
||||
}
|
||||
if (logstashProperties.isEnabled()) {
|
||||
addLogstashTcpSocketAppender(context, customFields, logstashProperties);
|
||||
}
|
||||
if (loggingProperties.isUseJsonFormat() || logstashProperties.isEnabled()) {
|
||||
addContextListener(context, customFields, loggingProperties);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import java.time.Duration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientProviderBuilder;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
|
||||
|
||||
@Configuration
|
||||
public class OAuth2Configuration {
|
||||
|
||||
@Bean
|
||||
public OAuth2AuthorizedClientManager authorizedClientManager(
|
||||
ClientRegistrationRepository clientRegistrationRepository,
|
||||
OAuth2AuthorizedClientRepository authorizedClientRepository
|
||||
) {
|
||||
DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager(
|
||||
clientRegistrationRepository,
|
||||
authorizedClientRepository
|
||||
);
|
||||
|
||||
authorizedClientManager.setAuthorizedClientProvider(
|
||||
OAuth2AuthorizedClientProviderBuilder
|
||||
.builder()
|
||||
.authorizationCode()
|
||||
.refreshToken(builder -> builder.clockSkew(Duration.ofMinutes(3)))
|
||||
.clientCredentials()
|
||||
.password()
|
||||
.build()
|
||||
);
|
||||
|
||||
|
||||
return authorizedClientManager;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.springdoc.core.GroupedOpenApi;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
import tech.jhipster.config.apidoc.customizer.JHipsterOpenApiCustomizer;
|
||||
|
||||
@Configuration
|
||||
@Profile(JHipsterConstants.SPRING_PROFILE_API_DOCS)
|
||||
public class OpenApiConfiguration {
|
||||
|
||||
public static final String API_FIRST_PACKAGE = "org.gcube.fullstackapps.informationsystemmonitor.web.api";
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(name = "apiFirstGroupedOpenAPI")
|
||||
public GroupedOpenApi apiFirstGroupedOpenAPI(
|
||||
JHipsterOpenApiCustomizer jhipsterOpenApiCustomizer,
|
||||
JHipsterProperties jHipsterProperties
|
||||
) {
|
||||
JHipsterProperties.ApiDocs properties = jHipsterProperties.getApiDocs();
|
||||
return GroupedOpenApi
|
||||
.builder()
|
||||
.group("openapi")
|
||||
.addOpenApiCustomiser(jhipsterOpenApiCustomizer)
|
||||
.packagesToScan(API_FIRST_PACKAGE)
|
||||
.pathsToMatch(properties.getDefaultIncludePattern())
|
||||
.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.AuthoritiesConstants;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.SecurityUtils;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.oauth2.AudienceValidator;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.oauth2.CustomClaimConverter;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.oauth2.JwtGrantedAuthorityConverter;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.web.filter.OAuth2RefreshTokensWebFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.RequestEntity;
|
||||
import org.springframework.http.converter.FormHttpMessageConverter;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.authorization.AuthorityAuthorizationManager;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
|
||||
import org.springframework.security.oauth2.client.InMemoryOAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.endpoint.DefaultAuthorizationCodeTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.NimbusAuthorizationCodeTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AccessTokenResponseClient;
|
||||
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest;
|
||||
import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
|
||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
|
||||
import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserService;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
|
||||
import org.springframework.security.oauth2.core.DelegatingOAuth2TokenValidator;
|
||||
import org.springframework.security.oauth2.core.OAuth2AccessToken;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
|
||||
import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
|
||||
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoder;
|
||||
import org.springframework.security.oauth2.jwt.JwtDecoders;
|
||||
import org.springframework.security.oauth2.jwt.JwtValidators;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfFilter;
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
|
||||
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
|
||||
@EnableWebSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
|
||||
@Import(SecurityProblemSupport.class)
|
||||
public class SecurityConfiguration {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SecurityConfiguration.class);
|
||||
|
||||
private final JHipsterProperties jHipsterProperties;
|
||||
|
||||
private final CorsFilter corsFilter;
|
||||
|
||||
@Value("${spring.security.oauth2.client.provider.oidc.issuer-uri}")
|
||||
private String issuerUri;
|
||||
|
||||
private final SecurityProblemSupport problemSupport;
|
||||
|
||||
public SecurityConfiguration(CorsFilter corsFilter, JHipsterProperties jHipsterProperties,
|
||||
SecurityProblemSupport problemSupport) {
|
||||
this.corsFilter = corsFilter;
|
||||
this.problemSupport = problemSupport;
|
||||
this.jHipsterProperties = jHipsterProperties;
|
||||
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
// @formatter:off
|
||||
http
|
||||
.csrf()
|
||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
.and()
|
||||
.addFilterBefore(corsFilter, CsrfFilter.class)
|
||||
.exceptionHandling()
|
||||
.authenticationEntryPoint(problemSupport)
|
||||
.accessDeniedHandler(problemSupport)
|
||||
.and()
|
||||
.headers()
|
||||
.contentSecurityPolicy(jHipsterProperties.getSecurity().getContentSecurityPolicy())
|
||||
.and()
|
||||
.referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN)
|
||||
.and()
|
||||
.permissionsPolicy().policy("camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()")
|
||||
.and()
|
||||
.frameOptions().sameOrigin()
|
||||
.and()
|
||||
.authorizeRequests()
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
|
||||
.antMatchers("/app/**/*.{js,html}").permitAll()
|
||||
.antMatchers("/i18n/**").permitAll()
|
||||
.antMatchers("/content/**").permitAll()
|
||||
.antMatchers("/swagger-ui/**").permitAll()
|
||||
.antMatchers("/test/**").permitAll()
|
||||
.antMatchers("/login/oauth2/code/oidc").permitAll()
|
||||
.antMatchers("/api/account").permitAll()
|
||||
.antMatchers("/api/authenticate").permitAll()
|
||||
.antMatchers("/api/auth-info").permitAll()
|
||||
.antMatchers("/api/admin/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/api/**").authenticated()
|
||||
.antMatchers("/management/health").permitAll()
|
||||
.antMatchers("/management/health/**").permitAll()
|
||||
.antMatchers("/management/info").permitAll()
|
||||
.antMatchers("/management/prometheus").permitAll()
|
||||
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.and()
|
||||
.oauth2Login()
|
||||
//.defaultSuccessUrl("/api/scopes/discovery").userInfoEndpoint(userInfo -> userInfo
|
||||
// .oidcUserService(this.oidcUserService()))
|
||||
//.defaultSuccessUrl(issuerUri, false)
|
||||
//.defaultSuccessUrl("/api/login/oauth2/code/oidc")
|
||||
//.addFilterAfter(new CustomAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
|
||||
//.logout(logout -> logout.logoutSuccessHandler(oidcLogoutSuccessHandler()))
|
||||
//.tokenEndpoint()
|
||||
//.accessTokenResponseClient(accessTokenResponseClient())
|
||||
//.and()
|
||||
//.oauth2ResourceServer()
|
||||
//.jwt()
|
||||
//.jwtAuthenticationConverter(authenticationConverter())
|
||||
//.and()
|
||||
.and()
|
||||
.oauth2Client();
|
||||
//.authorizationCodeGrant();
|
||||
|
||||
|
||||
return http.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
|
||||
|
||||
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService() {
|
||||
final OidcUserService delegate = new OidcUserService();
|
||||
|
||||
return (userRequest) -> {
|
||||
// Delegate to the default implementation for loading a user
|
||||
OidcUser oidcUser = delegate.loadUser(userRequest);
|
||||
|
||||
OAuth2AccessToken accessToken = userRequest.getAccessToken();
|
||||
|
||||
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
||||
logger.debug("Fetch AccessToken: {}",accessToken.getTokenValue());
|
||||
// TODO
|
||||
// 1) Fetch the authority information from the protected resource using accessToken
|
||||
// 2) Map the authority information to one or more GrantedAuthority's and add it to mappedAuthorities
|
||||
|
||||
// 3) Create a copy of oidcUser but use the mappedAuthorities instead
|
||||
oidcUser = new DefaultOidcUser(mappedAuthorities, oidcUser.getIdToken(), oidcUser.getUserInfo());
|
||||
logger.debug("OIDCUser: {}",oidcUser);
|
||||
|
||||
return oidcUser;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
Converter<Jwt, AbstractAuthenticationToken> authenticationConverter() {
|
||||
logger.debug("JWT AuthenticationConverter()");
|
||||
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
|
||||
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(new JwtGrantedAuthorityConverter());
|
||||
return jwtAuthenticationConverter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Map authorities from "groups" or "roles" claim in ID Token.
|
||||
*
|
||||
* @return a {@link GrantedAuthoritiesMapper} that maps groups from the IdP to
|
||||
* Spring Security Authorities.
|
||||
*/
|
||||
@Bean
|
||||
public GrantedAuthoritiesMapper userAuthoritiesMapper() {
|
||||
return authorities -> {
|
||||
logger.debug("Authorities: {}", authorities);
|
||||
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();
|
||||
|
||||
authorities.forEach(authority -> {
|
||||
// Check for OidcUserAuthority because Spring Security 5.2 returns
|
||||
// each scope as a GrantedAuthority, which we don't care about.
|
||||
logger.debug("Authority: {}", authority);
|
||||
if (authority instanceof OidcUserAuthority) {
|
||||
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
|
||||
logger.debug("TokenValue: {}", oidcUserAuthority.getIdToken().getTokenValue());
|
||||
logger.debug("oidcUserAuthority: {}", oidcUserAuthority);
|
||||
mappedAuthorities.addAll(
|
||||
SecurityUtils.extractAuthorityFromClaims(oidcUserAuthority.getUserInfo().getClaims()));
|
||||
}
|
||||
});
|
||||
return mappedAuthorities;
|
||||
};
|
||||
}
|
||||
|
||||
@Bean
|
||||
JwtDecoder jwtDecoder(ClientRegistrationRepository clientRegistrationRepository,
|
||||
RestTemplateBuilder restTemplateBuilder) {
|
||||
logger.debug("JWTDecoder: {}", restTemplateBuilder);
|
||||
|
||||
NimbusJwtDecoder jwtDecoder = JwtDecoders.fromOidcIssuerLocation(issuerUri);
|
||||
|
||||
OAuth2TokenValidator<Jwt> audienceValidator = new AudienceValidator(
|
||||
jHipsterProperties.getSecurity().getOauth2().getAudience());
|
||||
OAuth2TokenValidator<Jwt> withIssuer = JwtValidators.createDefaultWithIssuer(issuerUri);
|
||||
OAuth2TokenValidator<Jwt> withAudience = new DelegatingOAuth2TokenValidator<>(withIssuer, audienceValidator);
|
||||
|
||||
jwtDecoder.setJwtValidator(withAudience);
|
||||
jwtDecoder.setClaimSetConverter(new CustomClaimConverter(
|
||||
clientRegistrationRepository.findByRegistrationId("oidc"), restTemplateBuilder.build()));
|
||||
|
||||
return jwtDecoder;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.Profile;
|
||||
import org.springframework.http.CacheControl;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistration;
|
||||
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
@Configuration
|
||||
@Profile({ JHipsterConstants.SPRING_PROFILE_PRODUCTION })
|
||||
public class StaticResourcesWebConfiguration implements WebMvcConfigurer {
|
||||
|
||||
protected static final String[] RESOURCE_LOCATIONS = new String[] {
|
||||
"classpath:/static/",
|
||||
"classpath:/static/content/",
|
||||
"classpath:/static/i18n/",
|
||||
};
|
||||
protected static final String[] RESOURCE_PATHS = new String[] {
|
||||
"/*.js",
|
||||
"/*.css",
|
||||
"/*.svg",
|
||||
"/*.png",
|
||||
"*.ico",
|
||||
"/content/**",
|
||||
"/i18n/*",
|
||||
};
|
||||
|
||||
private final JHipsterProperties jhipsterProperties;
|
||||
|
||||
public StaticResourcesWebConfiguration(JHipsterProperties jHipsterProperties) {
|
||||
this.jhipsterProperties = jHipsterProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
ResourceHandlerRegistration resourceHandlerRegistration = appendResourceHandler(registry);
|
||||
initializeResourceHandler(resourceHandlerRegistration);
|
||||
}
|
||||
|
||||
protected ResourceHandlerRegistration appendResourceHandler(ResourceHandlerRegistry registry) {
|
||||
return registry.addResourceHandler(RESOURCE_PATHS);
|
||||
}
|
||||
|
||||
protected void initializeResourceHandler(ResourceHandlerRegistration resourceHandlerRegistration) {
|
||||
resourceHandlerRegistration.addResourceLocations(RESOURCE_LOCATIONS).setCacheControl(getCacheControl());
|
||||
}
|
||||
|
||||
protected CacheControl getCacheControl() {
|
||||
return CacheControl.maxAge(getJHipsterHttpCacheProperty(), TimeUnit.DAYS).cachePublic();
|
||||
}
|
||||
|
||||
private int getJHipsterHttpCacheProperty() {
|
||||
return jhipsterProperties.getHttp().getCache().getTimeToLiveInDays();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.dto.UmaResponseDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.LinkedMultiValueMap;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
|
||||
|
||||
|
||||
@Component
|
||||
public class TokenManager {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(TokenManager.class);
|
||||
@Value("${spring.security.oauth2.client.provider.oidc.token-uri}")
|
||||
private String tokenUri;
|
||||
|
||||
@Autowired
|
||||
private OAuth2AuthorizedClientService authorizedClientService;
|
||||
|
||||
|
||||
|
||||
public String getUmaToken(String context) {
|
||||
String accessToken=getAccessToken();
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||
headers.set("Authorization", "Bearer " + accessToken);
|
||||
log.debug("Headers: {}", headers);
|
||||
|
||||
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
|
||||
params.add("grant_type", "urn:ietf:params:oauth:grant-type:uma-ticket");
|
||||
params.add("audience", context);
|
||||
log.debug("Params: {}", params);
|
||||
|
||||
HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(params, headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
|
||||
ResponseEntity<UmaResponseDTO> response = restTemplate.exchange(tokenUri, HttpMethod.POST, entity, UmaResponseDTO.class);
|
||||
UmaResponseDTO umaResponceDTO = response.getBody();
|
||||
log.debug("UmaResponceDTO: {}", umaResponceDTO);
|
||||
String umaToken=umaResponceDTO.getAccess_token();
|
||||
log.debug("UmaToken: {}", umaToken);
|
||||
return umaToken;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
OAuth2AuthenticationToken oAuth2AuthenticationToken = (OAuth2AuthenticationToken) SecurityContextHolder
|
||||
.getContext().getAuthentication();
|
||||
log.debug("OAuth2AuthenticationToken: {}", oAuth2AuthenticationToken);
|
||||
|
||||
OAuth2AuthorizedClient client = authorizedClientService.loadAuthorizedClient(
|
||||
oAuth2AuthenticationToken.getAuthorizedClientRegistrationId(), oAuth2AuthenticationToken.getName());
|
||||
/*if(client.getAccessToken().getExpiresAt().compareTo(Instant.now())>0) {
|
||||
|
||||
}*/
|
||||
|
||||
String accessToken = client.getAccessToken().getTokenValue();
|
||||
|
||||
log.debug("AccessToken: {}", accessToken);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public String getRootContext() {
|
||||
String rootContext = "/gcube";
|
||||
return rootContext;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
||||
|
||||
import static java.net.URLDecoder.decode;
|
||||
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactory;
|
||||
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
|
||||
import org.springframework.boot.web.servlet.ServletContextInitializer;
|
||||
import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
/**
|
||||
* Configuration of web application with Servlet 3.0 APIs.
|
||||
*/
|
||||
@Configuration
|
||||
public class WebConfigurer implements ServletContextInitializer, WebServerFactoryCustomizer<WebServerFactory> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
|
||||
|
||||
private final Environment env;
|
||||
|
||||
private final JHipsterProperties jHipsterProperties;
|
||||
|
||||
public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties) {
|
||||
this.env = env;
|
||||
this.jHipsterProperties = jHipsterProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
if (env.getActiveProfiles().length != 0) {
|
||||
log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
|
||||
}
|
||||
|
||||
log.info("Web application fully configured");
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the Servlet engine: Mime types, the document root, the cache.
|
||||
*/
|
||||
@Override
|
||||
public void customize(WebServerFactory server) {
|
||||
// When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets.
|
||||
setLocationForStaticAssets(server);
|
||||
}
|
||||
|
||||
private void setLocationForStaticAssets(WebServerFactory server) {
|
||||
if (server instanceof ConfigurableServletWebServerFactory) {
|
||||
ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server;
|
||||
File root;
|
||||
String prefixPath = resolvePathPrefix();
|
||||
root = new File(prefixPath + "target/classes/static/");
|
||||
if (root.exists() && root.isDirectory()) {
|
||||
servletWebServer.setDocumentRoot(root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve path prefix to static resources.
|
||||
*/
|
||||
private String resolvePathPrefix() {
|
||||
String fullExecutablePath = decode(this.getClass().getResource("").getPath(), StandardCharsets.UTF_8);
|
||||
String rootPath = Paths.get(".").toUri().normalize().getPath();
|
||||
String extractedPath = fullExecutablePath.replace(rootPath, "");
|
||||
int extractionEndIndex = extractedPath.indexOf("target/");
|
||||
if (extractionEndIndex <= 0) {
|
||||
return "";
|
||||
}
|
||||
return extractedPath.substring(0, extractionEndIndex);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = jHipsterProperties.getCors();
|
||||
if (!CollectionUtils.isEmpty(config.getAllowedOrigins()) || !CollectionUtils.isEmpty(config.getAllowedOriginPatterns())) {
|
||||
log.debug("Registering CORS filter");
|
||||
source.registerCorsConfiguration("/login/**", config);
|
||||
source.registerCorsConfiguration("/api/**", config);
|
||||
source.registerCorsConfiguration("/management/**", config);
|
||||
source.registerCorsConfiguration("/v3/api-docs", config);
|
||||
source.registerCorsConfiguration("/swagger-ui/**", config);
|
||||
}
|
||||
return new CorsFilter(source);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Spring Framework configuration files.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.config;
|
|
@ -0,0 +1,17 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.domain;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TestDialogDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String status;
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* JPA domain objects.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.domain;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Spring Data JPA repositories.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.repository;
|
|
@ -0,0 +1,15 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security;
|
||||
|
||||
/**
|
||||
* Constants for Spring Security authorities.
|
||||
*/
|
||||
public final class AuthoritiesConstants {
|
||||
|
||||
public static final String ADMIN = "ROLE_ADMIN";
|
||||
|
||||
public static final String USER = "ROLE_USER";
|
||||
|
||||
public static final String ANONYMOUS = "ROLE_ANONYMOUS";
|
||||
|
||||
private AuthoritiesConstants() {}
|
||||
}
|
|
@ -0,0 +1,167 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
|
||||
/**
|
||||
* Utility class for Spring Security.
|
||||
*/
|
||||
public final class SecurityUtils {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(SecurityUtils.class);
|
||||
|
||||
public static final String CLAIMS_NAMESPACE = "https://www.jhipster.tech/";
|
||||
|
||||
private SecurityUtils() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the login of the current user.
|
||||
*
|
||||
* @return the login of the current user.
|
||||
*/
|
||||
public static Optional<String> getCurrentUserLogin() {
|
||||
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
return Optional.ofNullable(extractPrincipal(securityContext.getAuthentication()));
|
||||
}
|
||||
|
||||
private static String extractPrincipal(Authentication authentication) {
|
||||
logger.debug("extractPrincipal: {}", authentication);
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
} else if (authentication.getPrincipal() instanceof UserDetails) {
|
||||
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
|
||||
return springSecurityUser.getUsername();
|
||||
} else if (authentication instanceof JwtAuthenticationToken) {
|
||||
return (String) ((JwtAuthenticationToken) authentication).getToken().getClaims().get("preferred_username");
|
||||
} else if (authentication.getPrincipal() instanceof DefaultOidcUser) {
|
||||
Map<String, Object> attributes = ((DefaultOidcUser) authentication.getPrincipal()).getAttributes();
|
||||
if (attributes.containsKey("preferred_username")) {
|
||||
return (String) attributes.get("preferred_username");
|
||||
}
|
||||
} else if (authentication.getPrincipal() instanceof String) {
|
||||
return (String) authentication.getPrincipal();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a user is authenticated.
|
||||
*
|
||||
* @return true if the user is authenticated, false otherwise.
|
||||
*/
|
||||
public static boolean isAuthenticated() {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
return authentication != null
|
||||
&& getAuthorities(authentication).noneMatch(AuthoritiesConstants.ANONYMOUS::equals);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has any of the authorities.
|
||||
*
|
||||
* @param authorities the authorities to check.
|
||||
* @return true if the current user has any of the authorities, false otherwise.
|
||||
*/
|
||||
public static boolean hasCurrentUserAnyOfAuthorities(String... authorities) {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
return (authentication != null && getAuthorities(authentication)
|
||||
.anyMatch(authority -> Arrays.asList(authorities).contains(authority)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has none of the authorities.
|
||||
*
|
||||
* @param authorities the authorities to check.
|
||||
* @return true if the current user has none of the authorities, false
|
||||
* otherwise.
|
||||
*/
|
||||
public static boolean hasCurrentUserNoneOfAuthorities(String... authorities) {
|
||||
return !hasCurrentUserAnyOfAuthorities(authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the current user has a specific authority.
|
||||
*
|
||||
* @param authority the authority to check.
|
||||
* @return true if the current user has the authority, false otherwise.
|
||||
*/
|
||||
public static boolean hasCurrentUserThisAuthority(String authority) {
|
||||
return hasCurrentUserAnyOfAuthorities(authority);
|
||||
}
|
||||
|
||||
private static Stream<String> getAuthorities(Authentication authentication) {
|
||||
logger.debug("getAuthorities: {}", authentication);
|
||||
Collection<? extends GrantedAuthority> authorities = authentication instanceof JwtAuthenticationToken
|
||||
? extractAuthorityFromClaims(((JwtAuthenticationToken) authentication).getToken().getClaims())
|
||||
: authentication.getAuthorities();
|
||||
return authorities.stream().map(GrantedAuthority::getAuthority);
|
||||
}
|
||||
|
||||
public static List<GrantedAuthority> extractAuthorityFromClaims(Map<String, Object> claims) {
|
||||
logger.debug("extractAuthorityFromClaims: {}", claims);
|
||||
return mapRolesToGrantedAuthorities(getRolesFromClaims(claims));
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static Collection<String> getRolesFromClaims(Map<String, Object> claims) {
|
||||
logger.debug("getRolesFromClaims(): {}", claims);
|
||||
// return (Collection<String>) claims.getOrDefault(
|
||||
// "groups",
|
||||
// claims.getOrDefault("roles", claims.getOrDefault(CLAIMS_NAMESPACE + "roles",
|
||||
// new ArrayList<>()))
|
||||
// );
|
||||
if (claims.get("resource_access") != null) {
|
||||
logger.debug("ResourceAccess: {}",claims.get("resource_access").getClass());
|
||||
Map<String,Object> scope=(Map<String,Object>)claims.get("resource_access");
|
||||
ArrayList<String> roles = new ArrayList<>();
|
||||
for (String key : scope.keySet()) {
|
||||
logger.info("Default Scope: {}",key);
|
||||
roles=((Map<String, ArrayList<String>>)scope.get(key)).get("roles");
|
||||
break;
|
||||
}
|
||||
logger.info("D4Science Roles: {}",roles);
|
||||
return roles;
|
||||
} else {
|
||||
logger.debug("D4Science Roles: {}");
|
||||
return new ArrayList<String>();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static List<GrantedAuthority> mapRolesToGrantedAuthorities(Collection<String> roles) {
|
||||
logger.debug("mapRolesToGrantedAuthorities(): {}", roles);
|
||||
List<GrantedAuthority> ga = new ArrayList<>();
|
||||
boolean isAdmin = false;
|
||||
for (String role : roles) {
|
||||
if (role.compareTo("Member") == 0) {
|
||||
isAdmin = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isAdmin) {
|
||||
ga.add(new SimpleGrantedAuthority(AuthoritiesConstants.ADMIN));
|
||||
} else {
|
||||
ga.add(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
|
||||
|
||||
}
|
||||
logger.info("GrantedAuthority: {}",ga);
|
||||
return ga;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security.oauth2;
|
||||
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.oauth2.core.OAuth2Error;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
|
||||
import org.springframework.security.oauth2.core.OAuth2TokenValidatorResult;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
public class AudienceValidator implements OAuth2TokenValidator<Jwt> {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(AudienceValidator.class);
|
||||
private final OAuth2Error error = new OAuth2Error("invalid_token", "The required audience is missing", null);
|
||||
|
||||
private final List<String> allowedAudience;
|
||||
|
||||
public AudienceValidator(List<String> allowedAudience) {
|
||||
Assert.notEmpty(allowedAudience, "Allowed audience should not be null or empty.");
|
||||
this.allowedAudience = allowedAudience;
|
||||
}
|
||||
|
||||
public OAuth2TokenValidatorResult validate(Jwt jwt) {
|
||||
List<String> audience = jwt.getAudience();
|
||||
if (audience.stream().anyMatch(allowedAudience::contains)) {
|
||||
return OAuth2TokenValidatorResult.success();
|
||||
} else {
|
||||
log.warn("Invalid audience: {}", audience);
|
||||
return OAuth2TokenValidatorResult.failure(error);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security.oauth2;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.http.HttpEntity;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistration;
|
||||
import org.springframework.security.oauth2.jwt.MappedJwtClaimSetConverter;
|
||||
import org.springframework.security.oauth2.server.resource.web.BearerTokenResolver;
|
||||
import org.springframework.security.oauth2.server.resource.web.DefaultBearerTokenResolver;
|
||||
import org.springframework.web.client.RestTemplate;
|
||||
import org.springframework.web.context.request.RequestAttributes;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.github.benmanes.caffeine.cache.Cache;
|
||||
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||
|
||||
/**
|
||||
* Claim converter to add custom claims by retrieving the user from the userinfo endpoint.
|
||||
*/
|
||||
public class CustomClaimConverter implements Converter<Map<String, Object>, Map<String, Object>> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(CustomClaimConverter.class);
|
||||
|
||||
private final BearerTokenResolver bearerTokenResolver = new DefaultBearerTokenResolver();
|
||||
|
||||
private final MappedJwtClaimSetConverter delegate = MappedJwtClaimSetConverter.withDefaults(Collections.emptyMap());
|
||||
|
||||
private final RestTemplate restTemplate;
|
||||
|
||||
private final ClientRegistration registration;
|
||||
|
||||
// See https://github.com/jhipster/generator-jhipster/issues/18868
|
||||
// We don't use a distributed cache or the user selected cache implementation here on purpose
|
||||
private final Cache<String, ObjectNode> users = Caffeine
|
||||
.newBuilder()
|
||||
.maximumSize(10_000)
|
||||
.expireAfterWrite(Duration.ofHours(1))
|
||||
.recordStats()
|
||||
.build();
|
||||
|
||||
public CustomClaimConverter(ClientRegistration registration, RestTemplate restTemplate) {
|
||||
this.registration = registration;
|
||||
this.restTemplate = restTemplate;
|
||||
}
|
||||
|
||||
public Map<String, Object> convert(Map<String, Object> claims) {
|
||||
logger.debug("convert()");
|
||||
Map<String, Object> convertedClaims = this.delegate.convert(claims);
|
||||
// Only look up user information if identity claims are missing
|
||||
if (claims.containsKey("given_name") && claims.containsKey("family_name")) {
|
||||
return convertedClaims;
|
||||
}
|
||||
RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
|
||||
if (attributes instanceof ServletRequestAttributes) {
|
||||
// Retrieve and set the token
|
||||
String token = bearerTokenResolver.resolve(((ServletRequestAttributes) attributes).getRequest());
|
||||
logger.debug("Token: {}",token);
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.set("Authorization", buildBearer(token));
|
||||
|
||||
// Retrieve user info from OAuth provider if not already loaded
|
||||
ObjectNode user = users.get(
|
||||
claims.get("sub").toString(),
|
||||
s -> {
|
||||
ResponseEntity<ObjectNode> userInfo = restTemplate.exchange(
|
||||
registration.getProviderDetails().getUserInfoEndpoint().getUri(),
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(headers),
|
||||
ObjectNode.class
|
||||
);
|
||||
return userInfo.getBody();
|
||||
}
|
||||
);
|
||||
|
||||
logger.debug("User Info: {}",user);
|
||||
|
||||
// Add custom claims
|
||||
if (user != null) {
|
||||
convertedClaims.put("preferred_username", user.get("preferred_username").asText());
|
||||
if (user.has("given_name")) {
|
||||
convertedClaims.put("given_name", user.get("given_name").asText());
|
||||
}
|
||||
if (user.has("family_name")) {
|
||||
convertedClaims.put("family_name", user.get("family_name").asText());
|
||||
}
|
||||
if (user.has("email")) {
|
||||
convertedClaims.put("email", user.get("email").asText());
|
||||
}
|
||||
// Allow full name in a name claim - happens with Auth0
|
||||
if (user.has("name")) {
|
||||
String[] name = user.get("name").asText().split("\\s+");
|
||||
if (name.length > 0) {
|
||||
convertedClaims.put("given_name", name[0]);
|
||||
convertedClaims.put("family_name", String.join(" ", Arrays.copyOfRange(name, 1, name.length)));
|
||||
}
|
||||
}
|
||||
if (user.has("groups")) {
|
||||
List<String> groups = StreamSupport
|
||||
.stream(user.get("groups").spliterator(), false)
|
||||
.map(JsonNode::asText)
|
||||
.collect(Collectors.toList());
|
||||
convertedClaims.put("groups", groups);
|
||||
}
|
||||
if (user.has(SecurityUtils.CLAIMS_NAMESPACE + "roles")) {
|
||||
List<String> roles = StreamSupport
|
||||
.stream(user.get(SecurityUtils.CLAIMS_NAMESPACE + "roles").spliterator(), false)
|
||||
.map(JsonNode::asText)
|
||||
.collect(Collectors.toList());
|
||||
convertedClaims.put("roles", roles);
|
||||
}
|
||||
}
|
||||
}
|
||||
logger.debug("Claims: "+convertedClaims.toString());
|
||||
return convertedClaims;
|
||||
}
|
||||
|
||||
private String buildBearer(String token) {
|
||||
return "Bearer " + token;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security.oauth2;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class JwtGrantedAuthorityConverter implements Converter<Jwt, Collection<GrantedAuthority>> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(JwtGrantedAuthorityConverter.class);
|
||||
public JwtGrantedAuthorityConverter() {
|
||||
logger.debug("New JwtGrantedAuthorityConverter: created");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<GrantedAuthority> convert(Jwt jwt) {
|
||||
logger.debug("convert(): {}",jwt);
|
||||
return SecurityUtils.extractAuthorityFromClaims(jwt.getClaims());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.security.oauth2;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class OAuthIdpTokenResponseDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@JsonProperty("token_type")
|
||||
private String tokenType;
|
||||
|
||||
private String scope;
|
||||
|
||||
@JsonProperty("expires_in")
|
||||
private Long expiresIn;
|
||||
|
||||
@JsonProperty("ext_expires_in")
|
||||
private Long extExpiresIn;
|
||||
|
||||
@JsonProperty("expires_on")
|
||||
private Long expiresOn;
|
||||
|
||||
@JsonProperty("not-before-policy")
|
||||
private Long notBefore;
|
||||
|
||||
private UUID resource;
|
||||
|
||||
@JsonProperty("access_token")
|
||||
private String accessToken;
|
||||
|
||||
@JsonProperty("refresh_token")
|
||||
private String refreshToken;
|
||||
|
||||
@JsonProperty("id_token")
|
||||
private String idToken;
|
||||
|
||||
@JsonProperty("session_state")
|
||||
private String sessionState;
|
||||
|
||||
@JsonProperty("refresh_expires_in")
|
||||
private String refreshExpiresIn;
|
||||
|
||||
public OAuthIdpTokenResponseDTO() {
|
||||
// Empty constructor for serialization.
|
||||
}
|
||||
|
||||
public String getRefreshExpiresIn() {
|
||||
return refreshExpiresIn;
|
||||
}
|
||||
|
||||
public void setRefreshExpiresIn(String refreshExpiresIn) {
|
||||
this.refreshExpiresIn = refreshExpiresIn;
|
||||
}
|
||||
|
||||
public String getSessionState() {
|
||||
return sessionState;
|
||||
}
|
||||
|
||||
public void setSessionState(String sessionState) {
|
||||
this.sessionState = sessionState;
|
||||
}
|
||||
|
||||
public String getTokenType() {
|
||||
return tokenType;
|
||||
}
|
||||
|
||||
public void setTokenType(String tokenType) {
|
||||
this.tokenType = tokenType;
|
||||
}
|
||||
|
||||
public String getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public void setScope(String scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public Long getExpiresIn() {
|
||||
return expiresIn;
|
||||
}
|
||||
|
||||
public void setExpiresIn(Long expiresIn) {
|
||||
this.expiresIn = expiresIn;
|
||||
}
|
||||
|
||||
public Long getExtExpiresIn() {
|
||||
return extExpiresIn;
|
||||
}
|
||||
|
||||
public void setExtExpiresIn(Long extExpiresIn) {
|
||||
this.extExpiresIn = extExpiresIn;
|
||||
}
|
||||
|
||||
public Long getExpiresOn() {
|
||||
return expiresOn;
|
||||
}
|
||||
|
||||
public void setExpiresOn(Long expiresOn) {
|
||||
this.expiresOn = expiresOn;
|
||||
}
|
||||
|
||||
public Long getNotBefore() {
|
||||
return notBefore;
|
||||
}
|
||||
|
||||
public void setNotBefore(Long notBefore) {
|
||||
this.notBefore = notBefore;
|
||||
}
|
||||
|
||||
public UUID getResource() {
|
||||
return resource;
|
||||
}
|
||||
|
||||
public void setResource(UUID resource) {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
public String getAccessToken() {
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
public void setAccessToken(String accessToken) {
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
public String getRefreshToken() {
|
||||
return refreshToken;
|
||||
}
|
||||
|
||||
public void setRefreshToken(String refreshToken) {
|
||||
this.refreshToken = refreshToken;
|
||||
}
|
||||
|
||||
public String getIdToken() {
|
||||
return idToken;
|
||||
}
|
||||
|
||||
public void setIdToken(String idToken) {
|
||||
this.idToken = idToken;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "OAuthIdpTokenResponseDTO [tokenType=" + tokenType + ", scope=" + scope + ", expiresIn=" + expiresIn
|
||||
+ ", extExpiresIn=" + extExpiresIn + ", expiresOn=" + expiresOn + ", notBefore=" + notBefore
|
||||
+ ", resource=" + resource + ", accessToken=" + accessToken + ", refreshToken=" + refreshToken
|
||||
+ ", idToken=" + idToken + ", sessionState=" + sessionState + ", refreshExpiresIn=" + refreshExpiresIn
|
||||
+ "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Spring Security configuration.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.security;
|
|
@ -0,0 +1,46 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.AuthorizedClientServiceOAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.core.oidc.user.DefaultOidcUser;
|
||||
import org.springframework.security.web.authentication.WebAuthenticationDetails;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
|
||||
@Service
|
||||
public class ContextService {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(ContextService.class);
|
||||
|
||||
|
||||
|
||||
|
||||
public ArrayList<String> all(){
|
||||
ArrayList<String> scopes=new ArrayList<>();
|
||||
scopes.add("gcube");
|
||||
scopes.add("gcube/devsec");
|
||||
scopes.add("gcube/devsec/devVRE");
|
||||
log.debug("Scopes found: {}", scopes);
|
||||
|
||||
Authentication auth=SecurityContextHolder.getContext().getAuthentication();
|
||||
DefaultOidcUser userDetails = (DefaultOidcUser) auth.getPrincipal();
|
||||
log.debug("UserDetails: {}",userDetails.toString());
|
||||
|
||||
|
||||
WebAuthenticationDetails details=(WebAuthenticationDetails)auth.getDetails();
|
||||
log.debug("Provaci: {}",details);
|
||||
|
||||
String sessionId=RequestContextHolder.currentRequestAttributes().getSessionId();
|
||||
log.debug("SessionId: {}",sessionId);
|
||||
|
||||
|
||||
|
||||
return scopes;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.authorization.utils.manager.SecretManager;
|
||||
import org.gcube.common.authorization.utils.manager.SecretManagerProvider;
|
||||
import org.gcube.common.authorization.utils.secret.JWTSecret;
|
||||
import org.gcube.common.authorization.utils.secret.Secret;
|
||||
import org.gcube.informationsystem.contexts.impl.entities.ContextImpl;
|
||||
import org.gcube.informationsystem.contexts.reference.entities.Context;
|
||||
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClient;
|
||||
import org.gcube.informationsystem.resourceregistry.client.ResourceRegistryClientFactory;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* Service class for managing InformationSystem resources.
|
||||
*/
|
||||
@Service
|
||||
public class InformationSystemService {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(InformationSystemService.class);
|
||||
|
||||
|
||||
public void setUma(String umaToken) throws Exception {
|
||||
log.debug("Set Uma: [umaToken={}]",umaToken);
|
||||
SecretManagerProvider.instance.reset();
|
||||
SecretManager secretManager = new SecretManager();
|
||||
Secret secret = new JWTSecret(umaToken);
|
||||
secretManager.addSecret(secret);
|
||||
secretManager.set();
|
||||
SecretManagerProvider.instance.set(secretManager);
|
||||
|
||||
}
|
||||
|
||||
|
||||
public List<Context> getAllContext(String context) throws Exception {
|
||||
log.debug("GetAllContext: [context={}]",context);
|
||||
ResourceRegistryClient resourceRegistryClient= ResourceRegistryClientFactory.create(context);
|
||||
//List<Context> contexts=new ArrayList<>();
|
||||
//contexts.add(new ContextImpl("/gcube"));
|
||||
|
||||
List<Context>contexts=resourceRegistryClient.getAllContext();
|
||||
log.debug("AllContext: {}",contexts);
|
||||
return contexts;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.Constants;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.security.AuthoritiesConstants;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.dto.AdminUserDTO;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.dto.RealmAccessDTO;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.dto.ResourceAccessDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import com.nimbusds.jose.shaded.json.JSONArray;
|
||||
import com.nimbusds.jose.shaded.json.JSONObject;
|
||||
|
||||
/**
|
||||
* Service class for managing users.
|
||||
*/
|
||||
@Service
|
||||
public class UserService {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(UserService.class);
|
||||
|
||||
/**
|
||||
* Returns the user from an OAuth 2.0 login or resource server with JWT.
|
||||
*
|
||||
* @param authToken the authentication token.
|
||||
* @return the user from the authentication.
|
||||
*/
|
||||
public AdminUserDTO getUserFromAuthentication(AbstractAuthenticationToken authToken) {
|
||||
Map<String, Object> attributes;
|
||||
if (authToken instanceof JwtAuthenticationToken) {
|
||||
logger.debug("AuthToken is a JwtAuthenticationToken");
|
||||
attributes = ((JwtAuthenticationToken) authToken).getTokenAttributes();
|
||||
} else if (authToken instanceof OAuth2AuthenticationToken) {
|
||||
logger.debug("AuthToken is a OAuth2AuthenticationToken");
|
||||
OAuth2AuthenticationToken oauth2Token = ((OAuth2AuthenticationToken) authToken);
|
||||
attributes = oauth2Token.getPrincipal().getAttributes();
|
||||
} else {
|
||||
throw new IllegalArgumentException("AuthenticationToken is not OAuth2 or JWT!");
|
||||
}
|
||||
logger.debug("Attributes: {}", attributes);
|
||||
AdminUserDTO user = getUser(attributes);
|
||||
Set<String> authorities= new HashSet<>();
|
||||
authorities.add(AuthoritiesConstants.ADMIN);
|
||||
user.setAuthorities(authorities);
|
||||
//user.setAuthorities(
|
||||
// authToken.getAuthorities().stream().map(GrantedAuthority::getAuthority).collect(Collectors.toSet()));
|
||||
return user;
|
||||
}
|
||||
|
||||
private static AdminUserDTO getUser(Map<String, Object> details) {
|
||||
AdminUserDTO user = new AdminUserDTO();
|
||||
Boolean activated = Boolean.TRUE;
|
||||
String sub = String.valueOf(details.get("sub"));
|
||||
String username = null;
|
||||
if (details.get("preferred_username") != null) {
|
||||
username = ((String) details.get("preferred_username")).toLowerCase();
|
||||
}
|
||||
// handle resource server JWT, where sub claim is email and uid is ID
|
||||
if (details.get("uid") != null) {
|
||||
user.setId((String) details.get("uid"));
|
||||
user.setLogin(sub);
|
||||
} else {
|
||||
user.setId(sub);
|
||||
}
|
||||
if (username != null) {
|
||||
user.setLogin(username);
|
||||
} else if (user.getLogin() == null) {
|
||||
user.setLogin(user.getId());
|
||||
}
|
||||
if (details.get("given_name") != null) {
|
||||
user.setFirstName((String) details.get("given_name"));
|
||||
} else if (details.get("name") != null) {
|
||||
user.setFirstName((String) details.get("name"));
|
||||
}
|
||||
if (details.get("family_name") != null) {
|
||||
user.setLastName((String) details.get("family_name"));
|
||||
}
|
||||
if (details.get("email_verified") != null) {
|
||||
activated = (Boolean) details.get("email_verified");
|
||||
}
|
||||
if (details.get("email") != null) {
|
||||
user.setEmail(((String) details.get("email")).toLowerCase());
|
||||
} else if (sub.contains("|") && (username != null && username.contains("@"))) {
|
||||
// special handling for Auth0
|
||||
user.setEmail(username);
|
||||
} else {
|
||||
user.setEmail(sub);
|
||||
}
|
||||
if (details.get("langKey") != null) {
|
||||
user.setLangKey((String) details.get("langKey"));
|
||||
} else if (details.get("locale") != null) {
|
||||
// trim off country code if it exists
|
||||
String locale = (String) details.get("locale");
|
||||
if (locale.contains("_")) {
|
||||
locale = locale.substring(0, locale.indexOf('_'));
|
||||
} else if (locale.contains("-")) {
|
||||
locale = locale.substring(0, locale.indexOf('-'));
|
||||
}
|
||||
user.setLangKey(locale.toLowerCase());
|
||||
} else {
|
||||
// set langKey to default if not specified by IdP
|
||||
user.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
}
|
||||
if (details.get("picture") != null) {
|
||||
user.setImageUrl((String) details.get("picture"));
|
||||
}
|
||||
|
||||
if (details.get("realm_access") != null) {
|
||||
//com.nimbusds.jose.shaded.json.
|
||||
JSONObject realmAccessJSON=(JSONObject)details.get("realm_access");
|
||||
JSONArray rolesJSON=(JSONArray)realmAccessJSON.get("roles");
|
||||
ArrayList<String> roles=new ArrayList<>();
|
||||
for(int i=0;i<rolesJSON.size();i++) {
|
||||
roles.add((String)rolesJSON.get(i));
|
||||
}
|
||||
|
||||
RealmAccessDTO realmAccessDTO=new RealmAccessDTO(roles);
|
||||
user.setRealmAccessDTO(realmAccessDTO);
|
||||
}
|
||||
|
||||
if (details.get("resource_access") != null) {
|
||||
JSONObject resourceAccessJSON=(JSONObject)details.get("resource_access");
|
||||
logger.debug("ResourceAccess KeySet: {}",resourceAccessJSON.keySet());
|
||||
LinkedHashMap<String, ArrayList<String>> resourceAccess=new LinkedHashMap<>();
|
||||
for(String key: resourceAccessJSON.keySet()) {
|
||||
JSONObject valueJSON=(JSONObject)resourceAccessJSON.get(key);
|
||||
JSONArray rolesJSON=(JSONArray) valueJSON.get("roles");
|
||||
ArrayList<String> roles=new ArrayList<>();
|
||||
for(int i=0;i<rolesJSON.size();i++) {
|
||||
roles.add((String)rolesJSON.get(i));
|
||||
}
|
||||
resourceAccess.put(key, roles);
|
||||
}
|
||||
ResourceAccessDTO resourceAccessDTO=new ResourceAccessDTO(resourceAccess);
|
||||
user.setResourceAccessDTO(resourceAccessDTO);
|
||||
}
|
||||
|
||||
user.setActivated(activated);
|
||||
return user;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.validation.constraints.Email;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.Constants;
|
||||
|
||||
/**
|
||||
* A DTO representing a user, with his authorities.
|
||||
*/
|
||||
public class AdminUserDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private Set<String> authorities;
|
||||
|
||||
@NotBlank
|
||||
@Pattern(regexp = Constants.LOGIN_REGEX)
|
||||
@Size(min = 1, max = 50)
|
||||
private String login;
|
||||
|
||||
@Size(max = 50)
|
||||
private String firstName;
|
||||
|
||||
@Size(max = 50)
|
||||
private String lastName;
|
||||
|
||||
@Email
|
||||
@Size(min = 5, max = 254)
|
||||
private String email;
|
||||
|
||||
@Size(max = 256)
|
||||
private String imageUrl;
|
||||
|
||||
private boolean activated = false;
|
||||
|
||||
@Size(min = 2, max = 10)
|
||||
private String langKey;
|
||||
|
||||
private RealmAccessDTO realmAccessDTO;
|
||||
|
||||
private ResourceAccessDTO resourceAccessDTO;
|
||||
|
||||
// private Set<String> authorities;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Set<String> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public void setAuthorities(Set<String> authorities) {
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
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 String getEmail() {
|
||||
return email;
|
||||
}
|
||||
|
||||
public void setEmail(String email) {
|
||||
this.email = email;
|
||||
}
|
||||
|
||||
public String getImageUrl() {
|
||||
return imageUrl;
|
||||
}
|
||||
|
||||
public void setImageUrl(String imageUrl) {
|
||||
this.imageUrl = imageUrl;
|
||||
}
|
||||
|
||||
public boolean isActivated() {
|
||||
return activated;
|
||||
}
|
||||
|
||||
public void setActivated(boolean activated) {
|
||||
this.activated = activated;
|
||||
}
|
||||
|
||||
public String getLangKey() {
|
||||
return langKey;
|
||||
}
|
||||
|
||||
public void setLangKey(String langKey) {
|
||||
this.langKey = langKey;
|
||||
}
|
||||
|
||||
public static long getSerialversionuid() {
|
||||
return serialVersionUID;
|
||||
}
|
||||
|
||||
public RealmAccessDTO getRealmAccessDTO() {
|
||||
return realmAccessDTO;
|
||||
}
|
||||
|
||||
public void setRealmAccessDTO(RealmAccessDTO realmAccessDTO) {
|
||||
this.realmAccessDTO = realmAccessDTO;
|
||||
}
|
||||
|
||||
public ResourceAccessDTO getResourceAccessDTO() {
|
||||
return resourceAccessDTO;
|
||||
}
|
||||
|
||||
public void setResourceAccessDTO(ResourceAccessDTO resourceAccessDTO) {
|
||||
this.resourceAccessDTO = resourceAccessDTO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "AdminUserDTO [id=" + id + ", authorities=" + authorities + ", login=" + login + ", firstName="
|
||||
+ firstName + ", lastName=" + lastName + ", email=" + email + ", imageUrl=" + imageUrl + ", activated="
|
||||
+ activated + ", langKey=" + langKey + ", realmAccessDTO=" + realmAccessDTO + ", resourceAccessDTO="
|
||||
+ resourceAccessDTO + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class RealmAccessDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private ArrayList<String> roles;
|
||||
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class ResourceAccessDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private LinkedHashMap<String, ArrayList<String>> resourceAccess;
|
||||
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class TestDialogDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
private String status;
|
||||
}
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class UmaResponseDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private boolean upgraded;
|
||||
private String access_token;
|
||||
private int expires_in;
|
||||
private int refresh_expires_in;
|
||||
private String refresh_token;
|
||||
private String token_type;
|
||||
private int not_before_policy;
|
||||
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* A DTO representing a user, with only the public attributes.
|
||||
*/
|
||||
public class UserDTO implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String id;
|
||||
|
||||
private String login;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
|
||||
public void setLogin(String login) {
|
||||
this.login = login;
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
@Override
|
||||
public String toString() {
|
||||
return "UserDTO{" +
|
||||
"id='" + id + '\'' +
|
||||
", login='" + login + '\'' +
|
||||
"}";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Data Transfer Objects.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.service.dto;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Service layer beans.
|
||||
*/
|
||||
package org.gcube.fullstackapps.informationsystemmonitor.service;
|
|
@ -0,0 +1,87 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientManager;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
|
||||
import org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizationRequestResolver;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestRedirectFilter;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizationRequestResolver;
|
||||
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
|
||||
import org.springframework.security.oauth2.core.endpoint.OAuth2AuthorizationRequest;
|
||||
import org.springframework.security.web.DefaultRedirectStrategy;
|
||||
import org.springframework.security.web.RedirectStrategy;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
/**
|
||||
* Refresh oauth2 tokens.
|
||||
*/
|
||||
@Component
|
||||
public class OAuth2RefreshTokensWebFilter extends OncePerRequestFilter {
|
||||
|
||||
private final OAuth2AuthorizedClientManager clientManager;
|
||||
private final OAuth2AuthorizedClientRepository authorizedClientRepository;
|
||||
private final OAuth2AuthorizationRequestResolver authorizationRequestResolver;
|
||||
private final RedirectStrategy authorizationRedirectStrategy = new DefaultRedirectStrategy();
|
||||
|
||||
public OAuth2RefreshTokensWebFilter(
|
||||
OAuth2AuthorizedClientManager clientManager,
|
||||
OAuth2AuthorizedClientRepository authorizedClientRepository,
|
||||
ClientRegistrationRepository clientRegistrationRepository
|
||||
) {
|
||||
this.clientManager = clientManager;
|
||||
this.authorizedClientRepository = authorizedClientRepository;
|
||||
this.authorizationRequestResolver =
|
||||
new DefaultOAuth2AuthorizationRequestResolver(
|
||||
clientRegistrationRepository,
|
||||
OAuth2AuthorizationRequestRedirectFilter.DEFAULT_AUTHORIZATION_REQUEST_BASE_URI
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
|
||||
|
||||
if ((authentication instanceof OAuth2AuthenticationToken)) {
|
||||
try {
|
||||
OAuth2AuthorizedClient authorizedClient = authorizedClient((OAuth2AuthenticationToken) authentication);
|
||||
//logger.debug("Oauth2RefreshTokensWebFilter: "+authorizedClient.getRefreshToken().getTokenValue());
|
||||
this.authorizedClientRepository.saveAuthorizedClient(authorizedClient, authentication, request, response);
|
||||
} catch (Exception e) {
|
||||
OAuth2AuthorizationRequest authorizationRequest = this.authorizationRequestResolver.resolve(request);
|
||||
if (authorizationRequest != null) {
|
||||
this.authorizationRedirectStrategy.sendRedirect(request, response, authorizationRequest.getAuthorizationRequestUri());
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
|
||||
private OAuth2AuthorizedClient authorizedClient(OAuth2AuthenticationToken oauth2Authentication) {
|
||||
String clientRegistrationId = oauth2Authentication.getAuthorizedClientRegistrationId();
|
||||
OAuth2AuthorizeRequest request = OAuth2AuthorizeRequest
|
||||
.withClientRegistrationId(clientRegistrationId)
|
||||
.principal(oauth2Authentication)
|
||||
.build();
|
||||
if (clientManager == null) {
|
||||
throw new IllegalStateException(
|
||||
"No OAuth2AuthorizedClientManager bean was found. Did you include the " +
|
||||
"org.springframework.boot:spring-boot-starter-oauth2-client dependency?"
|
||||
);
|
||||
}
|
||||
return clientManager.authorize(request);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.rest;
|
||||
|
||||
import java.security.Principal;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.TokenManager;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.UserService;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.dto.AdminUserDTO;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.authentication.AbstractAuthenticationToken;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* REST controller for managing the current user's account.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
@RequiredArgsConstructor
|
||||
public class AccountResource {
|
||||
|
||||
private static class AccountResourceException extends RuntimeException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private AccountResourceException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(AccountResource.class);
|
||||
|
||||
private final TokenManager umaManager;
|
||||
private final UserService userService;
|
||||
|
||||
/**
|
||||
* {@code GET /account} : get the current user.
|
||||
*
|
||||
* @param principal the current user; resolves to {@code null} if not authenticated.
|
||||
* @return the current user.
|
||||
* @throws AccountResourceException {@code 500 (Internal Server Error)} if the user couldn't be returned.
|
||||
*/
|
||||
@GetMapping("/account")
|
||||
public AdminUserDTO getAccount(Principal principal) {
|
||||
if (principal instanceof AbstractAuthenticationToken) {
|
||||
return userService.getUserFromAuthentication((AbstractAuthenticationToken) principal);
|
||||
} else {
|
||||
throw new AccountResourceException("User could not be found");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@code GET /authenticate} : check if the user is authenticated, and return its login.
|
||||
*
|
||||
* @param request the HTTP request.
|
||||
* @return the login if the user is authenticated.
|
||||
*/
|
||||
@GetMapping("/authenticate")
|
||||
public String isAuthenticated(HttpServletRequest request) {
|
||||
log.debug("REST request to check if the current user is authenticated");
|
||||
return request.getRemoteUser();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/idtoken")
|
||||
public String idtoken(OAuth2AuthenticationToken token) {
|
||||
log.debug("REST request to check token: {}",token);
|
||||
return token.toString();
|
||||
}
|
||||
|
||||
@GetMapping("/accesstoken")
|
||||
public String accesstoken() {
|
||||
log.debug("Request access token");
|
||||
String accessToken=umaManager.getAccessToken();
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/umatoken")
|
||||
public String umatoken() {
|
||||
log.debug("Request uma token");
|
||||
String context=UriUtils.encode("/gcube", "UTF-8");
|
||||
String umaToken=umaManager.getUmaToken(context);
|
||||
return umaToken;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.rest;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Resource to return information about OIDC properties
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class AuthInfoResource {
|
||||
|
||||
@Value("${spring.security.oauth2.client.provider.oidc.issuer-uri:}")
|
||||
private String issuer;
|
||||
|
||||
@Value("${spring.security.oauth2.client.registration.oidc.client-id:}")
|
||||
private String clientId;
|
||||
|
||||
@GetMapping("/auth-info")
|
||||
public AuthInfoVM getAuthInfo() {
|
||||
return new AuthInfoVM(issuer, clientId);
|
||||
}
|
||||
|
||||
class AuthInfoVM {
|
||||
|
||||
private String issuer;
|
||||
private String clientId;
|
||||
|
||||
AuthInfoVM(String issuer, String clientId) {
|
||||
this.issuer = issuer;
|
||||
this.clientId = clientId;
|
||||
}
|
||||
|
||||
public String getIssuer() {
|
||||
return this.issuer;
|
||||
}
|
||||
|
||||
public void setIssuer(String issuer) {
|
||||
this.issuer = issuer;
|
||||
}
|
||||
|
||||
public String getClientId() {
|
||||
return clientId;
|
||||
}
|
||||
|
||||
public void setClientId(String clientId) {
|
||||
this.clientId = clientId;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.rest;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class ClientForwardController {
|
||||
|
||||
/**
|
||||
* Forwards any unmapped paths (except those containing a period) to the client {@code index.html}.
|
||||
* @return forward to client {@code index.html}.
|
||||
*/
|
||||
@GetMapping(value = "/**/{path:[^\\.]*}")
|
||||
public String forward() {
|
||||
return "forward:/";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.rest;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.ContextService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
|
||||
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
|
||||
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* ScopesDiscoveryResource controller
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/context")
|
||||
@RequiredArgsConstructor
|
||||
public class ContextResource {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(ContextResource.class);
|
||||
|
||||
private final ContextService contextService;
|
||||
|
||||
private final OAuth2AuthorizedClientService authorizedClientService;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* GET all
|
||||
*/
|
||||
@GetMapping("/all")
|
||||
public ArrayList<String> all() {
|
||||
log.debug("Request Scope Discovery");
|
||||
OAuth2AuthenticationToken oAuth2AuthenticationToken=(OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
|
||||
log.debug("OAuth2AuthenticationToken: {}",oAuth2AuthenticationToken);
|
||||
|
||||
OAuth2AuthorizedClient client = authorizedClientService
|
||||
.loadAuthorizedClient(oAuth2AuthenticationToken.getAuthorizedClientRegistrationId(), oAuth2AuthenticationToken.getName());
|
||||
log.debug("AccessToken: {}",client.getAccessToken().getTokenValue());
|
||||
|
||||
/*String userInfoEndpointUri = client.getClientRegistration().getProviderDetails().getUserInfoEndpoint().getUri();
|
||||
|
||||
if (!StringUtils.isEmpty(userInfoEndpointUri)) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add(HttpHeaders.AUTHORIZATION, "Bearer " + client.getAccessToken().getTokenValue());
|
||||
HttpEntity entity = new HttpEntity("", headers);
|
||||
|
||||
RestTemplate restTemplate = new RestTemplate();
|
||||
ResponseEntity<Map> response = restTemplate.exchange(userInfoEndpointUri, HttpMethod.GET, entity, Map.class);
|
||||
Map userAttributes = response.getBody();
|
||||
|
||||
model.addAttribute("name", userAttributes.get("name"));
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
return contextService.all();
|
||||
}
|
||||
|
||||
@GetMapping("/encode")
|
||||
public String encodeContext() {
|
||||
String contextEncoded=UriUtils.encode("/gcube", "UTF-8");
|
||||
return contextEncoded;
|
||||
}
|
||||
|
||||
@GetMapping("/decode")
|
||||
public String decodeContext() {
|
||||
String contextEncoded=UriUtils.decode("%2Fgcube", "UTF-8");
|
||||
return contextEncoded;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.gcube.fullstackapps.informationsystemmonitor.web.rest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.config.TokenManager;
|
||||
import org.gcube.fullstackapps.informationsystemmonitor.service.InformationSystemService;
|
||||
import org.gcube.informationsystem.contexts.reference.entities.Context;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.util.UriUtils;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import tech.jhipster.web.util.HeaderUtil;
|
||||
|
||||
/**
|
||||
* REST controller for managing the current user's account.
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/api/is")
|
||||
@RequiredArgsConstructor
|
||||
public class InformationSystemResource {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(InformationSystemResource.class);
|
||||
|
||||
@Value("${jhipster.clientApp.name}")
|
||||
private String applicationName;
|
||||
|
||||
private final TokenManager tokenManager;
|
||||
private final InformationSystemService informationSystemService;
|
||||
|
||||
@GetMapping("/allcontext")
|
||||
public ResponseEntity<String> allcontext() {
|
||||
log.debug("Request uma token");
|
||||
String rootContext = tokenManager.getRootContext();
|
||||
String contextEncoded = UriUtils.encode(rootContext, "UTF-8");
|
||||
String umaToken = tokenManager.getUmaToken(contextEncoded);
|
||||
|
||||
try {
|
||||
informationSystemService.setUma(umaToken);
|
||||
List<Context> contexts = informationSystemService.getAllContext(rootContext);
|
||||
ObjectMapper om = new ObjectMapper();
|
||||
String sc = om.writeValueAsString(contexts);
|
||||
return ResponseEntity.ok().body(sc);
|
||||
|
||||
//return new ResponseEntity<List<Context>>(contexts, HttpStatus.OK);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getLocalizedMessage(), e);
|
||||
return ResponseEntity.noContent()
|
||||
.headers(HeaderUtil.createAlert(applicationName, e.getLocalizedMessage(), "")).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue