Initial version of isdashboard generated by generator-jhipster@8.0.0-beta.2
This commit is contained in:
commit
abca9cf59e
|
@ -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): 17, 17-bullseye, 17-buster
|
||||
ARG VARIANT="17"
|
||||
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,53 @@
|
|||
// 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": "Isdashboard",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile",
|
||||
"args": {
|
||||
// Update the VARIANT arg to pick a Java version: 17, 19
|
||||
// Append -bullseye or -buster to pin to an OS version.
|
||||
// Use the -bullseye variants on local arm64/Apple Silicon.
|
||||
"VARIANT": "17-bullseye",
|
||||
// Options
|
||||
// maven and gradle wrappers are used by default, we don't need them installed globally
|
||||
// "INSTALL_MAVEN": "true",
|
||||
// "INSTALL_GRADLE": "false",
|
||||
"NODE_VERSION": "18.16.1"
|
||||
}
|
||||
},
|
||||
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
// Set *default* container specific settings.json values on container create.
|
||||
"settings": {
|
||||
"java.jdt.ls.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,9 @@
|
|||
node_modules/
|
||||
src/main/docker/
|
||||
jest.conf.js
|
||||
webpack/
|
||||
target/
|
||||
build/
|
||||
node/
|
||||
coverage/
|
||||
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,150 @@
|
|||
# This file is inspired by https://github.com/alexkaratarakis/gitattributes
|
||||
#
|
||||
# Auto detect text files and perform LF normalization
|
||||
# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
|
||||
* text=auto
|
||||
|
||||
# The above will handle all files NOT found below
|
||||
# These files are text and should be normalized (Convert crlf => lf)
|
||||
|
||||
*.bat text eol=crlf
|
||||
*.cmd text eol=crlf
|
||||
*.ps1 text eol=crlf
|
||||
*.coffee text
|
||||
*.css text
|
||||
*.cql text
|
||||
*.df text
|
||||
*.ejs text
|
||||
*.html text
|
||||
*.java text
|
||||
*.js text
|
||||
*.json text
|
||||
*.less text
|
||||
*.properties text
|
||||
*.sass text
|
||||
*.scss text
|
||||
*.sh text eol=lf
|
||||
*.sql text
|
||||
*.txt text
|
||||
*.ts text
|
||||
*.xml text
|
||||
*.yaml text
|
||||
*.yml text
|
||||
|
||||
# Documents
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
*.markdown text
|
||||
*.md text
|
||||
*.adoc text
|
||||
*.textile text
|
||||
*.mustache text
|
||||
*.csv text
|
||||
*.tab text
|
||||
*.tsv text
|
||||
*.txt text
|
||||
AUTHORS text
|
||||
CHANGELOG text
|
||||
CHANGES text
|
||||
CONTRIBUTING text
|
||||
COPYING text
|
||||
copyright text
|
||||
*COPYRIGHT* text
|
||||
INSTALL text
|
||||
license text
|
||||
LICENSE text
|
||||
NEWS text
|
||||
readme text
|
||||
*README* text
|
||||
TODO text
|
||||
|
||||
# Graphics
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.tif binary
|
||||
*.tiff binary
|
||||
*.ico binary
|
||||
# SVG treated as an asset (binary) by default. If you want to treat it as text,
|
||||
# comment-out the following line and uncomment the line after.
|
||||
*.svg binary
|
||||
#*.svg text
|
||||
*.eps binary
|
||||
|
||||
# These files are binary and should be left untouched
|
||||
# (binary is a macro for -text -diff)
|
||||
*.class binary
|
||||
*.jar binary
|
||||
*.war binary
|
||||
|
||||
## LINTERS
|
||||
.csslintrc text
|
||||
.eslintrc text
|
||||
.jscsrc text
|
||||
.jshintrc text
|
||||
.jshintignore text
|
||||
.stylelintrc text
|
||||
|
||||
## CONFIGS
|
||||
*.conf text
|
||||
*.config text
|
||||
.editorconfig text
|
||||
.gitattributes text
|
||||
.gitconfig text
|
||||
.gitignore text
|
||||
.htaccess text
|
||||
*.npmignore text
|
||||
|
||||
## HEROKU
|
||||
Procfile text
|
||||
.slugignore text
|
||||
|
||||
## AUDIO
|
||||
*.kar binary
|
||||
*.m4a binary
|
||||
*.mid binary
|
||||
*.midi binary
|
||||
*.mp3 binary
|
||||
*.ogg binary
|
||||
*.ra binary
|
||||
|
||||
## VIDEO
|
||||
*.3gpp binary
|
||||
*.3gp binary
|
||||
*.as binary
|
||||
*.asf binary
|
||||
*.asx binary
|
||||
*.fla binary
|
||||
*.flv binary
|
||||
*.m4v binary
|
||||
*.mng binary
|
||||
*.mov binary
|
||||
*.mp4 binary
|
||||
*.mpeg binary
|
||||
*.mpg binary
|
||||
*.swc binary
|
||||
*.swf binary
|
||||
*.webm binary
|
||||
|
||||
## ARCHIVES
|
||||
*.7z binary
|
||||
*.gz binary
|
||||
*.rar binary
|
||||
*.tar binary
|
||||
*.zip binary
|
||||
|
||||
## FONTS
|
||||
*.ttf binary
|
||||
*.eot binary
|
||||
*.otf binary
|
||||
*.woff binary
|
||||
*.woff2 binary
|
|
@ -0,0 +1,151 @@
|
|||
######################
|
||||
# Node
|
||||
######################
|
||||
/node/
|
||||
node_tmp/
|
||||
node_modules/
|
||||
npm-debug.log.*
|
||||
/.awcache/*
|
||||
/.cache-loader/*
|
||||
|
||||
######################
|
||||
# SASS
|
||||
######################
|
||||
.sass-cache/
|
||||
|
||||
######################
|
||||
# Eclipse
|
||||
######################
|
||||
*.pydevproject
|
||||
.project
|
||||
.metadata
|
||||
tmp/
|
||||
tmp/**/*
|
||||
*.tmp
|
||||
*.bak
|
||||
*.swp
|
||||
*~.nib
|
||||
local.properties
|
||||
.classpath
|
||||
.settings/
|
||||
.loadpath
|
||||
.factorypath
|
||||
|
||||
# External tool builders
|
||||
.externalToolBuilders/**
|
||||
|
||||
# Locally stored "Eclipse launch configurations"
|
||||
*.launch
|
||||
|
||||
# CDT-specific
|
||||
.cproject
|
||||
|
||||
# PDT-specific
|
||||
.buildpath
|
||||
|
||||
# STS-specific
|
||||
/.sts4-cache/*
|
||||
|
||||
######################
|
||||
# IntelliJ
|
||||
######################
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
*.ids
|
||||
*.orig
|
||||
classes/
|
||||
out/
|
||||
|
||||
######################
|
||||
# Visual Studio Code
|
||||
######################
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
*.code-workspace
|
||||
|
||||
######################
|
||||
# Maven
|
||||
######################
|
||||
/log/
|
||||
/target/
|
||||
|
||||
######################
|
||||
# Gradle
|
||||
######################
|
||||
.gradle/
|
||||
/build/
|
||||
|
||||
######################
|
||||
# Package Files
|
||||
######################
|
||||
*.jar
|
||||
*.war
|
||||
*.ear
|
||||
*.db
|
||||
|
||||
######################
|
||||
# Windows
|
||||
######################
|
||||
# Windows image file caches
|
||||
Thumbs.db
|
||||
|
||||
# Folder config file
|
||||
Desktop.ini
|
||||
|
||||
######################
|
||||
# Mac OSX
|
||||
######################
|
||||
.DS_Store
|
||||
.svn
|
||||
|
||||
# Thumbnails
|
||||
._*
|
||||
|
||||
# Files that might appear on external disk
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
|
||||
######################
|
||||
# Directories
|
||||
######################
|
||||
/bin/
|
||||
/deploy/
|
||||
|
||||
######################
|
||||
# Logs
|
||||
######################
|
||||
*.log*
|
||||
|
||||
######################
|
||||
# Others
|
||||
######################
|
||||
*.class
|
||||
*.*~
|
||||
*~
|
||||
.merge_file*
|
||||
|
||||
######################
|
||||
# Gradle Wrapper
|
||||
######################
|
||||
!gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
######################
|
||||
# Maven Wrapper
|
||||
######################
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################
|
||||
# ESLint
|
||||
######################
|
||||
.eslintcache
|
||||
|
||||
######################
|
||||
# Code coverage
|
||||
######################
|
||||
/coverage/
|
||||
/.nyc_output/
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
|
||||
"$(dirname "$0")/../npmw" exec --no-install lint-staged
|
|
@ -0,0 +1,3 @@
|
|||
module.exports = {
|
||||
'{,src/**/,webpack/}*.{md,json,yml,html,cjs,mjs,js,ts,tsx,css,scss,java}': ['prettier --write'],
|
||||
};
|
|
@ -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
|
||||
#
|
||||
# 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.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.2/apache-maven-3.9.2-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.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,46 @@
|
|||
{
|
||||
"generator-jhipster": {
|
||||
"applicationType": "monolith",
|
||||
"authenticationType": "session",
|
||||
"baseName": "isdashboard",
|
||||
"buildTool": "maven",
|
||||
"cacheProvider": "ehcache",
|
||||
"clientFramework": "angular",
|
||||
"clientTheme": "none",
|
||||
"creationTimestamp": 1690967932750,
|
||||
"databaseType": "no",
|
||||
"devDatabaseType": "no",
|
||||
"devServerPort": 4200,
|
||||
"dtoSuffix": "DTO",
|
||||
"enableGradleEnterprise": null,
|
||||
"enableHibernateCache": false,
|
||||
"enableSwaggerCodegen": false,
|
||||
"enableTranslation": false,
|
||||
"entities": [],
|
||||
"entitySuffix": "",
|
||||
"gradleEnterpriseHost": null,
|
||||
"jhiPrefix": "jhi",
|
||||
"jhipsterVersion": "8.0.0-beta.2",
|
||||
"messageBroker": false,
|
||||
"microfrontend": false,
|
||||
"microfrontends": [],
|
||||
"nativeLanguage": "en",
|
||||
"packageFolder": "org/gcube/isdashboard",
|
||||
"packageName": "org.gcube.isdashboard",
|
||||
"pages": [],
|
||||
"prodDatabaseType": "no",
|
||||
"reactive": false,
|
||||
"rememberMeKey": "6038bcb93c3f8cc61c163e71aa55573477e46c3535cf0624212567f396b89e7be83d90b03885a818d14b1b7f4928ab548561",
|
||||
"searchEngine": false,
|
||||
"serverPort": null,
|
||||
"serverSideOptions": [],
|
||||
"serviceDiscoveryType": false,
|
||||
"skipCheckLengthOfIdentifier": false,
|
||||
"skipClient": false,
|
||||
"skipFakeData": false,
|
||||
"skipUserManagement": true,
|
||||
"testFrameworks": [],
|
||||
"websocket": false,
|
||||
"withAdminUi": false
|
||||
}
|
||||
}
|
|
@ -0,0 +1,246 @@
|
|||
# isdashboard
|
||||
|
||||
This application was generated using JHipster 8.0.0-beta.2, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2](https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2).
|
||||
|
||||
## 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
|
||||
```
|
||||
|
||||
## Building for production
|
||||
|
||||
### Packaging as jar
|
||||
|
||||
To build the final jar and optimize the isdashboard 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 forced authentication redirect for UI 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 -Dsonar.login=admin -Dsonar.password=admin
|
||||
```
|
||||
|
||||
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 -Dsonar.login=admin -Dsonar.password=admin
|
||||
```
|
||||
|
||||
Additionally, Instead of passing `sonar.password` and `sonar.login` as CLI arguments, these parameters can be configured from [sonar-project.properties](sonar-project.properties) as shown below:
|
||||
|
||||
```
|
||||
sonar.login=admin
|
||||
sonar.password=admin
|
||||
```
|
||||
|
||||
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 8.0.0-beta.2 archive]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2
|
||||
[Using JHipster in development]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/development/
|
||||
[Using Docker and Docker-Compose]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/docker-compose
|
||||
[Using JHipster in production]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/production/
|
||||
[Running tests page]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/running-tests/
|
||||
[Code quality page]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/code-quality/
|
||||
[Setting up Continuous Integration]: https://www.jhipster.tech/documentation-archive/v8.0.0-beta.2/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/
|
|
@ -0,0 +1,109 @@
|
|||
{
|
||||
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||||
"version": 1,
|
||||
"newProjectRoot": "projects",
|
||||
"projects": {
|
||||
"isdashboard": {
|
||||
"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": ["zone.js"],
|
||||
"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": "isdashboard:build:development",
|
||||
"port": 4200
|
||||
},
|
||||
"configurations": {
|
||||
"production": {
|
||||
"browserTarget": "isdashboard:build:production"
|
||||
},
|
||||
"development": {
|
||||
"browserTarget": "isdashboard: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,308 @@
|
|||
#!/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.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# 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
|
||||
JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
|
||||
else
|
||||
JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=$(java-config --jre-home)
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -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 "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); 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 2>/dev/null; \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
|
||||
|
||||
# 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/.." || exit 1; pwd)
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
printf '%s' "$(cd "$basedir" || exit 1; pwd)"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
# Remove \r in case we run on Windows within Git Bash
|
||||
# and check out the repository with auto CRLF management
|
||||
# enabled. Otherwise, we may read lines that are delimited with
|
||||
# \r\n and produce $'-Xarg\r' rather than -Xarg due to word
|
||||
# splitting rules.
|
||||
tr -s '\r\n' ' ' < "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
log() {
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
printf '%s\n' "$1"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
|
||||
log "$MAVEN_PROJECTBASEDIR"
|
||||
|
||||
##########################################################################################
|
||||
# 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.
|
||||
##########################################################################################
|
||||
wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if [ -r "$wrapperJarPath" ]; then
|
||||
log "Found $wrapperJarPath"
|
||||
else
|
||||
log "Couldn't find $wrapperJarPath, downloading it ..."
|
||||
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
else
|
||||
wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
fi
|
||||
while IFS="=" read -r key value; do
|
||||
# Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
|
||||
safeValue=$(echo "$value" | tr -d '\r')
|
||||
case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
log "Downloading from: $wrapperUrl"
|
||||
|
||||
if $cygwin; then
|
||||
wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
log "Found wget ... using wget"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
else
|
||||
wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
log "Found curl ... using curl"
|
||||
[ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
else
|
||||
curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
else
|
||||
log "Falling back to using Java to download"
|
||||
javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaSource=$(cygpath --path --windows "$javaSource")
|
||||
javaClass=$(cygpath --path --windows "$javaClass")
|
||||
fi
|
||||
if [ -e "$javaSource" ]; then
|
||||
if [ ! -e "$javaClass" ]; then
|
||||
log " - Compiling MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/javac" "$javaSource")
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
log " - Running MavenWrapperDownloader.java ..."
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
# If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
wrapperSha256Sum=""
|
||||
while IFS="=" read -r key value; do
|
||||
case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
|
||||
esac
|
||||
done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ -n "$wrapperSha256Sum" ]; then
|
||||
wrapperSha256Result=false
|
||||
if command -v sha256sum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
elif command -v shasum > /dev/null; then
|
||||
if echo "$wrapperSha256Sum $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
|
||||
wrapperSha256Result=true
|
||||
fi
|
||||
else
|
||||
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
|
||||
echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
|
||||
exit 1
|
||||
fi
|
||||
if [ $wrapperSha256Result = false ]; then
|
||||
echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
|
||||
echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
|
||||
echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
|
||||
exit 1
|
||||
fi
|
||||
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 "$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
|
||||
|
||||
# shellcheck disable=SC2086 # safe args
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
$MAVEN_DEBUG_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
|
@ -0,0 +1,205 @@
|
|||
@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 Apache Maven Wrapper startup batch script, version 3.2.0
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@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 WRAPPER_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET WRAPPER_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 WRAPPER_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %WRAPPER_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('%WRAPPER_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM If specified, validate the SHA-256 sum of the Maven wrapper jar file
|
||||
SET WRAPPER_SHA_256_SUM=""
|
||||
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperSha256Sum" SET WRAPPER_SHA_256_SUM=%%B
|
||||
)
|
||||
IF NOT %WRAPPER_SHA_256_SUM%=="" (
|
||||
powershell -Command "&{"^
|
||||
"$hash = (Get-FileHash \"%WRAPPER_JAR%\" -Algorithm SHA256).Hash.ToLower();"^
|
||||
"If('%WRAPPER_SHA_256_SUM%' -ne $hash){"^
|
||||
" Write-Output 'Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised.';"^
|
||||
" Write-Output 'Investigate or delete %WRAPPER_JAR% to attempt a clean download.';"^
|
||||
" Write-Output 'If you updated your Maven version, you need to update the specified wrapperSha256Sum property.';"^
|
||||
" exit 1;"^
|
||||
"}"^
|
||||
"}"
|
||||
if ERRORLEVEL 1 goto error
|
||||
)
|
||||
|
||||
@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 %*
|
||||
)
|
|
@ -0,0 +1,138 @@
|
|||
{
|
||||
"name": "isdashboard",
|
||||
"version": "0.0.1-SNAPSHOT",
|
||||
"private": true,
|
||||
"description": "Description for Isdashboard",
|
||||
"license": "UNLICENSED",
|
||||
"scripts": {
|
||||
"app:start": "./mvnw",
|
||||
"app:up": "docker compose -f src/main/docker/app.yml up --wait",
|
||||
"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.tech.jhipster=OFF -Dlogging.level.org.gcube.isdashboard=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 services:up --if-present && docker ps -a",
|
||||
"preci:e2e:server:start": "npm run services:db:await --if-present && npm run services: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.tech.jhipster=OFF -Dlogging.level.org.gcube.isdashboard=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 --if-present",
|
||||
"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:db:up": "echo \"Docker for db no not configured for application isdashboard\"",
|
||||
"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",
|
||||
"prepare": "husky install",
|
||||
"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": "16.1.4",
|
||||
"@angular/compiler": "16.1.4",
|
||||
"@angular/core": "16.1.4",
|
||||
"@angular/forms": "16.1.4",
|
||||
"@angular/localize": "16.1.4",
|
||||
"@angular/platform-browser": "16.1.4",
|
||||
"@angular/platform-browser-dynamic": "16.1.4",
|
||||
"@angular/router": "16.1.4",
|
||||
"@fortawesome/angular-fontawesome": "0.13.0",
|
||||
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@ng-bootstrap/ng-bootstrap": "15.1.0",
|
||||
"@popperjs/core": "2.11.8",
|
||||
"bootstrap": "5.3.0",
|
||||
"dayjs": "1.11.9",
|
||||
"ngx-infinite-scroll": "16.0.0",
|
||||
"rxjs": "7.8.1",
|
||||
"tslib": "2.6.0",
|
||||
"zone.js": "0.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular-builders/custom-webpack": "16.0.0",
|
||||
"@angular-builders/jest": "16.0.0",
|
||||
"@angular-devkit/build-angular": "16.1.4",
|
||||
"@angular-eslint/eslint-plugin": "16.0.2",
|
||||
"@angular/cli": "16.1.4",
|
||||
"@angular/compiler-cli": "16.1.4",
|
||||
"@angular/service-worker": "16.1.4",
|
||||
"@types/jest": "29.5.3",
|
||||
"@types/node": "18.16.19",
|
||||
"@typescript-eslint/eslint-plugin": "5.61.0",
|
||||
"@typescript-eslint/parser": "5.61.0",
|
||||
"browser-sync": "2.29.3",
|
||||
"browser-sync-webpack-plugin": "2.3.0",
|
||||
"concurrently": "8.2.0",
|
||||
"copy-webpack-plugin": "11.0.0",
|
||||
"eslint": "8.44.0",
|
||||
"eslint-config-prettier": "8.8.0",
|
||||
"eslint-webpack-plugin": "4.0.1",
|
||||
"generator-jhipster": "8.0.0-beta.2",
|
||||
"husky": "8.0.3",
|
||||
"jest": "29.6.1",
|
||||
"jest-date-mock": "1.0.8",
|
||||
"jest-environment-jsdom": "29.6.1",
|
||||
"jest-junit": "16.0.0",
|
||||
"jest-preset-angular": "13.1.1",
|
||||
"jest-sonar": "0.2.16",
|
||||
"lint-staged": "13.2.3",
|
||||
"prettier": "2.8.8",
|
||||
"prettier-plugin-java": "2.2.0",
|
||||
"prettier-plugin-packagejson": "2.4.5",
|
||||
"rimraf": "5.0.1",
|
||||
"swagger-ui-dist": "5.1.0",
|
||||
"ts-jest": "29.1.1",
|
||||
"typescript": "5.1.6",
|
||||
"wait-on": "7.0.1",
|
||||
"webpack-bundle-analyzer": "4.9.0",
|
||||
"webpack-merge": "5.9.0",
|
||||
"webpack-notifier": "1.15.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.16.1"
|
||||
},
|
||||
"cacheDirectories": [
|
||||
"node_modules"
|
||||
],
|
||||
"overrides": {
|
||||
"webpack": "5.88.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
sonar.projectKey=isdashboard
|
||||
sonar.projectName=isdashboard 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,18 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
name: isdashboard
|
||||
services:
|
||||
app:
|
||||
image: isdashboard
|
||||
environment:
|
||||
- _JAVA_OPTIONS=-Xmx512m -Xms256m
|
||||
- SPRING_PROFILES_ACTIVE=prod,api-docs
|
||||
- MANAGEMENT_PROMETHEUS_METRICS_EXPORT_ENABLED=true
|
||||
# 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
|
||||
healthcheck:
|
||||
test: ['CMD', 'curl', '-f', 'http://localhost:8080/management/health']
|
||||
interval: 5s
|
||||
timeout: 5s
|
||||
retries: 40
|
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,48 @@
|
|||
## 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.
|
||||
|
||||
name: isdashboard
|
||||
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
|
||||
- SPRING_CLOUD_DISCOVERY_CLIENT_SIMPLE_INSTANCES_ISDASHBOARD_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.isdashboard.IsdashboardApp" "$@"
|
|
@ -0,0 +1,31 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
name: isdashboard
|
||||
services:
|
||||
prometheus:
|
||||
image: prom/prometheus:v2.45.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
|
||||
grafana:
|
||||
image: grafana/grafana:10.0.2
|
||||
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
|
|
@ -0,0 +1,15 @@
|
|||
# This configuration is intended for development purpose, it's **your** responsibility to harden it for production
|
||||
name: isdashboard
|
||||
services:
|
||||
sonar:
|
||||
container_name: sonarqube
|
||||
image: sonarqube:10.1.0-community
|
||||
# Forced authentication redirect for UI 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
|
||||
- 127.0.0.1:9000:9000
|
|
@ -0,0 +1,19 @@
|
|||
package org.gcube.isdashboard;
|
||||
|
||||
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(IsdashboardApp.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.gcube.isdashboard;
|
||||
|
||||
import jakarta.annotation.Generated;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Generated(value = "JHipster", comments = "Generated by JHipster 8.0.0-beta.2")
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@Target({ ElementType.TYPE })
|
||||
public @interface GeneratedByJHipster {
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
package org.gcube.isdashboard;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.gcube.isdashboard.config.ApplicationProperties;
|
||||
import org.gcube.isdashboard.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 IsdashboardApp {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(IsdashboardApp.class);
|
||||
|
||||
private final Environment env;
|
||||
|
||||
public IsdashboardApp(Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes isdashboard.
|
||||
* <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(IsdashboardApp.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,
|
||||
"""
|
||||
|
||||
----------------------------------------------------------
|
||||
\tApplication '{}' is running! Access URLs:
|
||||
\tLocal: \t\t{}://localhost:{}{}
|
||||
\tExternal: \t{}://{}:{}{}
|
||||
\tProfile(s): \t{}
|
||||
----------------------------------------------------------""",
|
||||
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.isdashboard.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.isdashboard.repository..*)" +
|
||||
" || within(org.gcube.isdashboard.service..*)" +
|
||||
" || within(org.gcube.isdashboard.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,4 @@
|
|||
/**
|
||||
* Logging aspect.
|
||||
*/
|
||||
package org.gcube.isdashboard.aop.logging;
|
|
@ -0,0 +1,16 @@
|
|||
package org.gcube.isdashboard.config;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Properties specific to Isdashboard.
|
||||
* <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.isdashboard.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,67 @@
|
|||
package org.gcube.isdashboard.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;
|
||||
|
||||
/**
|
||||
* Log filter to prevent attackers from forging log entries by submitting input containing CRLF characters.
|
||||
* CRLF characters are replaced with a red colored _ character.
|
||||
*
|
||||
* @see <a href="https://owasp.org/www-community/attacks/Log_Injection">Log Forging Description</a>
|
||||
* @see <a href="https://github.com/jhipster/generator-jhipster/issues/14949">JHipster issue</a>
|
||||
*/
|
||||
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",
|
||||
"org.springframework.boot.autoconfigure",
|
||||
"org.springframework.boot.diagnostics",
|
||||
};
|
||||
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,66 @@
|
|||
package org.gcube.isdashboard.config;
|
||||
|
||||
import java.time.Duration;
|
||||
import org.ehcache.config.builders.*;
|
||||
import org.ehcache.jsr107.Eh107Configuration;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
|
||||
import org.springframework.boot.info.BuildProperties;
|
||||
import org.springframework.boot.info.GitProperties;
|
||||
import org.springframework.cache.annotation.EnableCaching;
|
||||
import org.springframework.cache.interceptor.KeyGenerator;
|
||||
import org.springframework.context.annotation.*;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
import tech.jhipster.config.cache.PrefixedKeyGenerator;
|
||||
|
||||
@Configuration
|
||||
@EnableCaching
|
||||
public class CacheConfiguration {
|
||||
|
||||
private GitProperties gitProperties;
|
||||
private BuildProperties buildProperties;
|
||||
private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration;
|
||||
|
||||
public CacheConfiguration(JHipsterProperties jHipsterProperties) {
|
||||
JHipsterProperties.Cache.Ehcache ehcache = jHipsterProperties.getCache().getEhcache();
|
||||
|
||||
jcacheConfiguration =
|
||||
Eh107Configuration.fromEhcacheCacheConfiguration(
|
||||
CacheConfigurationBuilder
|
||||
.newCacheConfigurationBuilder(Object.class, Object.class, ResourcePoolsBuilder.heap(ehcache.getMaxEntries()))
|
||||
.withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(ehcache.getTimeToLiveSeconds())))
|
||||
.build()
|
||||
);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JCacheManagerCustomizer cacheManagerCustomizer() {
|
||||
return cm -> {
|
||||
// jhipster-needle-ehcache-add-entry
|
||||
};
|
||||
}
|
||||
|
||||
private void createCache(javax.cache.CacheManager cm, String cacheName) {
|
||||
javax.cache.Cache<Object, Object> cache = cm.getCache(cacheName);
|
||||
if (cache != null) {
|
||||
cache.clear();
|
||||
} else {
|
||||
cm.createCache(cacheName, jcacheConfiguration);
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setGitProperties(GitProperties gitProperties) {
|
||||
this.gitProperties = gitProperties;
|
||||
}
|
||||
|
||||
@Autowired(required = false)
|
||||
public void setBuildProperties(BuildProperties buildProperties) {
|
||||
this.buildProperties = buildProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public KeyGenerator keyGenerator() {
|
||||
return new PrefixedKeyGenerator(this.gitProperties, this.buildProperties);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.gcube.isdashboard.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,24 @@
|
|||
package org.gcube.isdashboard.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;
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package org.gcube.isdashboard.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.isdashboard.config;
|
||||
|
||||
import org.gcube.isdashboard.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.isdashboard.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,95 @@
|
|||
package org.gcube.isdashboard.config;
|
||||
|
||||
import static org.springframework.security.config.Customizer.withDefaults;
|
||||
|
||||
import org.gcube.isdashboard.security.*;
|
||||
import org.gcube.isdashboard.web.filter.SpaWebFilter;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configurers.HeadersConfigurer.FrameOptionsConfig;
|
||||
import org.springframework.security.web.SecurityFilterChain;
|
||||
import org.springframework.security.web.authentication.HttpStatusEntryPoint;
|
||||
import org.springframework.security.web.authentication.logout.HttpStatusReturningLogoutSuccessHandler;
|
||||
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
|
||||
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
|
||||
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
|
||||
import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter;
|
||||
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
|
||||
import org.springframework.security.web.util.matcher.OrRequestMatcher;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
import tech.jhipster.web.filter.CookieCsrfFilter;
|
||||
|
||||
@Configuration
|
||||
@EnableMethodSecurity(securedEnabled = true)
|
||||
public class SecurityConfiguration {
|
||||
|
||||
private final JHipsterProperties jHipsterProperties;
|
||||
|
||||
public SecurityConfiguration(JHipsterProperties jHipsterProperties) {
|
||||
this.jHipsterProperties = jHipsterProperties;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
|
||||
http
|
||||
.cors(withDefaults())
|
||||
.csrf(csrf ->
|
||||
csrf
|
||||
.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())
|
||||
// See https://stackoverflow.com/q/74447118/65681
|
||||
.csrfTokenRequestHandler(new CsrfTokenRequestAttributeHandler())
|
||||
)
|
||||
.addFilterAfter(new SpaWebFilter(), BasicAuthenticationFilter.class)
|
||||
.addFilterAfter(new CookieCsrfFilter(), BasicAuthenticationFilter.class)
|
||||
.headers(headers ->
|
||||
headers
|
||||
.contentSecurityPolicy(csp -> csp.policyDirectives(jHipsterProperties.getSecurity().getContentSecurityPolicy()))
|
||||
.frameOptions(FrameOptionsConfig::sameOrigin)
|
||||
.referrerPolicy(referrer -> referrer.policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN))
|
||||
.permissionsPolicy(permissions ->
|
||||
permissions.policy(
|
||||
"camera=(), fullscreen=(self), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), midi=(), payment=(), sync-xhr=()"
|
||||
)
|
||||
)
|
||||
)
|
||||
.authorizeHttpRequests(authz ->
|
||||
// prettier-ignore
|
||||
authz
|
||||
.requestMatchers("/", "/index.html", "/*.js", "/*.map", "/*.css").permitAll()
|
||||
.requestMatchers("/*.ico", "/*.png", "/*.svg", "/*.webapp").permitAll()
|
||||
.requestMatchers("/app/**").permitAll()
|
||||
.requestMatchers("/i18n/**").permitAll()
|
||||
.requestMatchers("/content/**").permitAll()
|
||||
.requestMatchers("/swagger-ui/**").permitAll()
|
||||
.requestMatchers("/api/authenticate").permitAll()
|
||||
.requestMatchers("/api/admin/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.requestMatchers("/api/**").authenticated()
|
||||
.requestMatchers("/v3/api-docs/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.requestMatchers("/management/health").permitAll()
|
||||
.requestMatchers("/management/health/**").permitAll()
|
||||
.requestMatchers("/management/info").permitAll()
|
||||
.requestMatchers("/management/prometheus").permitAll()
|
||||
.requestMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
)
|
||||
.exceptionHandling(exceptionHanding ->
|
||||
exceptionHanding.defaultAuthenticationEntryPointFor(
|
||||
new HttpStatusEntryPoint(HttpStatus.UNAUTHORIZED),
|
||||
new OrRequestMatcher(new AntPathRequestMatcher("/api/**"))
|
||||
)
|
||||
)
|
||||
.formLogin(formLogin ->
|
||||
formLogin
|
||||
.loginProcessingUrl("/api/authentication")
|
||||
.successHandler((request, response, authentication) -> response.setStatus(HttpStatus.OK.value()))
|
||||
.failureHandler((request, response, exception) -> response.setStatus(HttpStatus.UNAUTHORIZED.value()))
|
||||
.permitAll()
|
||||
)
|
||||
.logout(logout ->
|
||||
logout.logoutUrl("/api/logout").logoutSuccessHandler(new HttpStatusReturningLogoutSuccessHandler()).permitAll()
|
||||
);
|
||||
return http.build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.gcube.isdashboard.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,98 @@
|
|||
package org.gcube.isdashboard.config;
|
||||
|
||||
import static java.net.URLDecoder.decode;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import java.io.File;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Paths;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.web.server.*;
|
||||
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.core.env.Profiles;
|
||||
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.JHipsterConstants;
|
||||
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 servletWebServer) {
|
||||
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("/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 @@
|
|||
/**
|
||||
* Application configuration.
|
||||
*/
|
||||
package org.gcube.isdashboard.config;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Application root.
|
||||
*/
|
||||
package org.gcube.isdashboard;
|
|
@ -0,0 +1,15 @@
|
|||
package org.gcube.isdashboard.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,86 @@
|
|||
package org.gcube.isdashboard.security;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
/**
|
||||
* Utility class for Spring Security.
|
||||
*/
|
||||
public final class SecurityUtils {
|
||||
|
||||
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) {
|
||||
if (authentication == null) {
|
||||
return null;
|
||||
} else if (authentication.getPrincipal() instanceof UserDetails springSecurityUser) {
|
||||
return springSecurityUser.getUsername();
|
||||
} else if (authentication.getPrincipal() instanceof String s) {
|
||||
return s;
|
||||
}
|
||||
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) {
|
||||
return authentication.getAuthorities().stream().map(GrantedAuthority::getAuthority);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Application security utilities.
|
||||
*/
|
||||
package org.gcube.isdashboard.security;
|
|
@ -0,0 +1,32 @@
|
|||
package org.gcube.isdashboard.web.filter;
|
||||
|
||||
import jakarta.servlet.FilterChain;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
public class SpaWebFilter extends OncePerRequestFilter {
|
||||
|
||||
/**
|
||||
* Forwards any unmapped paths (except those containing a period) to the client {@code index.html}.
|
||||
*/
|
||||
@Override
|
||||
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
String path = request.getRequestURI();
|
||||
if (
|
||||
!path.startsWith("/api") &&
|
||||
!path.startsWith("/management") &&
|
||||
!path.startsWith("/v3/api-docs") &&
|
||||
!path.contains(".") &&
|
||||
path.matches("/(.*)")
|
||||
) {
|
||||
request.getRequestDispatcher("/index.html").forward(request, response);
|
||||
return;
|
||||
}
|
||||
|
||||
filterChain.doFilter(request, response);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Request chain filters.
|
||||
*/
|
||||
package org.gcube.isdashboard.web.filter;
|
|
@ -0,0 +1,78 @@
|
|||
package org.gcube.isdashboard.web.rest;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import org.gcube.isdashboard.security.SecurityUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api")
|
||||
public class AccountResource {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(AccountResource.class);
|
||||
|
||||
private static class AccountResourceException extends RuntimeException {}
|
||||
|
||||
/**
|
||||
* {@code GET /account} : get the current user.
|
||||
*
|
||||
* @return the current user.
|
||||
* @throws AccountResourceException {@code 500 (Internal Server Error)} if the user couldn't be returned.
|
||||
*/
|
||||
@GetMapping("/account")
|
||||
public UserVM getAccount() {
|
||||
String login = SecurityUtils.getCurrentUserLogin().orElseThrow(AccountResourceException::new);
|
||||
Set<String> authorities = SecurityContextHolder
|
||||
.getContext()
|
||||
.getAuthentication()
|
||||
.getAuthorities()
|
||||
.stream()
|
||||
.map(GrantedAuthority::getAuthority)
|
||||
.collect(Collectors.toSet());
|
||||
return new UserVM(login, authorities);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@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();
|
||||
}
|
||||
|
||||
private static class UserVM {
|
||||
|
||||
private String login;
|
||||
private Set<String> authorities;
|
||||
|
||||
@JsonCreator
|
||||
UserVM(String login, Set<String> authorities) {
|
||||
this.login = login;
|
||||
this.authorities = authorities;
|
||||
}
|
||||
|
||||
public boolean isActivated() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<String> getAuthorities() {
|
||||
return authorities;
|
||||
}
|
||||
|
||||
public String getLogin() {
|
||||
return login;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package org.gcube.isdashboard.web.rest.errors;
|
||||
|
||||
import java.net.URI;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.ErrorResponseException;
|
||||
import tech.jhipster.web.rest.errors.ProblemDetailWithCause;
|
||||
import tech.jhipster.web.rest.errors.ProblemDetailWithCause.ProblemDetailWithCauseBuilder;
|
||||
|
||||
@SuppressWarnings("java:S110") // Inheritance tree of classes should not be too deep
|
||||
public class BadRequestAlertException extends ErrorResponseException {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String entityName;
|
||||
|
||||
private final String errorKey;
|
||||
|
||||
public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) {
|
||||
this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey);
|
||||
}
|
||||
|
||||
public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) {
|
||||
super(
|
||||
HttpStatus.BAD_REQUEST,
|
||||
ProblemDetailWithCauseBuilder
|
||||
.instance()
|
||||
.withStatus(HttpStatus.BAD_REQUEST.value())
|
||||
.withType(type)
|
||||
.withTitle(defaultMessage)
|
||||
.withProperty("message", "error." + errorKey)
|
||||
.withProperty("params", entityName)
|
||||
.build(),
|
||||
null
|
||||
);
|
||||
this.entityName = entityName;
|
||||
this.errorKey = errorKey;
|
||||
}
|
||||
|
||||
public String getEntityName() {
|
||||
return entityName;
|
||||
}
|
||||
|
||||
public String getErrorKey() {
|
||||
return errorKey;
|
||||
}
|
||||
|
||||
public ProblemDetailWithCause getProblemDetailWithCause() {
|
||||
return (ProblemDetailWithCause) this.getBody();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
package org.gcube.isdashboard.web.rest.errors;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
public final class ErrorConstants {
|
||||
|
||||
public static final String ERR_VALIDATION = "error.validation";
|
||||
public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem";
|
||||
public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message");
|
||||
public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation");
|
||||
|
||||
private ErrorConstants() {}
|
||||
}
|
|
@ -0,0 +1,253 @@
|
|||
package org.gcube.isdashboard.web.rest.errors;
|
||||
|
||||
import static org.springframework.core.annotation.AnnotatedElementUtils.findMergedAnnotation;
|
||||
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpStatusCode;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.converter.HttpMessageConversionException;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.web.ErrorResponse;
|
||||
import org.springframework.web.ErrorResponseException;
|
||||
import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.context.request.NativeWebRequest;
|
||||
import org.springframework.web.context.request.WebRequest;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
import tech.jhipster.web.rest.errors.ProblemDetailWithCause;
|
||||
import tech.jhipster.web.rest.errors.ProblemDetailWithCause.ProblemDetailWithCauseBuilder;
|
||||
import tech.jhipster.web.util.HeaderUtil;
|
||||
|
||||
/**
|
||||
* Controller advice to translate the server side exceptions to client-friendly json structures.
|
||||
* The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807).
|
||||
*/
|
||||
@ControllerAdvice
|
||||
public class ExceptionTranslator extends ResponseEntityExceptionHandler {
|
||||
|
||||
private static final String FIELD_ERRORS_KEY = "fieldErrors";
|
||||
private static final String MESSAGE_KEY = "message";
|
||||
private static final String PATH_KEY = "path";
|
||||
private static final boolean CASUAL_CHAIN_ENABLED = false;
|
||||
|
||||
@Value("${jhipster.clientApp.name}")
|
||||
private String applicationName;
|
||||
|
||||
private final Environment env;
|
||||
|
||||
public ExceptionTranslator(Environment env) {
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
@ExceptionHandler
|
||||
public ResponseEntity<Object> handleAnyException(Throwable ex, NativeWebRequest request) {
|
||||
ProblemDetailWithCause pdCause = wrapAndCustomizeProblem(ex, request);
|
||||
return handleExceptionInternal(
|
||||
(Exception) ex,
|
||||
pdCause,
|
||||
buildHeaders(ex, request),
|
||||
HttpStatusCode.valueOf(pdCause.getStatus()),
|
||||
request
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
protected ResponseEntity<Object> handleExceptionInternal(
|
||||
Exception ex,
|
||||
@Nullable Object body,
|
||||
HttpHeaders headers,
|
||||
HttpStatusCode statusCode,
|
||||
WebRequest request
|
||||
) {
|
||||
body = body == null ? wrapAndCustomizeProblem((Throwable) ex, (NativeWebRequest) request) : body;
|
||||
return super.handleExceptionInternal(ex, body, headers, statusCode, request);
|
||||
}
|
||||
|
||||
protected ProblemDetailWithCause wrapAndCustomizeProblem(Throwable ex, NativeWebRequest request) {
|
||||
return customizeProblem(getProblemDetailWithCause(ex), ex, request);
|
||||
}
|
||||
|
||||
private ProblemDetailWithCause getProblemDetailWithCause(Throwable ex) {
|
||||
if (
|
||||
ex instanceof ErrorResponseException exp && exp.getBody() instanceof ProblemDetailWithCause
|
||||
) return (ProblemDetailWithCause) exp.getBody();
|
||||
return ProblemDetailWithCauseBuilder.instance().withStatus(toStatus(ex).value()).build();
|
||||
}
|
||||
|
||||
protected ProblemDetailWithCause customizeProblem(ProblemDetailWithCause problem, Throwable err, NativeWebRequest request) {
|
||||
if (problem.getStatus() <= 0) problem.setStatus(toStatus(err));
|
||||
|
||||
if (problem.getType() == null || problem.getType().equals(URI.create("about:blank"))) problem.setType(getMappedType(err));
|
||||
|
||||
// higher precedence to Custom/ResponseStatus types
|
||||
String title = extractTitle(err, problem.getStatus());
|
||||
String problemTitle = problem.getTitle();
|
||||
if (problemTitle == null || !problemTitle.equals(title)) {
|
||||
problem.setTitle(title);
|
||||
}
|
||||
|
||||
if (problem.getDetail() == null) {
|
||||
// higher precedence to cause
|
||||
problem.setDetail(getCustomizedErrorDetails(err));
|
||||
}
|
||||
|
||||
Map<String, Object> problemProperties = problem.getProperties();
|
||||
if (problemProperties == null || !problemProperties.containsKey(MESSAGE_KEY)) problem.setProperty(
|
||||
MESSAGE_KEY,
|
||||
getMappedMessageKey(err) != null ? getMappedMessageKey(err) : "error.http." + problem.getStatus()
|
||||
);
|
||||
|
||||
if (problemProperties == null || !problemProperties.containsKey(PATH_KEY)) problem.setProperty(PATH_KEY, getPathValue(request));
|
||||
|
||||
if (
|
||||
(err instanceof MethodArgumentNotValidException) &&
|
||||
(problemProperties == null || !problemProperties.containsKey(FIELD_ERRORS_KEY))
|
||||
) problem.setProperty(FIELD_ERRORS_KEY, getFieldErrors((MethodArgumentNotValidException) err));
|
||||
|
||||
problem.setCause(buildCause(err.getCause(), request).orElse(null));
|
||||
|
||||
return problem;
|
||||
}
|
||||
|
||||
private String extractTitle(Throwable err, int statusCode) {
|
||||
return getCustomizedTitle(err) != null ? getCustomizedTitle(err) : extractTitleForResponseStatus(err, statusCode);
|
||||
}
|
||||
|
||||
private List<FieldErrorVM> getFieldErrors(MethodArgumentNotValidException ex) {
|
||||
return ex
|
||||
.getBindingResult()
|
||||
.getFieldErrors()
|
||||
.stream()
|
||||
.map(f ->
|
||||
new FieldErrorVM(
|
||||
f.getObjectName().replaceFirst("DTO$", ""),
|
||||
f.getField(),
|
||||
StringUtils.isNotBlank(f.getDefaultMessage()) ? f.getDefaultMessage() : f.getCode()
|
||||
)
|
||||
)
|
||||
.toList();
|
||||
}
|
||||
|
||||
private String extractTitleForResponseStatus(Throwable err, int statusCode) {
|
||||
ResponseStatus specialStatus = extractResponseStatus(err);
|
||||
return specialStatus == null ? HttpStatus.valueOf(statusCode).getReasonPhrase() : specialStatus.reason();
|
||||
}
|
||||
|
||||
private String extractURI(NativeWebRequest request) {
|
||||
HttpServletRequest nativeRequest = request.getNativeRequest(HttpServletRequest.class);
|
||||
return nativeRequest != null ? nativeRequest.getRequestURI() : StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
private HttpStatus toStatus(final Throwable throwable) {
|
||||
// Let the ErrorResponse take this responsibility
|
||||
if (throwable instanceof ErrorResponse err) return HttpStatus.valueOf(err.getBody().getStatus());
|
||||
|
||||
return Optional
|
||||
.ofNullable(getMappedStatus(throwable))
|
||||
.orElse(
|
||||
Optional.ofNullable(resolveResponseStatus(throwable)).map(ResponseStatus::value).orElse(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||
);
|
||||
}
|
||||
|
||||
private ResponseStatus extractResponseStatus(final Throwable throwable) {
|
||||
return Optional.ofNullable(resolveResponseStatus(throwable)).orElse(null);
|
||||
}
|
||||
|
||||
private ResponseStatus resolveResponseStatus(final Throwable type) {
|
||||
final ResponseStatus candidate = findMergedAnnotation(type.getClass(), ResponseStatus.class);
|
||||
return candidate == null && type.getCause() != null ? resolveResponseStatus(type.getCause()) : candidate;
|
||||
}
|
||||
|
||||
private URI getMappedType(Throwable err) {
|
||||
if (err instanceof MethodArgumentNotValidException exp) return ErrorConstants.CONSTRAINT_VIOLATION_TYPE;
|
||||
return ErrorConstants.DEFAULT_TYPE;
|
||||
}
|
||||
|
||||
private String getMappedMessageKey(Throwable err) {
|
||||
if (err instanceof MethodArgumentNotValidException) return ErrorConstants.ERR_VALIDATION;
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getCustomizedTitle(Throwable err) {
|
||||
if (err instanceof MethodArgumentNotValidException exp) return "Method argument not valid";
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getCustomizedErrorDetails(Throwable err) {
|
||||
Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
|
||||
if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
|
||||
if (err instanceof HttpMessageConversionException) return "Unable to convert http message";
|
||||
if (containsPackageName(err.getMessage())) return "Unexpected runtime exception";
|
||||
}
|
||||
return err.getCause() != null ? err.getCause().getMessage() : err.getMessage();
|
||||
}
|
||||
|
||||
private HttpStatus getMappedStatus(Throwable err) {
|
||||
// Where we disagree with Spring defaults
|
||||
if (err instanceof AccessDeniedException) return HttpStatus.FORBIDDEN;
|
||||
if (err instanceof BadCredentialsException) return HttpStatus.UNAUTHORIZED;
|
||||
return null;
|
||||
}
|
||||
|
||||
private URI getPathValue(NativeWebRequest request) {
|
||||
if (request == null) return URI.create("about:blank");
|
||||
return URI.create(extractURI(request));
|
||||
}
|
||||
|
||||
private HttpHeaders buildHeaders(Throwable err, NativeWebRequest request) {
|
||||
return err instanceof BadRequestAlertException
|
||||
? HeaderUtil.createFailureAlert(
|
||||
applicationName,
|
||||
true,
|
||||
((BadRequestAlertException) err).getEntityName(),
|
||||
((BadRequestAlertException) err).getErrorKey(),
|
||||
((BadRequestAlertException) err).getMessage()
|
||||
)
|
||||
: null;
|
||||
}
|
||||
|
||||
public Optional<ProblemDetailWithCause> buildCause(final Throwable throwable, NativeWebRequest request) {
|
||||
if (throwable != null && isCasualChainEnabled()) {
|
||||
return Optional.of(customizeProblem(getProblemDetailWithCause(throwable), throwable, request));
|
||||
}
|
||||
return Optional.ofNullable(null);
|
||||
}
|
||||
|
||||
private boolean isCasualChainEnabled() {
|
||||
// Customize as per the needs
|
||||
return CASUAL_CHAIN_ENABLED;
|
||||
}
|
||||
|
||||
private boolean containsPackageName(String message) {
|
||||
// This list is for sure not complete
|
||||
return StringUtils.containsAny(
|
||||
message,
|
||||
"org.",
|
||||
"java.",
|
||||
"net.",
|
||||
"jakarta.",
|
||||
"javax.",
|
||||
"com.",
|
||||
"io.",
|
||||
"de.",
|
||||
"org.gcube.isdashboard"
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package org.gcube.isdashboard.web.rest.errors;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class FieldErrorVM implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private final String objectName;
|
||||
|
||||
private final String field;
|
||||
|
||||
private final String message;
|
||||
|
||||
public FieldErrorVM(String dto, String field, String message) {
|
||||
this.objectName = dto;
|
||||
this.field = field;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getObjectName() {
|
||||
return objectName;
|
||||
}
|
||||
|
||||
public String getField() {
|
||||
return field;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Rest layer error handling.
|
||||
*/
|
||||
package org.gcube.isdashboard.web.rest.errors;
|
|
@ -0,0 +1,4 @@
|
|||
/**
|
||||
* Rest layer.
|
||||
*/
|
||||
package org.gcube.isdashboard.web.rest;
|
|
@ -0,0 +1,10 @@
|
|||
|
||||
${AnsiColor.GREEN} ██╗${AnsiColor.RED} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗
|
||||
${AnsiColor.GREEN} ██║${AnsiColor.RED} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗
|
||||
${AnsiColor.GREEN} ██║${AnsiColor.RED} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝
|
||||
${AnsiColor.GREEN}██╗ ██║${AnsiColor.RED} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║
|
||||
${AnsiColor.GREEN}╚██████╔╝${AnsiColor.RED} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗
|
||||
${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.RED} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝
|
||||
|
||||
${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} :: Startup profile(s) ${spring.profiles.active} ::
|
||||
:: https://www.jhipster.tech ::${AnsiColor.DEFAULT}
|
|
@ -0,0 +1,83 @@
|
|||
# ===================================================================
|
||||
# Spring Boot configuration for the "dev" profile.
|
||||
#
|
||||
# This configuration overrides the application.yml file.
|
||||
#
|
||||
# More information on profiles: https://www.jhipster.tech/profiles/
|
||||
# More information on configuration properties: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Standard Spring Boot properties.
|
||||
# Full reference is available at:
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
logging:
|
||||
level:
|
||||
ROOT: DEBUG
|
||||
tech.jhipster: DEBUG
|
||||
org.hibernate.SQL: DEBUG
|
||||
org.gcube.isdashboard: DEBUG
|
||||
|
||||
spring:
|
||||
devtools:
|
||||
restart:
|
||||
enabled: true
|
||||
additional-exclude: static/**
|
||||
livereload:
|
||||
enabled: false # we use Webpack dev server + BrowserSync for livereload
|
||||
jackson:
|
||||
serialization:
|
||||
indent-output: true
|
||||
messages:
|
||||
cache-duration: PT1S # 1 second, see the ISO 8601 standard
|
||||
thymeleaf:
|
||||
cache: false
|
||||
|
||||
server:
|
||||
port: 8080
|
||||
|
||||
# ===================================================================
|
||||
# JHipster specific properties
|
||||
#
|
||||
# Full reference is available at: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
jhipster:
|
||||
cache: # Cache configuration
|
||||
ehcache: # Ehcache configuration
|
||||
time-to-live-seconds: 3600 # By default objects stay 1 hour in the cache
|
||||
max-entries: 100 # Number of objects in each cache entry
|
||||
# CORS is only enabled by default with the "dev" profile
|
||||
cors:
|
||||
# Allow Ionic for JHipster by default (* no longer allowed in Spring Boot 2.4+)
|
||||
allowed-origins: 'http://localhost:8100,https://localhost:8100,http://localhost:9000,https://localhost:9000,http://localhost:4200,https://localhost:4200'
|
||||
# Enable CORS when running in GitHub Codespaces
|
||||
allowed-origin-patterns: 'https://*.githubpreview.dev'
|
||||
allowed-methods: '*'
|
||||
allowed-headers: '*'
|
||||
exposed-headers: 'Link,X-Total-Count,X-${jhipster.clientApp.name}-alert,X-${jhipster.clientApp.name}-error,X-${jhipster.clientApp.name}-params'
|
||||
allow-credentials: true
|
||||
max-age: 1800
|
||||
security:
|
||||
remember-me:
|
||||
# security key (this key should be unique for your application, and kept secret)
|
||||
key: 6038bcb93c3f8cc61c163e71aa55573477e46c3535cf0624212567f396b89e7be83d90b03885a818d14b1b7f4928ab548561
|
||||
logging:
|
||||
use-json-format: false # By default, logs are not in Json format
|
||||
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 5000
|
||||
ring-buffer-size: 512
|
||||
# ===================================================================
|
||||
# Application specific properties
|
||||
# Add your own application properties here, see the ApplicationProperties class
|
||||
# to have type-safe configuration, like in the JHipsterProperties above
|
||||
#
|
||||
# More documentation is available at:
|
||||
# https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# application:
|
|
@ -0,0 +1,98 @@
|
|||
# ===================================================================
|
||||
# Spring Boot configuration for the "prod" profile.
|
||||
#
|
||||
# This configuration overrides the application.yml file.
|
||||
#
|
||||
# More information on profiles: https://www.jhipster.tech/profiles/
|
||||
# More information on configuration properties: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Standard Spring Boot properties.
|
||||
# Full reference is available at:
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
logging:
|
||||
level:
|
||||
ROOT: INFO
|
||||
tech.jhipster: INFO
|
||||
org.gcube.isdashboard: INFO
|
||||
|
||||
management:
|
||||
prometheus:
|
||||
metrics:
|
||||
export:
|
||||
enabled: false
|
||||
|
||||
spring:
|
||||
devtools:
|
||||
restart:
|
||||
enabled: false
|
||||
livereload:
|
||||
enabled: false
|
||||
thymeleaf:
|
||||
cache: true
|
||||
|
||||
# ===================================================================
|
||||
# To enable TLS in production, generate a certificate using:
|
||||
# keytool -genkey -alias isdashboard -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650
|
||||
#
|
||||
# You can also use Let's Encrypt:
|
||||
# See details in topic "Create a Java Keystore (.JKS) from Let's Encrypt Certificates" on https://maximilian-boehm.com/en-gb/blog
|
||||
#
|
||||
# Then, modify the server.ssl properties so your "server" configuration looks like:
|
||||
#
|
||||
# server:
|
||||
# port: 443
|
||||
# ssl:
|
||||
# key-store: classpath:config/tls/keystore.p12
|
||||
# key-store-password: password
|
||||
# key-store-type: PKCS12
|
||||
# key-alias: selfsigned
|
||||
# # The ciphers suite enforce the security by deactivating some old and deprecated SSL cipher, this list was tested against SSL Labs (https://www.ssllabs.com/ssltest/)
|
||||
# ciphers: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
|
||||
# ===================================================================
|
||||
server:
|
||||
port: 8080
|
||||
shutdown: graceful # see https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
|
||||
compression:
|
||||
enabled: true
|
||||
mime-types: text/html,text/xml,text/plain,text/css,application/javascript,application/json,image/svg+xml
|
||||
min-response-size: 1024
|
||||
|
||||
# ===================================================================
|
||||
# JHipster specific properties
|
||||
#
|
||||
# Full reference is available at: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
jhipster:
|
||||
http:
|
||||
cache: # Used by the CachingHttpHeadersFilter
|
||||
timeToLiveInDays: 1461
|
||||
cache: # Cache configuration
|
||||
ehcache: # Ehcache configuration
|
||||
time-to-live-seconds: 3600 # By default objects stay 1 hour in the cache
|
||||
max-entries: 1000 # Number of objects in each cache entry
|
||||
security:
|
||||
remember-me:
|
||||
# security key (this key should be unique for your application, and kept secret)
|
||||
key: 6038bcb93c3f8cc61c163e71aa55573477e46c3535cf0624212567f396b89e7be83d90b03885a818d14b1b7f4928ab548561
|
||||
logging:
|
||||
use-json-format: false # By default, logs are not in Json format
|
||||
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 5000
|
||||
ring-buffer-size: 512
|
||||
# ===================================================================
|
||||
# Application specific properties
|
||||
# Add your own application properties here, see the ApplicationProperties class
|
||||
# to have type-safe configuration, like in the JHipsterProperties above
|
||||
#
|
||||
# More documentation is available at:
|
||||
# https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# application:
|
|
@ -0,0 +1,19 @@
|
|||
# ===================================================================
|
||||
# Activate this profile to enable TLS and HTTP/2.
|
||||
#
|
||||
# JHipster has generated a self-signed certificate, which will be used to encrypt traffic.
|
||||
# As your browser will not understand this certificate, you will need to import it.
|
||||
#
|
||||
# Another (easiest) solution with Chrome is to enable the "allow-insecure-localhost" flag
|
||||
# at chrome://flags/#allow-insecure-localhost
|
||||
# ===================================================================
|
||||
server:
|
||||
ssl:
|
||||
key-store: classpath:config/tls/keystore.p12
|
||||
key-store-password: password
|
||||
key-store-type: PKCS12
|
||||
key-alias: selfsigned
|
||||
ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
|
||||
enabled-protocols: TLSv1.2
|
||||
http2:
|
||||
enabled: true
|
|
@ -0,0 +1,192 @@
|
|||
# ===================================================================
|
||||
# Spring Boot configuration.
|
||||
#
|
||||
# This configuration will be overridden by the Spring profile you use,
|
||||
# for example application-dev.yml if you use the "dev" profile.
|
||||
#
|
||||
# More information on profiles: https://www.jhipster.tech/profiles/
|
||||
# More information on configuration properties: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Standard Spring Boot properties.
|
||||
# Full reference is available at:
|
||||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
---
|
||||
# Conditionally disable springdoc on missing api-docs profile
|
||||
spring:
|
||||
config:
|
||||
activate:
|
||||
on-profile: '!api-docs'
|
||||
springdoc:
|
||||
api-docs:
|
||||
enabled: false
|
||||
---
|
||||
management:
|
||||
endpoints:
|
||||
web:
|
||||
base-path: /management
|
||||
exposure:
|
||||
include:
|
||||
- configprops
|
||||
- env
|
||||
- health
|
||||
- info
|
||||
- jhimetrics
|
||||
- jhiopenapigroups
|
||||
- logfile
|
||||
- loggers
|
||||
- prometheus
|
||||
- threaddump
|
||||
- caches
|
||||
endpoint:
|
||||
health:
|
||||
show-details: when_authorized
|
||||
roles: 'ROLE_ADMIN'
|
||||
probes:
|
||||
enabled: true
|
||||
group:
|
||||
liveness:
|
||||
include: livenessState
|
||||
readiness:
|
||||
include: readinessState
|
||||
jhimetrics:
|
||||
enabled: true
|
||||
info:
|
||||
git:
|
||||
mode: full
|
||||
env:
|
||||
enabled: true
|
||||
health:
|
||||
mail:
|
||||
enabled: false # When using the MailService, configure an SMTP server and set this to true
|
||||
prometheus:
|
||||
metrics:
|
||||
export:
|
||||
enabled: true
|
||||
step: 60
|
||||
enable:
|
||||
http: true
|
||||
jvm: true
|
||||
logback: true
|
||||
process: true
|
||||
system: true
|
||||
distribution:
|
||||
percentiles-histogram:
|
||||
all: true
|
||||
percentiles:
|
||||
all: 0, 0.5, 0.75, 0.95, 0.99, 1.0
|
||||
tags:
|
||||
application: ${spring.application.name}
|
||||
web:
|
||||
server:
|
||||
request:
|
||||
autotime:
|
||||
enabled: true
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: isdashboard
|
||||
profiles:
|
||||
# The commented value for `active` can be replaced with valid Spring profiles to load.
|
||||
# Otherwise, it will be filled in by maven when building the JAR file
|
||||
# Either way, it can be overridden by `--spring.profiles.active` value passed in the commandline or `-Dspring.profiles.active` set in `JAVA_OPTS`
|
||||
active: #spring.profiles.active#
|
||||
group:
|
||||
dev:
|
||||
- dev
|
||||
- api-docs
|
||||
# Uncomment to activate TLS for the dev profile
|
||||
#- tls
|
||||
jmx:
|
||||
enabled: false
|
||||
messages:
|
||||
basename: i18n/messages
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
mvc:
|
||||
problemdetails:
|
||||
enabled: true
|
||||
security:
|
||||
user:
|
||||
name: admin
|
||||
password: admin
|
||||
roles:
|
||||
- ADMIN
|
||||
- USER
|
||||
task:
|
||||
execution:
|
||||
thread-name-prefix: isdashboard-task-
|
||||
pool:
|
||||
core-size: 2
|
||||
max-size: 50
|
||||
queue-capacity: 10000
|
||||
scheduling:
|
||||
thread-name-prefix: isdashboard-scheduling-
|
||||
pool:
|
||||
size: 2
|
||||
thymeleaf:
|
||||
mode: HTML
|
||||
output:
|
||||
ansi:
|
||||
console-available: true
|
||||
|
||||
server:
|
||||
servlet:
|
||||
session:
|
||||
cookie:
|
||||
http-only: true
|
||||
|
||||
springdoc:
|
||||
show-actuator: true
|
||||
|
||||
# Properties to be exposed on the /info management endpoint
|
||||
info:
|
||||
# Comma separated list of profiles that will trigger the ribbon to show
|
||||
display-ribbon-on-profiles: 'dev'
|
||||
|
||||
# ===================================================================
|
||||
# JHipster specific properties
|
||||
#
|
||||
# Full reference is available at: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
jhipster:
|
||||
clientApp:
|
||||
name: 'isdashboardApp'
|
||||
# By default CORS is disabled. Uncomment to enable.
|
||||
# cors:
|
||||
# allowed-origins: "http://localhost:8100,http://localhost:9000"
|
||||
# allowed-methods: "*"
|
||||
# allowed-headers: "*"
|
||||
# exposed-headers: "Link,X-Total-Count,X-${jhipster.clientApp.name}-alert,X-${jhipster.clientApp.name}-error,X-${jhipster.clientApp.name}-params"
|
||||
# allow-credentials: true
|
||||
# max-age: 1800
|
||||
mail:
|
||||
from: isdashboard@localhost
|
||||
api-docs:
|
||||
default-include-pattern: ${server.servlet.context-path:}/api/**
|
||||
management-include-pattern: ${server.servlet.context-path:}/management/**
|
||||
title: Isdashboard API
|
||||
description: Isdashboard API documentation
|
||||
version: 0.0.1
|
||||
terms-of-service-url:
|
||||
contact-name:
|
||||
contact-url:
|
||||
contact-email:
|
||||
license: unlicensed
|
||||
license-url:
|
||||
security:
|
||||
content-security-policy: "default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:"
|
||||
# ===================================================================
|
||||
# Application specific properties
|
||||
# Add your own application properties here, see the ApplicationProperties class
|
||||
# to have type-safe configuration, like in the JHipsterProperties above
|
||||
#
|
||||
# More documentation is available at:
|
||||
# https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# application:
|
Binary file not shown.
|
@ -0,0 +1,6 @@
|
|||
# Error page
|
||||
error.title=Your request cannot be processed
|
||||
error.subtitle=Sorry, an error has occurred.
|
||||
error.status=Status:
|
||||
error.message=Message:
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration>
|
||||
|
||||
<configuration scan="true">
|
||||
<!-- Patterns based on https://github.com/spring-projects/spring-boot/blob/v3.0.0/spring-boot-project/spring-boot/src/main/resources/org/springframework/boot/logging/logback/defaults.xml -->
|
||||
<conversionRule conversionWord="crlf" converterClass="org.gcube.isdashboard.config.CRLFLogConverter" />
|
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %crlf(%m){red} %n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
<!-- The FILE and ASYNC appenders are here as examples for a production configuration -->
|
||||
<!--
|
||||
<property name="FILE_LOG_PATTERN" value="${FILE_LOG_PATTERN:-%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd'T'HH:mm:ss.SSSXXX}} ${LOG_LEVEL_PATTERN:-%5p} ${PID:- } --- [%t] %-40.40logger{39} : %crlf(%m) %n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
-->
|
||||
|
||||
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
|
||||
<include resource="org/springframework/boot/logging/logback/console-appender.xml" />
|
||||
|
||||
<!-- The FILE and ASYNC appenders are here as examples for a production configuration -->
|
||||
<!--
|
||||
<include resource="org/springframework/boot/logging/logback/file-appender.xml" />
|
||||
|
||||
<appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender">
|
||||
<queueSize>512</queueSize>
|
||||
<appender-ref ref="FILE"/>
|
||||
</appender>
|
||||
|
||||
<root level="${logging.level.root}">
|
||||
<appender-ref ref="ASYNC"/>
|
||||
</root>
|
||||
-->
|
||||
|
||||
<logger name="angus.activation" level="WARN"/>
|
||||
<logger name="jakarta.activation" level="WARN"/>
|
||||
<logger name="jakarta.mail" level="WARN"/>
|
||||
<logger name="jakarta.management.remote" level="WARN"/>
|
||||
<logger name="jakarta.xml.bind" level="WARN"/>
|
||||
<logger name="jdk.event.security" level="INFO"/>
|
||||
<logger name="com.ryantenney" level="WARN"/>
|
||||
<logger name="com.sun" level="WARN"/>
|
||||
<logger name="com.zaxxer" level="WARN"/>
|
||||
<logger name="io.undertow" level="WARN"/>
|
||||
<logger name="io.undertow.websockets.jsr" level="ERROR"/>
|
||||
<logger name="org.ehcache" level="WARN"/>
|
||||
<logger name="org.apache" level="WARN"/>
|
||||
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>
|
||||
<logger name="org.bson" level="WARN"/>
|
||||
<logger name="org.hibernate.validator" level="WARN"/>
|
||||
<logger name="org.springframework" level="WARN"/>
|
||||
<logger name="org.springframework.web" level="WARN"/>
|
||||
<logger name="org.springframework.security" level="WARN"/>
|
||||
<logger name="org.springframework.boot.autoconfigure.logging" level="INFO"/>
|
||||
<logger name="org.springframework.cache" level="WARN"/>
|
||||
<logger name="org.thymeleaf" level="WARN"/>
|
||||
<logger name="org.xnio" level="WARN"/>
|
||||
<logger name="io.swagger.v3" level="INFO"/>
|
||||
<logger name="sun.rmi" level="WARN"/>
|
||||
<logger name="sun.rmi.transport" level="WARN"/>
|
||||
<!-- See https://github.com/jhipster/generator-jhipster/issues/13835 -->
|
||||
<logger name="Validator" level="INFO"/>
|
||||
<!-- See https://github.com/jhipster/generator-jhipster/issues/14444 -->
|
||||
<logger name="_org.springframework.web.servlet.HandlerMapping.Mappings" level="INFO"/>
|
||||
<!-- jhipster-needle-logback-add-log - JHipster will add a new log with level -->
|
||||
|
||||
<springProperty name="log.level" source="logging.level.root" defaultValue="INFO" />
|
||||
<root level="${log.level}">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
</root>
|
||||
|
||||
<contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
|
||||
<resetJUL>true</resetJUL>
|
||||
</contextListener>
|
||||
|
||||
</configuration>
|
|
@ -0,0 +1,92 @@
|
|||
<!DOCTYPE html>
|
||||
<html
|
||||
xmlns:th="http://www.thymeleaf.org"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.thymeleaf.org"
|
||||
th:lang="${#locale.language}"
|
||||
lang="en"
|
||||
>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<link rel="icon" href="${baseUrl}/favicon.ico" />
|
||||
<title>Your request cannot be processed</title>
|
||||
<style>
|
||||
::-moz-selection {
|
||||
background: #b3d4fc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
::selection {
|
||||
background: #b3d4fc;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
html {
|
||||
padding: 30px 10px;
|
||||
font-size: 20px;
|
||||
line-height: 1.4;
|
||||
color: #737373;
|
||||
background: #3e8acc;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-ms-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
html,
|
||||
input {
|
||||
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
max-width: 1000px;
|
||||
_width: 500px;
|
||||
padding: 30px 20px 50px;
|
||||
border: 1px solid #b3b3b3;
|
||||
border-radius: 4px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff;
|
||||
background: #fcfcfc;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0 10px;
|
||||
font-size: 50px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 span {
|
||||
color: #bbb;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 1.5em 0 0.5em;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0 0 0 40px;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 800px;
|
||||
_width: 380px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1 th:text="#{error.title}">Your request cannot be processed <span>:(</span></h1>
|
||||
|
||||
<p th:text="#{error.subtitle}">Sorry, an error has occurred.</p>
|
||||
|
||||
<span th:text="#{error.status}">Status:</span> <span th:text="${error}"></span> (<span th:text="${error}"></span>)<br />
|
||||
<span th:if="${!#strings.isEmpty(message)}">
|
||||
<span th:text="#{error.message}">Message:</span> <span th:text="${message}"></span><br />
|
||||
</span>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,58 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Page Not Found</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<link rel="icon" href="favicon.ico" />
|
||||
<style>
|
||||
* {
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
color: #888;
|
||||
display: table;
|
||||
font-family: sans-serif;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
margin: 2em auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #555;
|
||||
font-size: 2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 auto;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 280px) {
|
||||
body,
|
||||
p {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin: 0 0 0.3em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Page Not Found</h1>
|
||||
<p>Sorry, but the page you were trying to view does not exist.</p>
|
||||
</body>
|
||||
</html>
|
||||
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->
|
|
@ -0,0 +1,13 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<mime-mapping>
|
||||
<extension>html</extension>
|
||||
<mime-type>text/html;charset=utf-8</mime-type>
|
||||
</mime-mapping>
|
||||
|
||||
</web-app>
|
|
@ -0,0 +1,18 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
/* jhipster-needle-add-admin-module-import - JHipster will add admin modules imports here */
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
/* jhipster-needle-add-admin-module - JHipster will add admin modules here */
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: 'docs',
|
||||
loadComponent: () => import('./docs/docs.component'),
|
||||
title: 'API',
|
||||
},
|
||||
/* jhipster-needle-add-admin-route - JHipster will add admin routes here */
|
||||
]),
|
||||
],
|
||||
})
|
||||
export default class AdminRoutingModule {}
|
|
@ -0,0 +1,10 @@
|
|||
<iframe
|
||||
src="swagger-ui/index.html"
|
||||
width="100%"
|
||||
height="900"
|
||||
seamless
|
||||
target="_top"
|
||||
title="Swagger UI"
|
||||
class="border-0"
|
||||
data-cy="swagger-frame"
|
||||
></iframe>
|
|
@ -0,0 +1,6 @@
|
|||
@import 'bootstrap/scss/functions';
|
||||
@import 'bootstrap/scss/variables';
|
||||
|
||||
iframe {
|
||||
background: white;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'jhi-docs',
|
||||
templateUrl: './docs.component.html',
|
||||
styleUrls: ['./docs.component.scss'],
|
||||
})
|
||||
export default class DocsComponent {}
|
|
@ -0,0 +1,17 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { RouterStateSnapshot, TitleStrategy } from '@angular/router';
|
||||
|
||||
@Injectable()
|
||||
export class AppPageTitleStrategy extends TitleStrategy {
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
override updateTitle(routerState: RouterStateSnapshot): void {
|
||||
let pageTitle = this.buildTitle(routerState);
|
||||
if (!pageTitle) {
|
||||
pageTitle = 'Isdashboard';
|
||||
}
|
||||
document.title = pageTitle;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { errorRoute } from './layouts/error/error.route';
|
||||
import { DEBUG_INFO_ENABLED } from 'app/app.constants';
|
||||
import { Authority } from 'app/config/authority.constants';
|
||||
|
||||
import HomeComponent from './home/home.component';
|
||||
import NavbarComponent from './layouts/navbar/navbar.component';
|
||||
import LoginComponent from './login/login.component';
|
||||
|
||||
import { UserRouteAccessService } from 'app/core/auth/user-route-access.service';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(
|
||||
[
|
||||
{
|
||||
path: '',
|
||||
component: HomeComponent,
|
||||
title: 'Welcome, Java Hipster!',
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
component: NavbarComponent,
|
||||
outlet: 'navbar',
|
||||
},
|
||||
{
|
||||
path: 'admin',
|
||||
data: {
|
||||
authorities: [Authority.ADMIN],
|
||||
},
|
||||
canActivate: [UserRouteAccessService],
|
||||
loadChildren: () => import('./admin/admin-routing.module'),
|
||||
},
|
||||
{
|
||||
path: 'login',
|
||||
component: LoginComponent,
|
||||
title: 'Sign in',
|
||||
},
|
||||
{
|
||||
path: '',
|
||||
loadChildren: () => import(`./entities/entity-routing.module`).then(({ EntityRoutingModule }) => EntityRoutingModule),
|
||||
},
|
||||
...errorRoute,
|
||||
],
|
||||
{ enableTracing: DEBUG_INFO_ENABLED, bindToComponentInputs: true }
|
||||
),
|
||||
],
|
||||
exports: [RouterModule],
|
||||
})
|
||||
export class AppRoutingModule {}
|
|
@ -0,0 +1,9 @@
|
|||
// These constants are injected via webpack DefinePlugin variables.
|
||||
// You can add more variables in webpack.common.js or in profile specific webpack.<dev|prod>.js files.
|
||||
// If you change the values in the webpack config files, you need to re run webpack to update the application
|
||||
|
||||
declare const __DEBUG_INFO_ENABLED__: boolean;
|
||||
declare const __VERSION__: string;
|
||||
|
||||
export const VERSION = __VERSION__;
|
||||
export const DEBUG_INFO_ENABLED = __DEBUG_INFO_ENABLED__;
|
|
@ -0,0 +1,49 @@
|
|||
import { NgModule, LOCALE_ID } from '@angular/core';
|
||||
import { registerLocaleData } from '@angular/common';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import locale from '@angular/common/locales/en';
|
||||
import { BrowserModule, Title } from '@angular/platform-browser';
|
||||
import { TitleStrategy } from '@angular/router';
|
||||
import { ServiceWorkerModule } from '@angular/service-worker';
|
||||
import { FaIconLibrary } from '@fortawesome/angular-fontawesome';
|
||||
import dayjs from 'dayjs/esm';
|
||||
import { NgbDateAdapter, NgbDatepickerConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { ApplicationConfigService } from 'app/core/config/application-config.service';
|
||||
import './config/dayjs';
|
||||
import { AppRoutingModule } from './app-routing.module';
|
||||
// jhipster-needle-angular-add-module-import JHipster will add new module here
|
||||
import { NgbDateDayjsAdapter } from './config/datepicker-adapter';
|
||||
import { fontAwesomeIcons } from './config/font-awesome-icons';
|
||||
import { httpInterceptorProviders } from 'app/core/interceptor/index';
|
||||
import MainComponent from './layouts/main/main.component';
|
||||
import MainModule from './layouts/main/main.module';
|
||||
import { AppPageTitleStrategy } from './app-page-title-strategy';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
// jhipster-needle-angular-add-module JHipster will add new module here
|
||||
AppRoutingModule,
|
||||
// Set this to true to enable service worker (PWA)
|
||||
ServiceWorkerModule.register('ngsw-worker.js', { enabled: false }),
|
||||
HttpClientModule,
|
||||
MainModule,
|
||||
],
|
||||
providers: [
|
||||
Title,
|
||||
{ provide: LOCALE_ID, useValue: 'en' },
|
||||
{ provide: NgbDateAdapter, useClass: NgbDateDayjsAdapter },
|
||||
httpInterceptorProviders,
|
||||
{ provide: TitleStrategy, useClass: AppPageTitleStrategy },
|
||||
],
|
||||
bootstrap: [MainComponent],
|
||||
})
|
||||
export class AppModule {
|
||||
constructor(applicationConfigService: ApplicationConfigService, iconLibrary: FaIconLibrary, dpConfig: NgbDatepickerConfig) {
|
||||
applicationConfigService.setEndpointPrefix(SERVER_API_URL);
|
||||
registerLocaleData(locale);
|
||||
iconLibrary.addIcons(...fontAwesomeIcons);
|
||||
dpConfig.minDate = { year: dayjs().subtract(100, 'year').year(), month: 1, day: 1 };
|
||||
}
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
export enum Authority {
|
||||
ADMIN = 'ROLE_ADMIN',
|
||||
USER = 'ROLE_USER',
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
/**
|
||||
* Angular bootstrap Date adapter
|
||||
*/
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap';
|
||||
import dayjs from 'dayjs/esm';
|
||||
|
||||
@Injectable()
|
||||
export class NgbDateDayjsAdapter extends NgbDateAdapter<dayjs.Dayjs> {
|
||||
fromModel(date: dayjs.Dayjs | null): NgbDateStruct | null {
|
||||
if (date && dayjs.isDayjs(date) && date.isValid()) {
|
||||
return { year: date.year(), month: date.month() + 1, day: date.date() };
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
toModel(date: NgbDateStruct | null): dayjs.Dayjs | null {
|
||||
return date ? dayjs(`${date.year}-${date.month}-${date.day}`) : null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
import dayjs from 'dayjs/esm';
|
||||
import customParseFormat from 'dayjs/esm/plugin/customParseFormat';
|
||||
import duration from 'dayjs/esm/plugin/duration';
|
||||
import relativeTime from 'dayjs/esm/plugin/relativeTime';
|
||||
|
||||
// jhipster-needle-i18n-language-dayjs-imports - JHipster will import languages from dayjs here
|
||||
|
||||
// DAYJS CONFIGURATION
|
||||
dayjs.extend(customParseFormat);
|
||||
dayjs.extend(duration);
|
||||
dayjs.extend(relativeTime);
|
|
@ -0,0 +1,3 @@
|
|||
export const PROBLEM_BASE_URL = 'https://www.jhipster.tech/problem';
|
||||
export const EMAIL_ALREADY_USED_TYPE = `${PROBLEM_BASE_URL}/email-already-used`;
|
||||
export const LOGIN_ALREADY_USED_TYPE = `${PROBLEM_BASE_URL}/login-already-used`;
|
|
@ -0,0 +1,83 @@
|
|||
import {
|
||||
faArrowLeft,
|
||||
faAsterisk,
|
||||
faBan,
|
||||
faBars,
|
||||
faBell,
|
||||
faBook,
|
||||
faCalendarAlt,
|
||||
faCheck,
|
||||
faCloud,
|
||||
faCogs,
|
||||
faDatabase,
|
||||
faEye,
|
||||
faFlag,
|
||||
faHeart,
|
||||
faHome,
|
||||
faList,
|
||||
faLock,
|
||||
faPencilAlt,
|
||||
faPlus,
|
||||
faRoad,
|
||||
faSave,
|
||||
faSearch,
|
||||
faSignOutAlt,
|
||||
faSignInAlt,
|
||||
faSort,
|
||||
faSortDown,
|
||||
faSortUp,
|
||||
faSync,
|
||||
faTachometerAlt,
|
||||
faTasks,
|
||||
faThList,
|
||||
faTimes,
|
||||
faTrashAlt,
|
||||
faUser,
|
||||
faUserPlus,
|
||||
faUsers,
|
||||
faUsersCog,
|
||||
faWrench,
|
||||
// jhipster-needle-add-icon-import
|
||||
} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export const fontAwesomeIcons = [
|
||||
faArrowLeft,
|
||||
faAsterisk,
|
||||
faBan,
|
||||
faBars,
|
||||
faBell,
|
||||
faBook,
|
||||
faCalendarAlt,
|
||||
faCheck,
|
||||
faCloud,
|
||||
faCogs,
|
||||
faDatabase,
|
||||
faEye,
|
||||
faFlag,
|
||||
faHeart,
|
||||
faHome,
|
||||
faList,
|
||||
faLock,
|
||||
faPencilAlt,
|
||||
faPlus,
|
||||
faRoad,
|
||||
faSave,
|
||||
faSearch,
|
||||
faSignOutAlt,
|
||||
faSignInAlt,
|
||||
faSort,
|
||||
faSortDown,
|
||||
faSortUp,
|
||||
faSync,
|
||||
faTachometerAlt,
|
||||
faTasks,
|
||||
faThList,
|
||||
faTimes,
|
||||
faTrashAlt,
|
||||
faUser,
|
||||
faUserPlus,
|
||||
faUsers,
|
||||
faUsersCog,
|
||||
faWrench,
|
||||
// jhipster-needle-add-icon-import
|
||||
];
|
|
@ -0,0 +1,2 @@
|
|||
export const DATE_FORMAT = 'YYYY-MM-DD';
|
||||
export const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm';
|
|
@ -0,0 +1,5 @@
|
|||
export const ASC = 'asc';
|
||||
export const DESC = 'desc';
|
||||
export const SORT = 'sort';
|
||||
export const ITEM_DELETED_EVENT = 'deleted';
|
||||
export const DEFAULT_SORT_DATA = 'defaultSort';
|
|
@ -0,0 +1,3 @@
|
|||
export const TOTAL_COUNT_RESPONSE_HEADER = 'X-Total-Count';
|
||||
export const PAGE_HEADER = 'page';
|
||||
export const ITEMS_PER_PAGE = 20;
|
|
@ -0,0 +1,14 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { ITEMS_PER_PAGE } from 'app/config/pagination.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PaginationConfig {
|
||||
constructor(config: NgbPaginationConfig) {
|
||||
config.boundaryLinks = true;
|
||||
config.maxSize = 5;
|
||||
config.pageSize = ITEMS_PER_PAGE;
|
||||
config.size = 'sm';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
export class Account {
|
||||
constructor(
|
||||
public activated: boolean,
|
||||
public authorities: string[],
|
||||
public email: string,
|
||||
public firstName: string | null,
|
||||
public langKey: string,
|
||||
public lastName: string | null,
|
||||
public login: string,
|
||||
public imageUrl: string | null
|
||||
) {}
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
jest.mock('app/core/auth/state-storage.service');
|
||||
|
||||
import { Router } from '@angular/router';
|
||||
import { RouterTestingModule } from '@angular/router/testing';
|
||||
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
|
||||
import { TestBed } from '@angular/core/testing';
|
||||
|
||||
import { Account } from 'app/core/auth/account.model';
|
||||
import { Authority } from 'app/config/authority.constants';
|
||||
import { StateStorageService } from 'app/core/auth/state-storage.service';
|
||||
|
||||
import { AccountService } from './account.service';
|
||||
|
||||
function accountWithAuthorities(authorities: string[]): Account {
|
||||
return {
|
||||
activated: true,
|
||||
authorities,
|
||||
email: '',
|
||||
firstName: '',
|
||||
langKey: '',
|
||||
lastName: '',
|
||||
login: '',
|
||||
imageUrl: '',
|
||||
};
|
||||
}
|
||||
|
||||
describe('Account Service', () => {
|
||||
let service: AccountService;
|
||||
let httpMock: HttpTestingController;
|
||||
let mockStorageService: StateStorageService;
|
||||
let mockRouter: Router;
|
||||
|
||||
beforeEach(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [HttpClientTestingModule, RouterTestingModule.withRoutes([])],
|
||||
providers: [StateStorageService],
|
||||
});
|
||||
|
||||
service = TestBed.inject(AccountService);
|
||||
httpMock = TestBed.inject(HttpTestingController);
|
||||
mockStorageService = TestBed.inject(StateStorageService);
|
||||
mockRouter = TestBed.inject(Router);
|
||||
jest.spyOn(mockRouter, 'navigateByUrl').mockImplementation(() => Promise.resolve(true));
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
httpMock.verify();
|
||||
});
|
||||
|
||||
describe('authenticate', () => {
|
||||
it('authenticationState should emit null if input is null', () => {
|
||||
// GIVEN
|
||||
let userIdentity: Account | null = accountWithAuthorities([]);
|
||||
service.getAuthenticationState().subscribe(account => (userIdentity = account));
|
||||
|
||||
// WHEN
|
||||
service.authenticate(null);
|
||||
|
||||
// THEN
|
||||
expect(userIdentity).toBeNull();
|
||||
expect(service.isAuthenticated()).toBe(false);
|
||||
});
|
||||
|
||||
it('authenticationState should emit the same account as was in input parameter', () => {
|
||||
// GIVEN
|
||||
const expectedResult = accountWithAuthorities([]);
|
||||
let userIdentity: Account | null = null;
|
||||
service.getAuthenticationState().subscribe(account => (userIdentity = account));
|
||||
|
||||
// WHEN
|
||||
service.authenticate(expectedResult);
|
||||
|
||||
// THEN
|
||||
expect(userIdentity).toEqual(expectedResult);
|
||||
expect(service.isAuthenticated()).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('identity', () => {
|
||||
it('should call /account only once if last call have not returned', () => {
|
||||
// When I call
|
||||
service.identity().subscribe();
|
||||
// Once more
|
||||
service.identity().subscribe();
|
||||
// Then there is only request
|
||||
httpMock.expectOne({ method: 'GET' });
|
||||
});
|
||||
|
||||
it('should call /account only once if not logged out after first authentication and should call /account again if user has logged out', () => {
|
||||
// Given the user is authenticated
|
||||
service.identity().subscribe();
|
||||
httpMock.expectOne({ method: 'GET' }).flush({});
|
||||
|
||||
// When I call
|
||||
service.identity().subscribe();
|
||||
|
||||
// Then there is no second request
|
||||
httpMock.expectNone({ method: 'GET' });
|
||||
|
||||
// When I log out
|
||||
service.authenticate(null);
|
||||
// and then call
|
||||
service.identity().subscribe();
|
||||
|
||||
// Then there is a new request
|
||||
httpMock.expectOne({ method: 'GET' });
|
||||
});
|
||||
|
||||
describe('navigateToStoredUrl', () => {
|
||||
it('should navigate to the previous stored url post successful authentication', () => {
|
||||
// GIVEN
|
||||
mockStorageService.getUrl = jest.fn(() => 'admin/users?page=0');
|
||||
|
||||
// WHEN
|
||||
service.identity().subscribe();
|
||||
httpMock.expectOne({ method: 'GET' }).flush({});
|
||||
|
||||
// THEN
|
||||
expect(mockStorageService.getUrl).toHaveBeenCalledTimes(1);
|
||||
expect(mockStorageService.clearUrl).toHaveBeenCalledTimes(1);
|
||||
expect(mockRouter.navigateByUrl).toHaveBeenCalledWith('admin/users?page=0');
|
||||
});
|
||||
|
||||
it('should not navigate to the previous stored url when authentication fails', () => {
|
||||
// WHEN
|
||||
service.identity().subscribe();
|
||||
httpMock.expectOne({ method: 'GET' }).error(new ErrorEvent(''));
|
||||
|
||||
// THEN
|
||||
expect(mockStorageService.getUrl).not.toHaveBeenCalled();
|
||||
expect(mockStorageService.clearUrl).not.toHaveBeenCalled();
|
||||
expect(mockRouter.navigateByUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not navigate to the previous stored url when no such url exists post successful authentication', () => {
|
||||
// GIVEN
|
||||
mockStorageService.getUrl = jest.fn(() => null);
|
||||
|
||||
// WHEN
|
||||
service.identity().subscribe();
|
||||
httpMock.expectOne({ method: 'GET' }).flush({});
|
||||
|
||||
// THEN
|
||||
expect(mockStorageService.getUrl).toHaveBeenCalledTimes(1);
|
||||
expect(mockStorageService.clearUrl).not.toHaveBeenCalled();
|
||||
expect(mockRouter.navigateByUrl).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasAnyAuthority', () => {
|
||||
describe('hasAnyAuthority string parameter', () => {
|
||||
it('should return false if user is not logged', () => {
|
||||
const hasAuthority = service.hasAnyAuthority(Authority.USER);
|
||||
expect(hasAuthority).toBe(false);
|
||||
});
|
||||
|
||||
it('should return false if user is logged and has not authority', () => {
|
||||
service.authenticate(accountWithAuthorities([Authority.USER]));
|
||||
|
||||
const hasAuthority = service.hasAnyAuthority(Authority.ADMIN);
|
||||
|
||||
expect(hasAuthority).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if user is logged and has authority', () => {
|
||||
service.authenticate(accountWithAuthorities([Authority.USER]));
|
||||
|
||||
const hasAuthority = service.hasAnyAuthority(Authority.USER);
|
||||
|
||||
expect(hasAuthority).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('hasAnyAuthority array parameter', () => {
|
||||
it('should return false if user is not logged', () => {
|
||||
const hasAuthority = service.hasAnyAuthority([Authority.USER]);
|
||||
expect(hasAuthority).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should return false if user is logged and has not authority', () => {
|
||||
service.authenticate(accountWithAuthorities([Authority.USER]));
|
||||
|
||||
const hasAuthority = service.hasAnyAuthority([Authority.ADMIN]);
|
||||
|
||||
expect(hasAuthority).toBe(false);
|
||||
});
|
||||
|
||||
it('should return true if user is logged and has authority', () => {
|
||||
service.authenticate(accountWithAuthorities([Authority.USER]));
|
||||
|
||||
const hasAuthority = service.hasAnyAuthority([Authority.USER, Authority.ADMIN]);
|
||||
|
||||
expect(hasAuthority).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,77 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable, ReplaySubject, of } from 'rxjs';
|
||||
import { shareReplay, tap, catchError } from 'rxjs/operators';
|
||||
|
||||
import { StateStorageService } from 'app/core/auth/state-storage.service';
|
||||
import { ApplicationConfigService } from '../config/application-config.service';
|
||||
import { Account } from 'app/core/auth/account.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AccountService {
|
||||
private userIdentity: Account | null = null;
|
||||
private authenticationState = new ReplaySubject<Account | null>(1);
|
||||
private accountCache$?: Observable<Account> | null;
|
||||
|
||||
constructor(
|
||||
private http: HttpClient,
|
||||
private stateStorageService: StateStorageService,
|
||||
private router: Router,
|
||||
private applicationConfigService: ApplicationConfigService
|
||||
) {}
|
||||
|
||||
authenticate(identity: Account | null): void {
|
||||
this.userIdentity = identity;
|
||||
this.authenticationState.next(this.userIdentity);
|
||||
if (!identity) {
|
||||
this.accountCache$ = null;
|
||||
}
|
||||
}
|
||||
|
||||
hasAnyAuthority(authorities: string[] | string): boolean {
|
||||
if (!this.userIdentity) {
|
||||
return false;
|
||||
}
|
||||
if (!Array.isArray(authorities)) {
|
||||
authorities = [authorities];
|
||||
}
|
||||
return this.userIdentity.authorities.some((authority: string) => authorities.includes(authority));
|
||||
}
|
||||
|
||||
identity(force?: boolean): Observable<Account | null> {
|
||||
if (!this.accountCache$ || force) {
|
||||
this.accountCache$ = this.fetch().pipe(
|
||||
tap((account: Account) => {
|
||||
this.authenticate(account);
|
||||
|
||||
this.navigateToStoredUrl();
|
||||
}),
|
||||
shareReplay()
|
||||
);
|
||||
}
|
||||
return this.accountCache$.pipe(catchError(() => of(null)));
|
||||
}
|
||||
|
||||
isAuthenticated(): boolean {
|
||||
return this.userIdentity !== null;
|
||||
}
|
||||
|
||||
getAuthenticationState(): Observable<Account | null> {
|
||||
return this.authenticationState.asObservable();
|
||||
}
|
||||
|
||||
private fetch(): Observable<Account> {
|
||||
return this.http.get<Account>(this.applicationConfigService.getEndpointFor('api/account'));
|
||||
}
|
||||
|
||||
private navigateToStoredUrl(): void {
|
||||
// previousState can be set in the authExpiredInterceptor and in the userRouteAccessService
|
||||
// if login is successful, go to stored previousState and clear previousState
|
||||
const previousUrl = this.stateStorageService.getUrl();
|
||||
if (previousUrl) {
|
||||
this.stateStorageService.clearUrl();
|
||||
this.router.navigateByUrl(previousUrl);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpHeaders } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { ApplicationConfigService } from '../config/application-config.service';
|
||||
import { Login } from 'app/login/login.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuthServerProvider {
|
||||
constructor(private http: HttpClient, private applicationConfigService: ApplicationConfigService) {}
|
||||
|
||||
login(credentials: Login): Observable<{}> {
|
||||
const data =
|
||||
`username=${encodeURIComponent(credentials.username)}` +
|
||||
`&password=${encodeURIComponent(credentials.password)}` +
|
||||
`&remember-me=${credentials.rememberMe ? 'true' : 'false'}` +
|
||||
'&submit=Login';
|
||||
|
||||
const headers = new HttpHeaders().set('Content-Type', 'application/x-www-form-urlencoded');
|
||||
|
||||
return this.http.post(this.applicationConfigService.getEndpointFor('api/authentication'), data, { headers });
|
||||
}
|
||||
|
||||
logout(): Observable<void> {
|
||||
// logout from the server
|
||||
return this.http.post(this.applicationConfigService.getEndpointFor('api/logout'), {}).pipe(
|
||||
map(() => {
|
||||
// to get a new csrf token call the api
|
||||
this.http.get(this.applicationConfigService.getEndpointFor('api/account')).subscribe();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class StateStorageService {
|
||||
private previousUrlKey = 'previousUrl';
|
||||
private authenticationKey = 'jhi-authenticationToken';
|
||||
|
||||
storeUrl(url: string): void {
|
||||
sessionStorage.setItem(this.previousUrlKey, JSON.stringify(url));
|
||||
}
|
||||
|
||||
getUrl(): string | null {
|
||||
const previousUrl = sessionStorage.getItem(this.previousUrlKey);
|
||||
return previousUrl ? (JSON.parse(previousUrl) as string | null) : previousUrl;
|
||||
}
|
||||
|
||||
clearUrl(): void {
|
||||
sessionStorage.removeItem(this.previousUrlKey);
|
||||
}
|
||||
|
||||
storeAuthenticationToken(authenticationToken: string, rememberMe: boolean): void {
|
||||
authenticationToken = JSON.stringify(authenticationToken);
|
||||
this.clearAuthenticationToken();
|
||||
if (rememberMe) {
|
||||
localStorage.setItem(this.authenticationKey, authenticationToken);
|
||||
} else {
|
||||
sessionStorage.setItem(this.authenticationKey, authenticationToken);
|
||||
}
|
||||
}
|
||||
|
||||
getAuthenticationToken(): string | null {
|
||||
const authenticationToken = localStorage.getItem(this.authenticationKey) ?? sessionStorage.getItem(this.authenticationKey);
|
||||
return authenticationToken ? (JSON.parse(authenticationToken) as string | null) : authenticationToken;
|
||||
}
|
||||
|
||||
clearAuthenticationToken(): void {
|
||||
sessionStorage.removeItem(this.authenticationKey);
|
||||
localStorage.removeItem(this.authenticationKey);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue