removing JHipster

This commit is contained in:
Michael Hoennig 2022-07-22 13:31:37 +02:00
parent 31cd92f3be
commit f2d0fbe67a
747 changed files with 2225 additions and 92268 deletions

View File

@ -18,7 +18,3 @@ insert_final_newline = true
[*.md]
trim_trailing_whitespace = false
[package.json]
indent_style = space
indent_size = 2

View File

@ -1,5 +0,0 @@
{
"hooks": {
"pre-commit": "lint-staged"
}
}

View File

@ -1,61 +0,0 @@
{
"name": "Asset",
"fields": [
{
"fieldName": "documentDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "valueDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "action",
"fieldType": "AssetAction",
"fieldValues": "PAYMENT,HANDOVER,ADOPTION,LOSS,CLEARING,PAYBACK",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "amount",
"fieldType": "BigDecimal",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "remark",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 160
}
],
"relationships": [
{
"relationshipType": "many-to-one",
"otherEntityName": "membership",
"otherEntityRelationshipName": "asset",
"relationshipValidateRules": "required",
"relationshipName": "membership",
"otherEntityField": "admissionDocumentDate"
}
],
"changelogDate": "20190507105335",
"entityTableName": "asset",
"dto": "mapstruct",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,154 +0,0 @@
{
"name": "Customer",
"fields": [
{
"fieldName": "reference",
"fieldType": "Integer",
"fieldValidateRules": [
"required",
"unique",
"min",
"max"
],
"fieldValidateRulesMin": 10000,
"fieldValidateRulesMax": 99999
},
{
"fieldName": "prefix",
"fieldType": "String",
"fieldValidateRules": [
"required",
"maxlength",
"unique",
"pattern"
],
"fieldValidateRulesMaxlength": 3,
"fieldValidateRulesPattern": "[a-z][a-z0-9]+"
},
{
"fieldName": "name",
"fieldType": "String",
"fieldValidateRules": [
"required",
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "kind",
"fieldType": "CustomerKind",
"fieldValues": "NATURAL,LEGAL",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "birthDate",
"fieldType": "LocalDate"
},
{
"fieldName": "birthPlace",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "registrationCourt",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "registrationNumber",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "vatRegion",
"fieldType": "VatRegion",
"fieldValues": "DOMESTIC,EU,OTHER",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "vatNumber",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 40
},
{
"fieldName": "contractualSalutation",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "contractualAddress",
"fieldType": "String",
"fieldValidateRules": [
"required",
"maxlength"
],
"fieldValidateRulesMaxlength": 400
},
{
"fieldName": "billingSalutation",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 80
},
{
"fieldName": "billingAddress",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 400
},
{
"fieldName": "remark",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 160
}
],
"relationships": [
{
"relationshipType": "one-to-many",
"otherEntityName": "membership",
"otherEntityRelationshipName": "customer",
"relationshipName": "membership"
},
{
"relationshipType": "one-to-many",
"otherEntityName": "sepaMandate",
"otherEntityRelationshipName": "customer",
"relationshipName": "sepamandate"
}
],
"changelogDate": "20190507105332",
"entityTableName": "customer",
"dto": "mapstruct",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,66 +0,0 @@
{
"name": "Membership",
"fields": [
{
"fieldName": "admissionDocumentDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "cancellationDocumentDate",
"fieldType": "LocalDate"
},
{
"fieldName": "memberFromDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "memberUntilDate",
"fieldType": "LocalDate"
},
{
"fieldName": "remark",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 160
}
],
"relationships": [
{
"relationshipType": "one-to-many",
"otherEntityName": "share",
"otherEntityRelationshipName": "membership",
"relationshipName": "share"
},
{
"relationshipType": "one-to-many",
"otherEntityName": "asset",
"otherEntityRelationshipName": "membership",
"relationshipName": "asset"
},
{
"relationshipType": "many-to-one",
"otherEntityName": "customer",
"otherEntityRelationshipName": "membership",
"relationshipValidateRules": "required",
"relationshipName": "customer",
"otherEntityField": "prefix"
}
],
"changelogDate": "20190507105333",
"entityTableName": "membership",
"dto": "mapstruct",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,84 +0,0 @@
{
"name": "SepaMandate",
"fields": [
{
"fieldName": "reference",
"fieldType": "String",
"fieldValidateRules": [
"maxlength",
"unique",
"required"
],
"fieldValidateRulesMaxlength": 40
},
{
"fieldName": "iban",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 34
},
{
"fieldName": "bic",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 11
},
{
"fieldName": "grantingDocumentDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "revokationDocumentDate",
"fieldType": "LocalDate"
},
{
"fieldName": "validFromDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "validUntilDate",
"fieldType": "LocalDate"
},
{
"fieldName": "lastUsedDate",
"fieldType": "LocalDate"
},
{
"fieldName": "remark",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 160
}
],
"relationships": [
{
"relationshipType": "many-to-one",
"otherEntityName": "customer",
"otherEntityRelationshipName": "sepamandate",
"relationshipValidateRules": "required",
"relationshipName": "customer",
"otherEntityField": "prefix"
}
],
"changelogDate": "20190507105336",
"entityTableName": "sepa_mandate",
"dto": "mapstruct",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,61 +0,0 @@
{
"name": "Share",
"fields": [
{
"fieldName": "documentDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "valueDate",
"fieldType": "LocalDate",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "action",
"fieldType": "ShareAction",
"fieldValues": "SUBSCRIPTION,CANCELLATION",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "quantity",
"fieldType": "Integer",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "remark",
"fieldType": "String",
"fieldValidateRules": [
"maxlength"
],
"fieldValidateRulesMaxlength": 160
}
],
"relationships": [
{
"relationshipType": "many-to-one",
"otherEntityName": "membership",
"otherEntityRelationshipName": "share",
"relationshipValidateRules": "required",
"relationshipName": "membership",
"otherEntityField": "admissionDocumentDate"
}
],
"changelogDate": "20190507105334",
"entityTableName": "share",
"dto": "mapstruct",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,47 +0,0 @@
{
"name": "UserRoleAssignment",
"fields": [
{
"fieldName": "entityTypeId",
"fieldType": "String",
"fieldValidateRules": [
"required",
"maxlength"
],
"fieldValidateRulesMaxlength": 32
},
{
"fieldName": "entityObjectId",
"fieldType": "Long",
"fieldValidateRules": [
"required"
]
},
{
"fieldName": "assignedRole",
"fieldType": "UserRole",
"fieldValues": "HOSTMASTER,ADMIN,SUPPORTER,CONTRACTUAL_CONTACT,FINANCIAL_CONTACT,TECHNICAL_CONTACT,CUSTOMER_USER",
"fieldValidateRules": [
"required"
]
}
],
"relationships": [
{
"relationshipType": "many-to-one",
"otherEntityName": "user",
"otherEntityRelationshipName": "required",
"relationshipName": "user",
"otherEntityField": "login"
}
],
"changelogDate": "20190507105342",
"entityTableName": "user_role_assignment",
"dto": "no",
"pagination": "infinite-scroll",
"service": "serviceClass",
"jpaMetamodelFiltering": true,
"fluentMethods": true,
"clientRootFolder": "",
"applications": "*"
}

View File

@ -1,3 +0,0 @@
node_modules
target
package-lock.json

View File

@ -1,12 +0,0 @@
# Prettier configuration
printWidth: 140
singleQuote: true
tabWidth: 4
useTabs: false
# js and ts rules:
arrowParens: avoid
# jsx and tsx rules:
jsxBracketSameLine: false

View File

@ -1,38 +0,0 @@
{
"generator-jhipster": {
"promptValues": {
"packageName": "org.hostsharing.hsadminng",
"nativeLanguage": "de"
},
"jhipsterVersion": "5.8.2",
"applicationType": "monolith",
"baseName": "hsadminNg",
"packageName": "org.hostsharing.hsadminng",
"packageFolder": "org/hostsharing/hsadminng",
"serverPort": "8080",
"authenticationType": "jwt",
"cacheProvider": "ehcache",
"enableHibernateCache": false,
"websocket": false,
"databaseType": "sql",
"devDatabaseType": "h2Memory",
"prodDatabaseType": "postgresql",
"searchEngine": false,
"messageBroker": false,
"serviceDiscoveryType": false,
"buildTool": "gradle",
"enableSwaggerCodegen": true,
"jwtSecretKey": "ZDFlMDUzODIzMTUzZDEwZjExN2E5ZjAzY2VhZmYzNDE1YjhlYWUxZGRhMGU3ODZiNjRkNjVlNzEwZjExYWY4YzczM2NlYzI5YWE1OTRkNWM0YThlYjZjZjA5Zjc5YWJkOTgzYjdhZjQxZWQyZGUyYjFlYjI5ZDE3NmE4M2UzYjQ=",
"clientFramework": "angularX",
"useSass": false,
"clientPackageManager": "npm",
"testFrameworks": ["cucumber"],
"jhiPrefix": "jhi",
"entitySuffix": "",
"dtoSuffix": "DTO",
"otherModules": [],
"enableTranslation": true,
"nativeLanguage": "de",
"languages": ["de", "en"]
}
}

18
Glossary.md Normal file
View File

@ -0,0 +1,18 @@
# hsadminNg Glossary
### Business Object
Represents an object from the
### Tenant
The RBAC
### RBAC
abbreviation for *Role Based Access Control*
### Role Based Access Control (RBAC)
A system to control access to business objects by defining users, roles, and permissions.
For more information see

View File

@ -1,196 +0,0 @@
# hsadminNg
This application was generated using JHipster 5.8.2, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v5.8.2](https://www.jhipster.tech/documentation-archive/v5.8.2).
## 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 [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.
./gradlew
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.
### Service workers
Service workers are commented by default, to enable them please uncomment the following code.
- The service worker registering script in index.html
```html
<script>
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('./service-worker.js').then(function() {
console.log('Service Worker Registered');
});
}
</script>
```
Note: workbox creates the respective service worker and dynamically generate the `service-worker.js`
### 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/vendor.ts](src/main/webapp/app/vendor.ts) file:
```
import 'leaflet/dist/leaflet.js';
```
Edit [src/main/webapp/content/css/vendor.css](src/main/webapp/content/css/vendor.css) file:
```
@import '~leaflet/dist/leaflet.css';
```
Note: there are still 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
### Doing API-First development using openapi-generator
[OpenAPI-Generator]() is configured for this application. You can generate API code from the `src/main/resources/swagger/api.yml` definition file by running:
```bash
./gradlew openApiGenerate
```
Then implements the generated delegate classes with `@Service` classes.
To edit the `api.yml` definition file, you can use a tool such as [Swagger-Editor](). Start a local instance of the swagger-editor using docker by running: `docker-compose -f src/main/docker/swagger-editor.yml up -d`. The editor will then be reachable at [http://localhost:7742](http://localhost:7742).
Refer to [Doing API-First development][] for more details.
## Building for production
To optimize the hsadminNg application for production, run:
./gradlew -Pprod clean bootWar
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 build/libs/*.war
Then navigate to [http://localhost:8080](http://localhost:8080) in your browser.
Refer to [Using JHipster in production][] for more details.
## Testing
To launch your application's tests, run:
./gradlew test
### Client tests
Unit tests are run by [Jest][] and written with [Jasmine][]. 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
```
Then, run a Sonar analysis:
```
./gradlew -Pprod clean test sonarqube
```
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.
For example, to start a postgresql database in a docker container, run:
docker-compose -f src/main/docker/postgresql.yml up -d
To stop it and remove the container, run:
docker-compose -f src/main/docker/postgresql.yml down
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:
./gradlew bootWar -Pprod jibDockerBuild
Then run:
docker-compose -f src/main/docker/app.yml up -d
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 5.8.2 archive]: https://www.jhipster.tech/documentation-archive/v5.8.2
[using jhipster in development]: https://www.jhipster.tech/documentation-archive/v5.8.2/development/
[using docker and docker-compose]: https://www.jhipster.tech/documentation-archive/v5.8.2/docker-compose
[using jhipster in production]: https://www.jhipster.tech/documentation-archive/v5.8.2/production/
[running tests page]: https://www.jhipster.tech/documentation-archive/v5.8.2/running-tests/
[code quality page]: https://www.jhipster.tech/documentation-archive/v5.8.2/code-quality/
[setting up continuous integration]: https://www.jhipster.tech/documentation-archive/v5.8.2/setting-up-ci/
[node.js]: https://nodejs.org/
[yarn]: https://yarnpkg.org/
[webpack]: https://webpack.github.io/
[angular cli]: https://cli.angular.io/
[browsersync]: http://www.browsersync.io/
[jest]: https://facebook.github.io/jest/
[jasmine]: http://jasmine.github.io/2.0/introduction.html
[protractor]: https://angular.github.io/protractor/
[leaflet]: http://leafletjs.com/
[definitelytyped]: http://definitelytyped.org/
[openapi-generator]: https://openapi-generator.tech
[swagger-editor]: http://editor.swagger.io
[doing api-first development]: https://www.jhipster.tech/documentation-archive/v5.8.2/doing-api-first-development/

57
Jenkinsfile vendored
View File

@ -1,57 +0,0 @@
#!/usr/bin/env groovy
node {
withEnv(["PATH=$HOME/bin:$PATH"]) {
stage('checkout') {
checkout scm
}
stage('check java') {
sh "java -version"
}
stage('clean+spotless') {
sh "chmod +x gradlew"
sh "./gradlew clean spotlessCheck --no-daemon"
}
stage('npm install') {
sh "./gradlew npm_install -PnodeInstall --no-daemon"
}
stage('backend tests') {
try {
sh "./gradlew test -PnodeInstall --no-daemon"
} catch (err) {
throw err
} finally {
junit '**/build/**/TEST-*.xml'
}
}
stage('backend check') {
try {
sh "./gradlew check -PnodeInstall --no-daemon"
} catch (err) {
throw err
} finally {
archiveArtifacts artifacts: '**/build/reports/jacoco/test/html/', fingerprint: true
}
}
stage('frontend tests') {
try {
sh "./gradlew npm_run_test -PnodeInstall --no-daemon"
} catch (err) {
throw err
} finally {
junit '**/build/test-results/TESTS-*.xml'
}
}
stage('packaging') {
sh "./gradlew bootWar -x test -Pprod -PnodeInstall --no-daemon"
archiveArtifacts artifacts: '**/build/libs/*.war', fingerprint: true
}
}
}

363
README.md
View File

@ -1,350 +1,77 @@
# hsadminNg Development
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
- [Setting up the Development Environment](#setting-up-the-development-environment)
- [Frequent Tasks](#frequent-tasks)
- [Building the Application with Test Execution](#building-the-application-with-test-execution)
- [Starting the Application](#starting-the-application)
- [Running JUnit tests with branch coverage](#running-junit-tests-with-branch-coverage)
- [HOWTO Commits](#howto-commits)
- [Creating HOWTO Commits](#creating-howto-commits)
- [Special Build Tasks](#special-build-tasks)
- [Spotless Formatting](#spotless-formatting)
- [Mutation Testing PiTest](#mutation-testing-pitest)
- [Git Workflow for JHipster Generator](#git-workflow-for-jhipster-generator)
- [Generating the Table of Contents for Markdown](#generating-the-table-of-contents-for-markdown)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
## Setting up the Development Environment
You'll often need to execute `./gradlew`, therefore we suggest to define this alias:
### PostgreSQL Server
alias gw='./gradlew'
So far the spike contains almost only PostgreSQL Code.
All you need so far, is a PostgreSQL database, for now with full admin rights.
The easiest way to set it up is using docker:
TODO: Instructions for setting up the dev environment from scratch.
Initially, pull an image compatible to current PostgreSQL version of Hostsharing:
## Frequent Tasks
docker pull postgres:13.7-bullseye
### Building the Application with Test Execution
Create and run a container with the given PostgreSQL version:
gw build
docker run --name hsadmin-ng-postgres -e POSTGRES_PASSWORD=password -p 5432:5432 -d postgres:13.7-bullseye
### Starting the Application
To check if the PostgreSQL container is running, the following command should list a container with the name "hsadmin-ng-postgres":
To use an **H2 in-memory database** populated with sample-data.
docker container ls
gw bootRun
Stop the PostgreSQL container:
docker stop hsadmin-ng-postgres
To use an **H2 file-based database**, start the application with the h2file profile:
Start the PostgreSQL container again:
gw bootRun -Ph2file
gw bootRun -Ph2file -Psample-data # populated with sample data
docker container start hsadmin-ng-postgres
To use a **local Postgres database**, first prepare your environment:
Remove the PostgreSQL container:
export HSADMINNG_DB_URL='jdbc:postgresql://localhost:5432/DBNAME'
export HSADMINNG_DB_USER='DBUSER'
export HSADMINNG_DB_PASS='DBPASS'
docker rm hsadmin-ng-postgres
Where `DBNAME`, `DBUSER` and `DBPASS` are replaced by your credentials.
After the PostgreSQL container is removed, you need to create it again as shown in "Create and run ..." above.
Then start the application with the pgsql profile:
### Markdown with PlantUML plugin
gw bootRun -Ppgsql
gw bootRun -Ppgsql -Psample-data # populated with sample data
Can you see the following diagram?
To use a **remote Postgres database** on a Hostsharing server,
```plantuml
@startuml
me -> you: Can you see this diagram?
you -> me: Sorry, I don't :-(
me -> you: Install some tooling!
@enduml
```
autossh -M 0 -o "ServerAliveInterval 60" -o "ServerAliveCountMax 3" \
-f -N -L 55432:127.0.0.1:5432 "xyz00@xyz.hostsharing.net"
If not, you need to install some tooling.
Then prepare your environment, e.g. like this:
#### for IntelliJ IDEA (or derived products)
export HSADMINNG_DB_URL='jdbc:postgresql://localhost:55432/xyz00_hsadminng'
export HSADMINNG_DB_USER='xyz00_hsadminng'
export HSADMINNG_DB_PASS='whatever'
You just need the bundled Markdown plugin enabled and install and activate the PlantUML plugin in its settings:
In all cases, you can also **specify the port** to used for the application via environment:
jetbrains://idea/settings?name=Languages+%26+Frameworks--Markdown
SERVER_PORT=8081 gw bootRun ...
You might also need to install Graphviz on your operating system.
For Debian-based Linux systems this might work:
For starting the JVM of the application in **debug-mode**, add `--debug-jvm` to any of the options above, e.g.
```sh
sudo apt install graphviz
```
gw bootRun -Ppgsql -Psample-data --debug-jvm
### Running JUnit tests with branch coverage
### Ubuntu Linux command line
#### for IntelliJ IDEA
```sh
sudo apt-get install pandoc texlive-latex-base texlive-fonts-recommended texlive-extra-utils texlive-latex-extra pandoc-plantuml-filter
```
see: https://confluence.jetbrains.com/display/IDEADEV/IDEA+Coverage+Runner
```sh
pandoc --filter pandoc-plantuml rbac.md -o rbac.pdf
```
Either apply it to specific test configurations or,
better, delete the previous test configurations and amend the JUnit template.
### for other IDEs / operating systems
## HOWTO Commits
There are git tags on some commits which show how to add certain features.
Find all of such tags with:
git tag | grep HOWTO
### Creating HOWTO Commits
If you want to add such a commit, make sure that it contains no clutter
(no changes which are not necessary for whatever the commit is about to explain),
and is complete with all unit tests, code coverage, pitest and other checks.
Otherwise the next developer would run into the same problems again.
One way to keep the commit clean, is to develop it on a local branch.
If any other changes (e.g. bugfixes, API extensions etc.) are necessary,
apply these only to the master or cherry-pick just these to the master,
then rebase your local branch. Do not forget to run all checks locally:
gw clean check pitest # might need over an hour
(Check the PiTest section for speeding up mutation testing.)
To create and push a new tag use:
git tag HOWTO-... master
git push origin HOWTO-...
To moved an existing the tag to another commit (here current master again), do this:
git tag --force HOWTO-... master
git push --force origin HOWTO-...
## Special Build Tasks
Besides common build tasks like `build`, `test` or `bootRun` this projects has some not so common tasks which are explained in this section.
### Spotless Formatting
To make sure that no IDE auto-formatter destroys the git history of any file and
especially to avoid merge conflicts from JHipster generated files after these had been changed,
we are using a standard formatter enforced by _spotless_, which is based on the standard Eclipse formatter.
The rules can be checked and applied with these commands:
gw spotlessCheck
gw spotlessApply
The spotlessCheck task is included as an early step in our Jenkins build pipeline.
Therefore wrong formatting is automatically detected.
Our configuration can be found under the directory `cfg/spotless`.
Currently we only have specific rules for _\*.java_-files and their import-order.
#### Our Changes to the Standard Eclipse Formatter
We amended the Standard Eclipse Formatter in these respects:
- Lines of code are never joined, thus the developer has control about linebreaks,
which is important for readability in some implementations like toString().
- Lines in comments are never joined either, because that often destroys readable stucture.
- Parts of files can be excluded from getting formatted, by using `@formatter:off` and `@formatter:on` in a comment.
See for example in class `SecurityConfiguration`.
#### Pre-Commit Hook
If you like, you could add this code to the _pre-commit or \_pre_push_ hook\_ in your `.git/hooks` directory:
if ! ./gradlew spotlessCheck; then
exit 1
fi
#### The Tagged Spotless Commit
The commit which introduces the spotless configuration is tagged.
Through this tag it can easily be cherry-picked in the JHipster workflow.
If you need to amend the commit tagged 'spotless', e.g. to change the spotless configuration,
it can be done with these steps:
git tag REAL-HEAD
git reset --hard spotless^
git cherry-pick -n spotless
...
git add .
# do NOT run: gw spotlessApply yet!
# for the case you have a commit hook which runs spotlessCheck:
git commit --no-verify
git tag --force spotless
git push --no-verify origin spotless
git reset --hard REAL-HEAD
git tag -d REAL-HEAD
### Mutation Testing PiTest
./gradlew pitest
Runs (almost) all JUnit tests under mutation testing.
Mutation testing is a means to determine the quality of the tests.
On Jenkins, the results can be found in the build artifacts under:
- https://ci.hostsharing.net/job/hsadmin-ng-pitest/XX/artifact/build/reports/pitest/index.html
Where XX is the build number. Or for the latest build under:
- https://ci.hostsharing.net/job/hsadmin-ng-pitest/lastCompletedBuild/artifact/build/reports/pitest/index.html
#### Some Background Information on Mutation Testing
PiTest does it with these steps:
- initially PiTest checks which production code is executed by which tests
- if the tests don't pass, it stops
- otherwise the production code is 'mutated' and PiTest checks whether this makes a test fail ('mutant killed')
- Finally it checks thresholds for coverage and mutant killing.
More information about can be found here:
- PiTest: http://pitest.org/
- gradle-plugin: https://gradle-pitest-plugin.solidsoft.info/
#### How to Configure PiTest
These thresholds can be configured in `build.gradle`,
but we should generally not lower these.
There is also a list of excluded files, all generated by JHipster or MapStruct, not containing any changes by us.
As you might figure, mutation testing is CPU-hungry.
To limit load in our Jenkins build server, it only uses 2 CPU threads, thus it needs over an hour.
If you want to spend more CPU threads on your local system, you can change that via command line:
gw pitest -Doverride.pitest.threads=7
I suggest to leave one CPU thread for other tasks or your might lag extremely.
### Git Workflow for JHipster Generator
The following workflow steps make sure that
- JHipster re-imports work properly,
- the git history of changes to the JDL-files, the generated code and the master is comprehensible,
- and merging newly generated code to the master branch is smooth.
It uses a git branch `jhipster-generated` to track the history of the JDL model file and the generated source code.
Applying commits which contain non-generated changes to that branch breaks the normal git history for generated files.
Therefore, this documentation is also not available in that branch.
Thus:
**MANUAL STEP before starting:** Copy this workflow documentation, because this file will be gone once you switched the branch.
| WARNING: The following steps are just a guideline. You should understand what you are doing! |
| -------------------------------------------------------------------------------------------- |
#### 1. Preparing the `jhipster-generated` git Branch
This step assumes that the latest `*.jdl` files are on the `HEAD` of the `jhipster-generated` git branch.
On a re-import of a JDL-file, JHipster does not remove any generated classes which belong to entities deleted from the JDL-file.
Therefore, the project has to be reset to a clean state before changes to the JDL file can be re-imported.
We have not yet finally tested a simplified workflow for just adding new entities or properties.
A git tag `jdl-base` is assumed to sit on the base commit after the application was generated, but before any entities were imported.
git checkout jhipster-generated
git pull
git tag REAL-HEAD
git reset --hard jdl-base
git clean -f -d
git cherry-pick -n spotless
git reset --soft REAL-HEAD
git checkout REAL-HEAD src/main/jdl/customer.jdl
git checkout REAL-HEAD src/main/jdl/accessrights.jdl
git checkout REAL-HEAD src/main/jdl/... # once there are more
git tag -d REAL-HEAD
#### 2. Amending and Re-Importing the JDL
**MANUAL STEP:** First apply all necessary changes to the JDL files.
Then re-import like this:
# (Re-) Importing
jhipster import-jdl src/main/jdl/customer.jdl
jhipster import-jdl src/main/jdl/accessrights.jdl
jhipster import-jdl src/main/jdl/... # once there are more
For smoothly being able to merge, we need the same formatting in the generated code as on the master:
gw spotlessApply
#### 3. Committing our Changes
git add .
git commit -m"..."
#### 4. Merging our Changes to the `master` Branch
git checkout master
git pull
**MANUAL STEP:** If you've renamed any identifiers, use the refactoring feature of your IDE to rename in master as well.
To avoid oodles of merge-conflicts, you need to do that **BEFORE MERGING!**
Commit any of such changes, if any.
Now we can finally merge our changes to master.
git merge jhipster-generated
It's a good idea doing this step in an IDE because it makes conflict resolving much easier.
Typical merge conflicts stem from:
- Random numbers in test data of `*IntTest.java` files.
- Timestamps in Liquibase-xml-Files.
Now, I suggest to run all tests locally:
gw clean test
Once everything works again, we can push our new version:
git push
#### 5. General Aftermath
Think about which additional code could be effected by your JDL-changes!
Files which are not at all in the `jhipster-generated` branch, don't show conflicts even though they might need changes.
Here some examples for amendments to be done:
- in `historicization_*.xml`: the columns or their constraints
- `sampledata/*.xml/csv`
If you find more of such general cases, please add them here!
#### 6. Special Aftermath for new Entities
Because we have added quite some functionality, after introducing new entities, there is a lot more to amend.
Here some issues to consider:
- add sample-data for the new entity
- internal (Angular) frontend: add table filters
- internal (Angular) frontend: amend input fields for multiline, if applicable
- internal (Angular) frontend: check if dates are properly formatted
- \*Mapper: add displayLabel for entity itself and parents
- \*DTO: add access-right annotations with customized JSON serializer/deserializer
- Validator: implement entity-based validator and call it in the generated service
- external API: add new type to client library
WARNING: This list is most likely incomplete. Pleas add any new found issue!
For many of these issues look for HOWTO-commits in git or HOWTO comments in the source code.
### Generating the Table of Contents for Markdown
This README file contains a table of contents generated by _doctoc_.
It's quite simple to use:
npm install -g doctoc
doctoc --maxlevel 3 README.md
Further information can be found [https://github.com/thlorenz/doctoc/blob/master/README.md](on the _doctoc_ github page).
If you have figured out how it works, please add instructions above this section.

View File

@ -0,0 +1,160 @@
# Use VIEWs with JOIN into Permission-Assignments for Row-Level-Security
**Status:**
- [x] proposed by Michael Hönnig
- [ ] accepted by (Participants)
- [ ] rejected by (Participants)
- [ ] superseded by (superseding ADR)
## Context and Problem Statement
We need to decide how to apply the access rules defined in our RBAC system to the visibility of table rows for the accessing user.
The core problem here is, that in our RBAC system, determining the permissions of the accessing user has to consider a hierarchy of roles.
### Technical Background
The session variable `hsadminng.currentUser` contains the accessing (domain-level) user, which is unrelated to the PostgreSQL user).
Given is a stored function `isPermissionGrantedToSubject` which detects if the accessing user has a given permission (e.g. 'view').
Given is also a stored function `queryAllPermissionsOfSubjectId` which returns the flattened view to all permissions assigned to the given accessing user.
In the following code snippets `customer` is just an example domain table.
## Considered Options
* Perform Visibility-Checks programmatically in the Backend
* Add Visibility-Checks in the Backend
* POLICY with ENABLE ROW LEVEL SECURITY
* VIEW-RULE with ON SELECT DO INSTEAD
* VIEW with JOIN into Flattened Permissions
### Perform Visibility-Checks programmatically in the Backend
In this solution, the database ignores row level visibility and returns all rows which match a given query. Afterwards, the result is filtered programmatically with Java-code in the backend.
#### Advantages
Very flexible access, programmatic, rules could be implemented.
The role-hierarchy and permissions for currently logged-in users user could be cached in the backend.
The access logic can be tested in pure Java unit tests.
At least regarding this aspect, an in-memory database could be used for integration testing; though the recursive Role-evaluation uses PostgreSQL features anyway.
#### Disadvantages
It's inefficient when initial query is not very restrictive, e.g. as on overview pages in a frontend, which often show all accessible objects, large parts or even whole database tables need to be transferred from the database to the backend.
It's error-prone and security leaks can happen too easily, because after every query the access rights for all participating joins have to be considered.
### Add Visibility-Checks in the Backend
In this solution again, the database ignores row level visibility and returns all rows which match a given query. And the backend adds filter conditions to each query sent to the database.
#### Advantages
At least regarding this aspect, an in-memory database could be used for integration testing.
#### Disadvantages
It's error-prone and security leaks can happen too easily, because for every query the access rights for all participating joins have to be considered.
### POLICY with ENABLE ROW LEVEL SECURITY
For restricted DB-users, which are used by the backend, access to rows is filtered using a policy:
SET SESSION AUTHORIZATION DEFAULT;
CREATE ROLE restricted;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
ALTER TABLE customer ENABLE ROW LEVEL SECURITY;
CREATE POLICY customer_policy ON customer
FOR SELECT
TO restricted
USING (
isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId())
);
SET SESSION AUTHORIZATION restricted;
SET hsadminng.currentUser TO 'alex@example.com';
SELECT * from customer; -- will only return visible rows
#### Advantages
Using POLICY together with ENABLE ROW LEVEL SECURITY is the PostgreSQL native mechanism to control access to data on the role level. Therefore, it looked like an obvious and elegant solution.
Every access at from the backend is under access control at the database level.
### Disadvantages
Unfortunately security mechanisms in PostgreSQL prevent the query optimizer to work well beyond ownership barriers (session user vs. table owner) and a SELECT from a table with 1 million objects needed over 30 seconds with our hierarchical RBAC policy.
We are bound to PostgreSQL, including integration tests and testing the RBAC system itself.
### VIEW-RULE with ON SELECT DO INSTEAD
SET SESSION SESSION AUTHORIZATION DEFAULT;
CREATE VIEW cust_view AS
SELECT * FROM customer;
CREATE OR REPLACE RULE "_RETURN" AS
ON SELECT TO cust_view
DO INSTEAD
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId());
SET SESSION AUTHORIZATION restricted;
SET hsadminng.currentUser TO 'alex@example.com';
SELECT * from customer; -- will only return visible rows
#### Advantages
Every access at from the backend is under access control at the database level.
Also using ON UPDATE etc., original tables could be completely hidden from the backend, and thus improved security.
### Disadvantages
Unfortunately security mechanisms in PostgreSQL prevent the query optimizer to work well beyond ownership barriers (session user vs. table owner) and a SELECT from a table with 1 million objects needed over 30 seconds with our hierarchical RBAC policy.
We are bound to PostgreSQL, including integration tests and testing the RBAC system itself.
An extra view needed for every table.
### VIEW with JOIN into flattened permissions
We do not access the tables directly from the backend, but via views which join the flattened permissions
SET SESSION SESSION AUTHORIZATION DEFAULT;
CREATE OR REPLACE VIEW cust_view AS
SELECT c.id, c.reference, c.prefix
FROM customer AS c
JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
ON p.tableName='customer' AND p.rowId=c.id AND p.op='view';
GRANT ALL PRIVILEGES ON cust_view TO restricted;
SET SESSION SESSION AUTHORIZATION restricted;
SET hsadminng.currentUser TO 'alex@example.com';
SELECT * from cust_view; -- will only return visible rows
Alternatively the JOIN could also be applied in a "ON SELECT DO INSTEAD"-RULE, if there is any advantage for later features.
#### Advantages
Every access at from the backend is under access control at the database level.
No special PostgreSQL features needed; though the recursive Role-evaluation uses PostgreSQL features anyway.
Very fast, on my laptop a SELECT * FROM a table with 1 million rows just took about 50ms.
Also using ON UPDATE etc., original tables could be completely hidden from the backend, and thus improved security.
### Disadvantages
An extra view needed for every table.
## Decision Outcome
We chose the option **"VIEW with JOIN into flattened permissions"** because it supports the best combination of performance and security with almost no disadvantge.

View File

@ -1,39 +0,0 @@
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"hsadmin-ng": {
"root": "",
"sourceRoot": "src/main/webapp",
"projectType": "application",
"architect": {}
}
},
"defaultProject": "hsadmin-ng",
"cli": {
"packageManager": "npm"
},
"schematics": {
"@schematics/angular:component": {
"inlineStyle": true,
"inlineTemplate": false,
"spec": false,
"prefix": "jhi",
"styleExt": "css"
},
"@schematics/angular:directive": {
"spec": false,
"prefix": "jhi"
},
"@schematics/angular:guard": {
"spec": false
},
"@schematics/angular:pipe": {
"spec": false
},
"@schematics/angular:service": {
"spec": false
}
}
}

View File

@ -1,24 +0,0 @@
// Behaviour tests based on a deployed application.
task cucumberTest(type: Test) {
description = "Execute cucumber BDD tests."
group = "verification"
include '**/CucumberTest*'
// uncomment if the tests reports are not generated
// see https://github.com/jhipster/generator-jhipster/pull/2771 and https://github.com/jhipster/generator-jhipster/pull/4484
// ignoreFailures true
reports.html.enabled = false
}
check.dependsOn cucumberTest
task testReport(type: TestReport) {
destinationDir = file("$buildDir/reports/tests")
reportOn test
}
task cucumberTestReport(type: TestReport) {
destinationDir = file("$buildDir/reports/tests")
reportOn cucumberTest
}

View File

@ -1,84 +0,0 @@
// Checks code coverage of JUnit based tests.
apply plugin: 'jacoco'
jacoco {
toolVersion = "0.8.3a"
}
test.finalizedBy jacocoTestReport
check.dependsOn jacocoTestCoverageVerification
// Only for purely JHipster/MapStruct generated classes.
// Please do NOT add any self coded classes!
// Keep in mind, git will blame you ;-)
def jhipsterGeneratedClassesWithDecentCoverage = [
'org.hostsharing.hsadminng.repository.CustomAuditEventRepository',
'org.hostsharing.hsadminng.service.ContactQueryService',
'org.hostsharing.hsadminng.service.UserService',
'org.hostsharing.hsadminng.service.CustomerContactQueryService'
]
// Only for purely JHipster/MapStruct generated classes.
// Please do NOT add any self coded classes!
// Keep in mind, git will blame you ;-)
def jhipsterGeneratedClassesWithLowCoverage = [
'org.hostsharing.hsadminng.service.MailService',
'org.hostsharing.hsadminng.security.SecurityUtils',
'org.hostsharing.hsadminng.config.DefaultProfileUtil',
'org.hostsharing.hsadminng.config.WebConfigurer',
'org.hostsharing.hsadminng.web.rest.AccountResource',
'org.hostsharing.hsadminng.web.rest.errors.ExceptionTranslator',
'org.hostsharing.hsadminng.web.rest.errors.CustomParameterizedException',
'org.hostsharing.hsadminng.config.audit.AuditEventConverter',
'org.hostsharing.hsadminng.security.jwt.TokenProvider',
'org.hostsharing.hsadminng.aop.logging.LoggingAspect',
'org.hostsharing.hsadminng.HsadminNgApp',
'*.*QueryService',
'*.*Configuration',
'*MapperImpl',
'*Criteria',
'*_'
]
def specialExceptions = [
// lots of unreachable code due to error handling / verifications
'org.hostsharing.hsadminng.service.accessfilter.JSonAccessFilter',
'org.hostsharing.hsadminng.service.util.ReflectionUtil'
]
jacocoTestCoverageVerification {
violationRules {
rule {
element = 'CLASS'
limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
// Increasing the threshold is fine, decreasing is not.
// Keep in mind, git will blame you ;-)
minimum = 0.95
}
excludes = jhipsterGeneratedClassesWithDecentCoverage + jhipsterGeneratedClassesWithLowCoverage + specialExceptions
}
rule {
element = 'CLASS'
limit {
counter = 'BRANCH'
value = 'COVEREDRATIO'
minimum = 0.80
}
includes = jhipsterGeneratedClassesWithDecentCoverage
}
rule {
element = 'CLASS'
limit {
counter = 'LINE'
value = 'COVEREDRATIO'
minimum = 0.85
}
includes = specialExceptions
}
}
}

View File

@ -1,36 +0,0 @@
// PiTest based mutation testing
pitest {
targetClasses = ['org.hostsharing.hsadminng.*']
excludedClasses = [
// Unit Testing Spring configurations makes little sense in most cases.
'org.hostsharing.hsadminng.config.*',
'org.hostsharing.hsadminng.ApplicationWebXml',
'org.hostsharing.hsadminng.HsadminNgApp',
// Unit testing this would need PowerMock and
// blackbox testing of random values has little value.
'org.hostsharing.hsadminng.service.util.RandomUtil',
// The following are mostly generated classes,
// as soon as we amend these, consider removing the exclude.
'org.hostsharing.hsadminng.**Criteria',
'org.hostsharing.hsadminng.**MapperImpl',
'org.hostsharing.hsadminng.aop.logging.*',
'org.hostsharing.hsadminng.web.rest.vm.*',
'org.hostsharing.hsadminng.security.jwt.TokenProvider',
'org.hostsharing.hsadminng.web.api.*' // API helpers, not the API itself
]
threads = 2
// Do not set these limit lower! 96% each might sound great, but keep in mind:
// 91%*91% means that ~8% of the code are NOT properly covered by automated tests
// (100%-94%*96% = ~8%). Not counting defects which come through missing code :-)
coverageThreshold = 94
mutationThreshold = 96
outputFormats = ['XML', 'HTML']
timestampedReports = false
verbose = false
}

View File

@ -1,15 +0,0 @@
// apply and check standard formatting of files
apply plugin: "com.diffplug.gradle.spotless"
spotless {
// automatically format source files, see https://github.com/diffplug/spotless
java {
licenseHeader '// Licensed under Apache-2.0'
importOrderFile 'cfg/spotless/hsadminng.importorder'
eclipse().configFile 'cfg/spotless/eclipse_formatter.xml'
target 'src/main/**/*.java', 'src/test/**/*.java'
removeUnusedImports()
endWithNewline()
}
}

View File

@ -1,297 +0,0 @@
import org.gradle.internal.os.OperatingSystem
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven { url "http://repo.spring.io/plugins-release" }
maven { url "https://plugins.gradle.org/m2/" }
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:${spring_boot_version}"
classpath "io.spring.gradle:propdeps-plugin:0.0.10.RELEASE"
classpath "org.openapitools:openapi-generator-gradle-plugin:3.3.0"
classpath "gradle.plugin.com.gorylenko.gradle-git-properties:gradle-git-properties:1.5.2"
//jhipster-needle-gradle-buildscript-dependency - JHipster will add additional gradle build script plugins here
classpath "com.diffplug.spotless:spotless-plugin-gradle:3.22.0"
classpath 'org.owasp:dependency-check-gradle:4.0.2'
}
}
plugins {
id "org.sonarqube" version "2.6.2"
id "net.ltgt.apt-eclipse" version "0.19"
id "net.ltgt.apt-idea" version "0.19"
id "net.ltgt.apt" version "0.19"
id "io.spring.dependency-management" version "1.0.6.RELEASE"
id "com.moowork.node" version "1.2.0"
id 'org.liquibase.gradle' version '2.0.1'
id 'info.solidsoft.pitest' version '1.4.0'
//jhipster-needle-gradle-plugins - JHipster will add additional gradle plugins here
}
apply plugin: 'java'
apply plugin: 'org.owasp.dependencycheck'
sourceCompatibility=1.8
targetCompatibility=1.8
apply plugin: 'maven'
apply plugin: 'org.springframework.boot'
apply plugin: 'war'
apply plugin: 'propdeps'
apply plugin: 'com.moowork.node'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'idea'
apply from: 'build-jacoco.gradle'
apply from: 'build-pitest.gradle'
apply from: 'build-spotless.gradle'
idea {
module {
excludeDirs += files('node_modules')
}
}
dependencyManagement {
imports {
mavenBom 'io.github.jhipster:jhipster-dependencies:' + jhipster_dependencies_version
//jhipster-needle-gradle-dependency-management - JHipster will add additional dependencies management here
}
}
defaultTasks 'bootRun'
group = 'org.hostsharing.hsadminng'
version = '0.0.1-SNAPSHOT'
description = ''
bootWar {
mainClassName = 'org.hostsharing.hsadminng.HsadminNgApp'
}
war {
webAppDirName = 'build/www/'
enabled = true
extension = 'war.original'
}
springBoot {
mainClassName = 'org.hostsharing.hsadminng.HsadminNgApp'
}
if (OperatingSystem.current().isWindows()) {
// https://stackoverflow.com/questions/40037487/the-filename-or-extension-is-too-long-error-using-gradle
task classpathJar(type: Jar) {
dependsOn configurations.runtime
appendix = 'classpath'
doFirst {
manifest {
attributes 'Class-Path': configurations.runtime.files.collect {
it.toURI().toURL().toString().replaceFirst(/file:\/+/, '/').replaceAll(' ', '%20')
}.join(' ')
}
}
}
bootRun {
dependsOn classpathJar
doFirst {
classpath = files("$buildDir/classes/java/main", "$buildDir/resources/main", classpathJar.archivePath)
}
}
}
test {
exclude '**/CucumberTest*'
// uncomment if the tests reports are not generated
// see https://github.com/jhipster/generator-jhipster/pull/2771 and https://github.com/jhipster/generator-jhipster/pull/4484
// ignoreFailures true
reports.html.enabled = false
}
task cucumberTest(type: Test) {
description = "Execute cucumber BDD tests."
group = "verification"
include '**/CucumberTest*'
// uncomment if the tests reports are not generated
// see https://github.com/jhipster/generator-jhipster/pull/2771 and https://github.com/jhipster/generator-jhipster/pull/4484
// ignoreFailures true
reports.html.enabled = false
}
check.dependsOn cucumberTest
task testReport(type: TestReport) {
destinationDir = file("$buildDir/reports/tests")
reportOn test
}
task cucumberTestReport(type: TestReport) {
destinationDir = file("$buildDir/reports/tests")
reportOn cucumberTest
}
apply from: 'gradle/docker.gradle'
apply from: 'gradle/sonar.gradle'
apply from: 'gradle/swagger.gradle'
//jhipster-needle-gradle-apply-from - JHipster will add additional gradle scripts to be applied here
if (project.hasProperty('prod')) {
apply from: 'gradle/profile_prod.gradle'
} else {
apply from: 'gradle/profile_dev.gradle'
}
if (!project.hasProperty('runList')) {
project.ext.runList = 'main'
}
project.ext.diffChangelogFile = 'src/main/resources/config/liquibase/changelog/' + new Date().format('yyyyMMddHHmmss') + '_changelog.xml'
liquibase {
activities {
main {
driver ''
url ''
username 'hsadminNg'
password ''
changeLogFile 'src/main/resources/config/liquibase/master.xml'
defaultSchemaName ''
logLevel 'debug'
classpath 'src/main/resources/'
if (project.hasProperty('sample-data')) {
contexts 'sample-data'
}
}
diffLog {
driver ''
url ''
username 'hsadminNg'
password ''
changeLogFile project.ext.diffChangelogFile
referenceUrl 'hibernate:spring:org.hostsharing.hsadminng.domain?dialect=&amp;hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&amp;hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy'
defaultSchemaName ''
logLevel 'debug'
classpath "$buildDir/classes/java/main"
}
}
runList = project.ext.runList
}
configurations {
providedRuntime
compile.exclude module: "spring-boot-starter-tomcat"
}
repositories {
mavenLocal()
mavenCentral()
jcenter()
//jhipster-needle-gradle-repositories - JHipster will add additional repositories
}
dependencies {
// Use ", version: jhipster_dependencies_version, changing: true" if you want
// to use a SNAPSHOT release instead of a stable release
compile group: "io.github.jhipster", name: "jhipster-framework"
compile "org.springframework.boot:spring-boot-starter-cache"
compile "io.dropwizard.metrics:metrics-core"
compile 'io.micrometer:micrometer-registry-prometheus'
compile "net.logstash.logback:logstash-logback-encoder"
compile "com.fasterxml.jackson.datatype:jackson-datatype-hppc"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310"
compile "com.fasterxml.jackson.datatype:jackson-datatype-hibernate5"
compile "com.fasterxml.jackson.core:jackson-annotations"
compile "com.fasterxml.jackson.core:jackson-databind"
compile "com.fasterxml.jackson.module:jackson-module-afterburner"
compile "javax.cache:cache-api"
compile "org.hibernate:hibernate-core"
compile "com.zaxxer:HikariCP"
compile "org.apache.commons:commons-lang3"
compile "commons-io:commons-io"
compile "javax.transaction:javax.transaction-api"
compile "org.ehcache:ehcache"
compile "org.hibernate:hibernate-entitymanager"
compile "org.hibernate:hibernate-envers"
compile "org.hibernate.validator:hibernate-validator"
compile "org.liquibase:liquibase-core"
compile "com.mattbertolini:liquibase-slf4j"
liquibaseRuntime "org.liquibase:liquibase-core"
liquibaseRuntime "org.liquibase.ext:liquibase-hibernate5:${liquibase_hibernate5_version}"
liquibaseRuntime sourceSets.main.compileClasspath
compile "org.springframework.boot:spring-boot-loader-tools"
compile "org.springframework.boot:spring-boot-starter-mail"
compile "org.springframework.boot:spring-boot-starter-logging"
compile "org.springframework.boot:spring-boot-starter-actuator"
compile "org.springframework.boot:spring-boot-starter-aop"
compile "org.springframework.boot:spring-boot-starter-data-jpa"
compile "org.springframework.boot:spring-boot-starter-security"
compile ("org.springframework.boot:spring-boot-starter-web") {
exclude module: 'spring-boot-starter-tomcat'
}
compile "org.springframework.boot:spring-boot-starter-undertow"
compile "org.springframework.boot:spring-boot-starter-thymeleaf"
compile "org.zalando:problem-spring-web:0.24.0-RC.0"
compile "org.springframework.boot:spring-boot-starter-cloud-connectors"
compile "org.springframework.security:spring-security-config"
compile "org.springframework.security:spring-security-data"
compile "org.springframework.security:spring-security-web"
compile "io.jsonwebtoken:jjwt-api"
runtime "io.jsonwebtoken:jjwt-impl"
runtime "io.jsonwebtoken:jjwt-jackson"
compile ("io.springfox:springfox-swagger2") {
exclude module: 'mapstruct'
}
compile "io.springfox:springfox-bean-validators"
compile "org.postgresql:postgresql"
liquibaseRuntime "org.postgresql:postgresql"
compile "org.mapstruct:mapstruct-jdk8:${mapstruct_version}"
annotationProcessor "org.mapstruct:mapstruct-processor:${mapstruct_version}"
annotationProcessor "org.hibernate:hibernate-jpamodelgen"
annotationProcessor ("org.springframework.boot:spring-boot-configuration-processor") {
exclude group: 'com.vaadin.external.google', module: 'android-json'
}
testCompile "com.jayway.jsonpath:json-path"
testCompile "io.cucumber:cucumber-junit"
testCompile "io.cucumber:cucumber-spring"
testCompile ("org.springframework.boot:spring-boot-starter-test") {
exclude group: 'com.vaadin.external.google', module: 'android-json'
}
testCompile "org.springframework.security:spring-security-test"
testCompile "org.springframework.boot:spring-boot-test"
testCompile "org.assertj:assertj-core"
testCompile "junit:junit"
testCompile "org.mockito:mockito-core"
testCompile "com.mattbertolini:liquibase-slf4j"
testCompile "org.hamcrest:hamcrest-library"
testCompile "com.h2database:h2"
liquibaseRuntime "com.h2database:h2"
//jhipster-needle-gradle-dependency - JHipster will add additional dependencies here
}
task cleanResources(type: Delete) {
delete 'build/resources'
}
wrapper {
gradleVersion = '4.10.2'
}
task stage(dependsOn: 'bootWar') {
}
if (project.hasProperty('nodeInstall')) {
node {
version = "${node_version}"
npmVersion = "${npm_version}"
yarnVersion = "${yarn_version}"
download = false
}
}

View File

@ -1,315 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="13">
<profile kind="CodeFormatterProfile" name="Eclipse Formatter" version="13">
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_for_statment" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_invocation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_switch_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indentation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_enum_constant_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.disabling_tag" value="@formatter:off"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_enum_constants" value="49"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_if_while_statement" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_root_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.enabling_tag" value="@formatter:on"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.count_line_length_from_starting_position" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameterized_type_references" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.problem.enumIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.line_length" value="128"/>
<setting id="org.eclipse.jdt.core.formatter.use_on_off_tags" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_catch_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_lambda_body" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_parameters" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_annotation" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_line_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_module_statements" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_conditional_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode" value="enabled"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_method_declaration" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.join_wrapped_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_conditional_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.align_fields_grouping_blank_lines" value="2147483647"/>
<setting id="org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_resources_in_try" value="82"/>
<setting id="org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_try_clause" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation" value="80"/>
<setting id="org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.jdt.core.compiler.source" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.size" value="4"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_assignment_operator" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.codegen.targetPlatform" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_method_delcaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_type_arguments" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_label" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration" value="48"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.jdt.core.compiler.compliance" value="1.8"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.parentheses_positions_in_lambda_declaration" value="common_lines"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.alignment_for_expressions_in_for_loop_header" value="0"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.join_lines_in_comments" value="false"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.jdt.core.formatter.comment.indent_parameter_description" value="true"/>
<setting id="org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.jdt.core.formatter.lineSplit" value="128"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
</profile>
</profiles>

View File

@ -1,8 +0,0 @@
#Organize Import Order
6=javax
5=java
4=org
3=com
2=
1=org.hostsharing
0=\#

View File

@ -1,267 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<profiles version="11">
<profile kind="CodeFormatterProfile" name="CleanCode JS-Formatter" version="11">
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_binary_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.never_indent_block_comments_on_first_column" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_header" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.compact_else_if" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_synchronized" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.align_type_members_on_columns" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_first_class_body_declaration" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_else_statement_on_same_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_while" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_object_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_comma_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_switch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_increments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.wrap_before_binary_operator" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.put_empty_statement_on_new_line" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_unary_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_enum_constant" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indentation.size" value="2"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_annotation_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_assignment" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_multiple_fields" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_selector_in_method_invocation" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_and_in_type_parameter" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_for_parameter" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_inits" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.compliance" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_braces_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_constructor_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_after_package" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_method" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.problem.assertIdentifier" value="error"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_constructor_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_allocation_expression" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.tabulation.size" value="2"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_annotation" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_at_in_annotation_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_default" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superclass_in_type_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_enum_constant" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_source_code" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_block" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation_type_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_catch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_type_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation" value="2"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_throw" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_case" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_after_imports" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_empty_objlit_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_expressions_in_array_initializer" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_switch" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_then_statement_on_same_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_method_body" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_else_in_if_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_binary_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_between_import_groups" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_parenthesized_expression_in_return" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_field" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_labeled_statement" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.source" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_conditional_expression" value="80"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_binary_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.insert_new_line_before_root_tags" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_block_comments" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_catch_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_html" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_package" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_objlit_initializer" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_enum_constant" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_assignment_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_allocation_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_for_increments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_empty_array_initializer_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_new_chunk" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_finally_in_try_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_method_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_brackets_in_array_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_block" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_paren_in_cast" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_empty_lines" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_while" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_member_type" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_breaks_compare_to_cases" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_before_imports" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_object_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_superinterfaces" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_type_parameters" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_unary_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_if" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.blank_lines_between_type_declarations" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_switchstatements_compare_to_cases" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_synchronized" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_switch" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_semicolon_in_for" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_statements_compare_to_body" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_case" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_while_in_do_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_for_inits" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.clear_blank_lines_in_block_comment" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_constant" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_closing_brace_in_block" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.indent_body_declarations_compare_to_type_header" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_at_end_of_file_if_missing" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_anonymous_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_objlit_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.indent_root_tags" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_assert" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_question_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_block_in_case" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_if" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_switch" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_javadoc_comments" value="true"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_arguments_in_method_invocation" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_assert" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_superinterfaces" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_annotation_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_catch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_objlit_initializer" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_comma_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_colon_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.format_guardian_clause_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.format_line_comments" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_method_invocation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_constant" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.compiler.codegen.targetPlatform" value="1.5"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_bracket_in_array_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_semicolon_in_for" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_array_initializer" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.lineSplit" value="180"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.tabulation.char" value="space"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_at_in_annotation" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_throws_clause_in_method_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_in_empty_enum_declaration" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_postfix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.keep_imple_if_on_one_line" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_method_declaration_throws" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_ellipsis" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.use_tabs_only_for_leading_indentations" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_paren_in_cast" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_type_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_question_in_conditional" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_new_line_after_annotation" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_ellipsis" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_brace_in_array_initializer" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_opening_paren_in_switch" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_colon_in_labeled_statement" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_enum_constants" value="0"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.brace_position_for_method_declaration" value="end_of_line"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_assignment_operator" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_compact_if" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.line_length" value="80"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_parameters_in_method_declaration" value="48"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.continuation_indentation_for_array_initializer" value="2"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.number_of_empty_lines_to_preserve" value="1"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_declarations" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments" value="insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.never_indent_line_comments_on_first_column" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration" value="16"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_before_prefix_operator" value="do not insert"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.comment.indent_parameter_description" value="false"/>
<setting id="org.eclipse.wst.jsdt.core.formatter.insert_space_between_empty_parens_in_enum_constant" value="do not insert"/>
</profile>
</profiles>

View File

@ -1,53 +0,0 @@
rootProject.name=hsadmin-ng
profile=dev
# Build properties
node_version=10.15.3
npm_version=6.4.1
yarn_version=1.13.0
# Dependency versions
jhipster_dependencies_version=2.1.1
# The spring-boot version should match the one managed by
# https://mvnrepository.com/artifact/io.github.jhipster/jhipster-dependencies/${jhipster_dependencies_version}
spring_boot_version=2.0.8.RELEASE
# The hibernate version should match the one managed by
# https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/${spring-boot.version} -->
hibernate_version=5.2.17.Final
mapstruct_version=1.2.0.Final
liquibase_hibernate5_version=3.6
liquibaseTaskPrefix=liquibase
# jhipster-needle-gradle-property - JHipster will add additional properties here
## below are some of the gradle performance improvement settings that can be used as required, these are not enabled by default
## The Gradle daemon aims to improve the startup and execution time of Gradle.
## The daemon is enabled by default in Gradle 3+ setting this to false will disable this.
## TODO: disable daemon on CI, since builds should be clean and reliable on servers
## https://docs.gradle.org/current/userguide/gradle_daemon.html#sec:ways_to_disable_gradle_daemon
## un comment the below line to disable the daemon
#org.gradle.daemon=false
## Specifies the JVM arguments used for the daemon process.
## The setting is particularly useful for tweaking memory settings.
## Default value: -Xmx1024m -XX:MaxPermSize=256m
## un comment the below line to override the daemon defaults
#org.gradle.jvmargs=-Xmx1024m -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
## When configured, Gradle will run in incubating parallel mode.
## This option should only be used with decoupled projects. More details, visit
## http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
## un comment the below line to enable parallel mode
#org.gradle.parallel=true
## Enables new incubating mode that makes Gradle selective when configuring projects.
## Only relevant projects are configured which results in faster builds for large multi-projects.
## http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:configuration_on_demand
## un comment the below line to enable the selective mode
#org.gradle.configureondemand=true

View File

@ -1,35 +0,0 @@
buildscript {
repositories {
gradlePluginPortal()
}
dependencies {
classpath "gradle.plugin.com.google.cloud.tools:jib-gradle-plugin:0.9.11"
}
}
apply plugin: com.google.cloud.tools.jib.gradle.JibPlugin
jib {
from {
image = 'openjdk:8-jre-alpine'
}
to {
image = 'hsadminng:latest'
}
container {
entrypoint = ['sh', '-c', 'chmod +x /entrypoint.sh && sync && /entrypoint.sh']
ports = ['8080']
environment = [
SPRING_OUTPUT_ANSI_ENABLED: 'ALWAYS',
JHIPSTER_SLEEP: '0'
]
useCurrentTimestamp = true
}
}
task copyWwwIntoStatic (type: Copy) {
from 'build/www/'
into 'build/resources/main/static'
}
jibDockerBuild.dependsOn copyWwwIntoStatic

View File

@ -1,72 +0,0 @@
import org.gradle.internal.os.OperatingSystem
apply plugin: 'org.springframework.boot'
apply plugin: 'com.moowork.node'
dependencies {
compile "org.springframework.boot:spring-boot-devtools"
compile "com.h2database:h2"
}
def profiles = "";
if (project.hasProperty('pgsql')) {
profiles += 'pgsql'
} else if (project.hasProperty('h2file')) {
profiles += 'h2file'
} else {
profiles += 'h2mem'
}
if (project.hasProperty('no-liquibase')) {
profiles += ',no-liquibase'
}
if (project.hasProperty('tls')) {
profiles += ',tls'
}
println 'activating profiles: ' + profiles
springBoot {
buildInfo {
properties {
time = null
}
}
}
bootRun {
args = []
}
task webpackBuildDev(type: NpmTask) {
inputs.files(fileTree('src/main/webapp/'))
def webpackDevFiles = fileTree('webpack//')
webpackDevFiles.exclude('webpack.prod.js')
inputs.files(webpackDevFiles)
outputs.files(fileTree("build/www/"))
dependsOn npmInstall
args = ["run", "webpack:build"]
}
task copyIntoStatic (type: Copy) {
from 'build/www/'
into 'build/resources/main/static'
}
processResources {
filesMatching('**/application.yml') {
filter {
it.replace('#project.version#', version)
}
filter {
it.replace('#spring.profiles.active#', profiles)
}
}
}
processResources.dependsOn webpackBuildDev
copyIntoStatic.dependsOn processResources
bootJar.dependsOn copyIntoStatic

View File

@ -1,63 +0,0 @@
apply plugin: 'org.springframework.boot'
apply plugin: 'com.gorylenko.gradle-git-properties'
apply plugin: 'com.moowork.node'
dependencies {
testCompile "com.h2database:h2"
}
def profiles = 'prod'
if (project.hasProperty('no-liquibase')) {
profiles += ',no-liquibase'
}
if (project.hasProperty('swagger')) {
profiles += ',swagger'
}
springBoot {
buildInfo()
}
bootRun {
args = []
}
task webpack_test(type: NpmTask, dependsOn: 'npm_install') {
args = ["run", "webpack:test"]
}
task webpack(type: NpmTask, dependsOn: 'npm_install') {
args = ["run", "webpack:prod"]
}
task copyIntoStatic (type: Copy) {
from 'build/www/'
into 'build/resources/main/static'
}
processResources {
filesMatching('**/application.yml') {
filter {
it.replace('#project.version#', version)
}
filter {
it.replace('#spring.profiles.active#', profiles)
}
}
}
generateGitProperties {
onlyIf {
!source.isEmpty()
}
}
gitProperties {
keys = ['git.branch', 'git.commit.id.abbrev', 'git.commit.id.describe']
}
test.dependsOn webpack_test
processResources.dependsOn webpack
copyIntoStatic.dependsOn processResources
bootJar.dependsOn copyIntoStatic

View File

@ -1,47 +0,0 @@
apply plugin: "org.sonarqube"
apply plugin: 'jacoco'
jacoco {
toolVersion = '0.8.2'
}
jacocoTestReport {
reports {
xml.enabled true
}
}
sonarqube {
properties {
property "sonar.host.url", "http://localhost:9001"
property "sonar.exclusions", "src/main/webapp/content/**/*.*,src/main/webapp/i18n/*.js, build/www/**/*.*"
property "sonar.issue.ignore.multicriteria", "S3437,S4502,S4684,UndocumentedApi,BoldAndItalicTagsCheck"
// Rule https://sonarcloud.io/coding_rules?open=Web%3ABoldAndItalicTagsCheck&rule_key=Web%3ABoldAndItalicTagsCheck is ignored. Even if we agree that using the "i" tag is an awful practice, this is what is recommended by http://fontawesome.io/examples/
property "sonar.issue.ignore.multicriteria.BoldAndItalicTagsCheck.resourceKey", ">src/main/webapp/app/**/*.*"
property "sonar.issue.ignore.multicriteria.BoldAndItalicTagsCheck.ruleKey", "Web:BoldAndItalicTagsCheck"
// Rule https://sonarcloud.io/coding_rules?open=squid%3AS3437&rule_key=squid%3AS3437 is ignored, as a JPA-managed field cannot be transient
property "sonar.issue.ignore.multicriteria.S3437.resourceKey", "src/main/java/**/*"
property "sonar.issue.ignore.multicriteria.S3437.ruleKey", "squid:S3437"
// Rule https://sonarcloud.io/coding_rules?open=squid%3AUndocumentedApi&rule_key=squid%3AUndocumentedApi is ignored, as we want to follow "clean code" guidelines and classes, methods and arguments names should be self-explanatory
property "sonar.issue.ignore.multicriteria.UndocumentedApi.resourceKey", "src/main/java/**/*"
property "sonar.issue.ignore.multicriteria.UndocumentedApi.ruleKey", "squid:UndocumentedApi"
// Rule https://sonarcloud.io/coding_rules?open=squid%3AS4502&rule_key=squid%3AS4502 is ignored, as for JWT tokens we are not subject to CSRF attack
property "sonar.issue.ignore.multicriteria.S4502.resourceKey", "src/main/java/**/*"
property "sonar.issue.ignore.multicriteria.S4502.ruleKey", "squid:S4502"
// Rule https://sonarcloud.io/coding_rules?open=squid%3AS4684&rule_key=squid%3AS4684
property "sonar.issue.ignore.multicriteria.S4684.resourceKey", "src/main/java/**/*"
property "sonar.issue.ignore.multicriteria.S4684.ruleKey", "squid:S4684"
property "sonar.jacoco.reportPaths", "${project.buildDir}/jacoco/test.exec"
property "sonar.java.codeCoveragePlugin", "jacoco"
property "sonar.typescript.lcov.reportPaths", "${project.buildDir}/test-results/lcov.info"
property "sonar.junit.reportPaths", "${project.buildDir}/test-results"
property "sonar.sources", "${project.projectDir}/src/main/"
property "sonar.tests", "${project.projectDir}/src/test/"
}
}

View File

@ -1,28 +0,0 @@
/*
* Plugin that provides API-first development using OpenAPI-generator to
* generate Spring-MVC endpoint stubs at compile time from an OpenAPI definition file
*/
apply plugin: 'org.openapi.generator'
openApiGenerate {
generatorName = "spring"
inputSpec = "$rootDir/src/main/resources/swagger/api.yml".toString()
outputDir = "$buildDir/openapi".toString()
apiPackage = "org.hostsharing.hsadminng.web.api"
modelPackage = "org.hostsharing.hsadminng.web.api.model"
apiFilesConstrainedTo = [""]
modelFilesConstrainedTo = [""]
supportingFilesConstrainedTo = ["ApiUtil.java"]
configOptions = [delegatePattern: "true"]
validateSpec = true
}
sourceSets {
main {
java {
srcDir file("${project.buildDir.path}/openapi/src/main/java")
}
}
}
compileJava.dependsOn("openApiGenerate")

Binary file not shown.

View File

@ -1,6 +0,0 @@
#Sun Apr 28 06:46:48 CEST 2019
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.2-all.zip

View File

@ -1,3 +0,0 @@
dependencies {
compile "org.springframework.cloud:spring-cloud-starter-zipkin"
}

172
gradlew vendored
View File

@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
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
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

84
gradlew.bat vendored
View File

@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

18180
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,126 +0,0 @@
{
"name": "hsadmin-ng",
"version": "0.0.0",
"description": "Description for hsadminNg",
"private": true,
"license": "UNLICENSED",
"cacheDirectories": [
"node_modules"
],
"dependencies": {
"@angular/common": "7.2.4",
"@angular/compiler": "7.2.4",
"@angular/core": "7.2.4",
"@angular/forms": "7.2.4",
"@angular/platform-browser": "7.2.4",
"@angular/platform-browser-dynamic": "7.2.4",
"@angular/router": "7.2.4",
"@fortawesome/angular-fontawesome": "0.3.0",
"@fortawesome/fontawesome-svg-core": "1.2.14",
"@fortawesome/free-solid-svg-icons": "5.7.1",
"@ng-bootstrap/ng-bootstrap": "4.0.2",
"@ngx-translate/core": "11.0.1",
"@ngx-translate/http-loader": "4.0.0",
"bootstrap": "4.2.1",
"core-js": "2.6.4",
"moment": "2.24.0",
"ng-jhipster": "0.9.1",
"ngx-cookie": "2.0.1",
"ngx-infinite-scroll": "7.0.1",
"ngx-webstorage": "2.0.1",
"rxjs": "6.4.0",
"swagger-ui": "2.2.10",
"tslib": "1.9.3",
"zone.js": "0.8.29"
},
"devDependencies": {
"@angular/cli": "7.3.1",
"@angular/compiler-cli": "7.2.4",
"@ngtools/webpack": "7.3.1",
"@types/jest": "24.0.0",
"@types/node": "10.12.24",
"angular-router-loader": "0.8.5",
"angular2-template-loader": "0.6.2",
"autoprefixer": "9.4.7",
"browser-sync": "2.26.3",
"browser-sync-webpack-plugin": "2.2.2",
"cache-loader": "2.0.1",
"codelyzer": "4.5.0",
"copy-webpack-plugin": "4.6.0",
"css-loader": "2.1.0",
"file-loader": "3.0.1",
"fork-ts-checker-webpack-plugin": "0.5.2",
"friendly-errors-webpack-plugin": "1.7.0",
"generator-jhipster": "5.8.2",
"html-loader": "0.5.5",
"html-webpack-plugin": "3.2.0",
"husky": "1.3.1",
"jest": "24.1.0",
"jest-junit": "6.2.1",
"jest-preset-angular": "6.0.2",
"jest-sonar-reporter": "2.0.0",
"lint-staged": "8.1.3",
"merge-jsons-webpack-plugin": "1.0.18",
"mini-css-extract-plugin": "0.5.0",
"moment-locales-webpack-plugin": "1.0.7",
"optimize-css-assets-webpack-plugin": "5.0.1",
"prettier": "1.16.4",
"reflect-metadata": "0.1.13",
"rimraf": "2.6.3",
"simple-progress-webpack-plugin": "1.1.2",
"style-loader": "0.23.1",
"terser-webpack-plugin": "1.2.2",
"thread-loader": "2.1.2",
"to-string-loader": "1.1.5",
"ts-loader": "5.3.3",
"tslint": "5.12.1",
"tslint-config-prettier": "1.18.0",
"tslint-loader": "3.6.0",
"typescript": "3.2.4",
"postcss-loader": "3.0.0",
"webpack": "4.29.3",
"webpack-cli": "3.2.3",
"webpack-dev-server": "3.1.14",
"webpack-merge": "4.2.1",
"webpack-notifier": "1.7.0",
"webpack-visualizer-plugin": "0.1.11",
"workbox-webpack-plugin": "3.6.3",
"write-file-webpack-plugin": "4.5.0"
},
"engines": {
"node": ">=8.9.0"
},
"lint-staged": {
"{,src/**/}*.{md,json,ts,css,scss}": [
"prettier --write",
"git add"
]
},
"scripts": {
"prettier:format": "prettier --write \"{,src/**/}*.{md,json,ts,css,scss}\"",
"lint": "tslint --project tsconfig.json -e 'node_modules/**'",
"lint:fix": "npm run lint -- --fix",
"ngc": "ngc -p tsconfig-aot.json",
"cleanup": "rimraf build/{aot,www}",
"clean-www": "rimraf build//www/app/{src,build/}",
"start": "npm run webpack:dev",
"start-tls": "npm run webpack:dev -- --env.tls",
"serve": "npm run start",
"build": "npm run webpack:prod",
"test": "npm run lint && jest --coverage --logHeapUsage -w=2 --config src/test/javascript/jest.conf.js",
"test:watch": "npm run test -- --watch",
"webpack:dev": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --env.stats=minimal",
"webpack:dev-verbose": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --profile --progress --env.stats=normal",
"webpack:build:main": "npm run webpack -- --config webpack/webpack.dev.js --env.stats=minimal",
"webpack:build": "npm run cleanup && npm run webpack:build:main",
"webpack:prod:main": "npm run webpack -- --config webpack/webpack.prod.js --profile",
"webpack:prod": "npm run cleanup && npm run webpack:prod:main && npm run clean-www",
"webpack:test": "npm run test",
"webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
"webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js"
},
"jestSonar": {
"reportPath": "build/test-results/jest",
"reportFile": "TESTS-results-sonar.xml"
}
}

View File

@ -1,5 +0,0 @@
module.exports = {
plugins: [
require('autoprefixer')
]
}

View File

@ -1,7 +0,0 @@
{
"*": {
"target": "http://localhost:8080",
"secure": false,
"loglevel": "debug"
}
}

View File

@ -1 +0,0 @@
rootProject.name = 'hsadmin-ng'

38
sql/00-util.sql Normal file
View File

@ -0,0 +1,38 @@
abort;
set local session authorization default;
CREATE OR REPLACE FUNCTION array_distinct(anyarray) RETURNS anyarray AS $f$
SELECT array_agg(DISTINCT x) FROM unnest($1) t(x);
$f$ LANGUAGE SQL IMMUTABLE;
CREATE OR REPLACE FUNCTION lastRowCount()
RETURNS bigint
LANGUAGE plpgsql AS $$
DECLARE
lastRowCount bigint;
BEGIN
GET DIAGNOSTICS lastRowCount = ROW_COUNT;
RETURN lastRowCount;
END;
$$;
-- ========================================================
-- Test Data helpers
-- --------------------------------------------------------
CREATE OR REPLACE FUNCTION intToVarChar(i integer, len integer)
RETURNS varchar
LANGUAGE plpgsql AS $$
DECLARE
partial varchar;
BEGIN
SELECT chr(ascii('a') + i%26) INTO partial;
IF len > 1 THEN
RETURN intToVarChar(i/26, len-1) || partial;
ELSE
RETURN partial;
END IF;
END; $$;
SELECT * FROM intToVarChar(211, 4);

657
sql/10-rbac-base.sql Normal file
View File

@ -0,0 +1,657 @@
-- ========================================================
-- RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT;
-- https://arctype.com/blog/postgres-uuid/#creating-a-uuid-primary-key-using-uuid-osp-postgresql-example
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
DROP TABLE IF EXISTS "RbacPermission";
DROP TABLE IF EXISTS "RbacGrants";
DROP TABLE IF EXISTS "RbacUser";
DROP TABLE IF EXISTS RbacReference CASCADE;
DROP TYPE IF EXISTS RbacOp CASCADE;
DROP TYPE IF EXISTS ReferenceType CASCADE;
CREATE TYPE ReferenceType AS ENUM ('RbacUser', 'RbacRole', 'RbacPermission');
CREATE TABLE RbacReference
(
uuid uuid UNIQUE DEFAULT uuid_generate_v4(),
type ReferenceType not null
);
CREATE TABLE RbacUser
(
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
name varchar(63) not null unique
);
CREATE TABLE RbacRole
(
uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
name varchar(63) not null unique
);
CREATE TABLE RbacGrants
(
ascendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
descendantUuid uuid references RbacReference (uuid) ON DELETE CASCADE,
-- apply bool not null, -- alternative 1 to implement assumable roles
primary key (ascendantUuid, descendantUuid)
);
CREATE INDEX ON RbacGrants (ascendantUuid);
CREATE INDEX ON RbacGrants (descendantUuid);
DROP DOMAIN IF EXISTS RbacOp CASCADE;
CREATE DOMAIN RbacOp AS VARCHAR(67)
CHECK(
VALUE = '*'
OR VALUE = 'delete'
OR VALUE = 'edit'
OR VALUE = 'view'
OR VALUE = 'assume'
OR VALUE ~ '^add-[a-z]+$'
);
DROP TABLE IF EXISTS RbacObject;
CREATE TABLE RbacObject
(
uuid uuid UNIQUE DEFAULT uuid_generate_v4(),
objectTable varchar(64) not null,
unique (objectTable, uuid)
);
CREATE OR REPLACE FUNCTION createRbacObject()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
objectUuid uuid;
BEGIN
IF TG_OP = 'INSERT' THEN
INSERT INTO RbacObject (objectTable) VALUES (TG_TABLE_NAME) RETURNING uuid INTO objectUuid;
NEW.uuid = objectUuid;
RETURN NEW;
ELSE
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
END; $$;
DROP TABLE IF EXISTS RbacPermission;
CREATE TABLE RbacPermission
( uuid uuid primary key references RbacReference (uuid) ON DELETE CASCADE,
objectUuid uuid not null,
op RbacOp not null,
unique (objectUuid, op)
);
CREATE OR REPLACE FUNCTION hasPermission(forObjectUuid uuid, forOp RbacOp)
RETURNS bool
LANGUAGE sql AS $$
SELECT EXISTS (
SELECT op
FROM RbacPermission p
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
);
$$;
CREATE OR REPLACE FUNCTION createRbacUser(userName varchar)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
declare
objectId uuid;
BEGIN
INSERT INTO RbacReference (type) VALUES ('RbacUser') RETURNING uuid INTO objectId;
INSERT INTO RbacUser (uuid, name) VALUES (objectid, userName);
return objectId;
END;
$$;
CREATE OR REPLACE FUNCTION findRbacUser(userName varchar) -- TODO: rename to ...Id
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT uuid FROM RbacUser WHERE name = userName
$$;
CREATE OR REPLACE FUNCTION getRbacUserId(userName varchar, whenNotExists RbacWhenNotExists)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
DECLARE
userUuid uuid;
BEGIN
userUuid = findRbacUser(userName);
IF ( userUuid IS NULL ) THEN
IF ( whenNotExists = 'fail') THEN
RAISE EXCEPTION 'RbacUser with name="%" not found', userName;
END IF;
IF ( whenNotExists = 'create') THEN
userUuid = createRbacUser(userName);
END IF;
END IF;
return userUuid;
END;
$$;
CREATE OR REPLACE FUNCTION createRole(roleName varchar)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
declare
referenceId uuid;
BEGIN
INSERT INTO RbacReference (type) VALUES ('RbacRole') RETURNING uuid INTO referenceId;
INSERT INTO RbacRole (uuid, name) VALUES (referenceId, roleName);
IF (referenceId IS NULL) THEN
RAISE EXCEPTION 'referenceId for roleName "%" is unexpectedly null', roleName;
end if;
return referenceId;
END;
$$;
CREATE OR REPLACE PROCEDURE deleteRole(roleUUid uuid)
LANGUAGE plpgsql AS $$
BEGIN
DELETE FROM RbacRole WHERE uuid=roleUUid;
END;
$$;
CREATE OR REPLACE FUNCTION findRoleId(roleName varchar)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT uuid FROM RbacRole WHERE name = roleName
$$;
CREATE TYPE RbacWhenNotExists AS ENUM ('fail', 'create');
CREATE OR REPLACE FUNCTION getRoleId(roleName varchar, whenNotExists RbacWhenNotExists)
RETURNS uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
DECLARE
roleUuid uuid;
BEGIN
roleUuid = findRoleId(roleName);
IF ( roleUuid IS NULL ) THEN
IF ( whenNotExists = 'fail') THEN
RAISE EXCEPTION 'RbacRole with name="%" not found', roleName;
END IF;
IF ( whenNotExists = 'create') THEN
roleUuid = createRole(roleName);
END IF;
END IF;
return roleUuid;
END;
$$;
-- select getRoleId('hostmaster', 'create');
CREATE OR REPLACE FUNCTION createPermissions(forObjectUuid uuid, permitOps RbacOp[])
RETURNS uuid[]
LANGUAGE plpgsql AS $$
DECLARE
refId uuid;
permissionIds uuid[] = ARRAY[]::uuid[];
BEGIN
IF ( forObjectUuid IS NULL ) THEN
RAISE EXCEPTION 'forObjectUuid must not be null';
END IF;
IF ( array_length(permitOps, 1) > 1 AND '*' = any(permitOps) ) THEN
RAISE EXCEPTION '"*" operation must not be assigned along with other operations: %', permitOps;
END IF;
FOR i IN array_lower(permitOps, 1)..array_upper(permitOps, 1) LOOP
refId = (SELECT uuid FROM RbacPermission WHERE objectUuid=forObjectUuid AND op=permitOps[i]);
IF (refId IS NULL) THEN
INSERT INTO RbacReference ("type") VALUES ('RbacPermission') RETURNING uuid INTO refId;
INSERT INTO RbacPermission (uuid, objectUuid, op) VALUES (refId, forObjectUuid, permitOps[i]);
END IF;
permissionIds = permissionIds || refId;
END LOOP;
return permissionIds;
END;
$$;
CREATE OR REPLACE FUNCTION findPermissionId(forObjectTable varchar, forObjectUuid uuid, forOp RbacOp)
RETURNS uuid
RETURNS NULL ON NULL INPUT
STABLE LEAKPROOF
LANGUAGE sql AS $$
SELECT uuid FROM RbacPermission p
WHERE p.objectUuid=forObjectUuid AND p.op in ('*', forOp)
$$;
CREATE OR REPLACE FUNCTION assertReferenceType(argument varchar, referenceId uuid, expectedType ReferenceType)
RETURNS ReferenceType
LANGUAGE plpgsql AS $$
DECLARE
actualType ReferenceType;
BEGIN
actualType = (SELECT type FROM RbacReference WHERE uuid=referenceId);
IF ( actualType <> expectedType ) THEN
RAISE EXCEPTION '% must reference a %, but got a %', argument, expectedType, actualType;
end if;
RETURN expectedType;
END; $$;
CREATE OR REPLACE PROCEDURE grantPermissionsToRole(roleUuid uuid, permissionIds uuid[])
LANGUAGE plpgsql AS $$
BEGIN
FOR i IN array_lower(permissionIds, 1)..array_upper(permissionIds, 1) LOOP
perform assertReferenceType('roleId (ascendant)', roleUuid, 'RbacRole');
perform assertReferenceType('permissionId (descendant)', permissionIds[i], 'RbacPermission');
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (roleId, permissionIds[i], true); -- assumeV1
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (roleUuid, permissionIds[i]);
END LOOP;
END;
$$;
CREATE OR REPLACE PROCEDURE grantRoleToRole(subRoleId uuid, superRoleId uuid
-- , doapply bool = true -- assumeV1
)
LANGUAGE plpgsql AS $$
BEGIN
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
RAISE NOTICE 'granting subRole % to superRole %', subRoleId, superRoleId; -- TODO: remove
IF ( isGranted(subRoleId, superRoleId) ) THEN
RAISE EXCEPTION 'Cyclic role grant detected between % and %', subRoleId, superRoleId;
END IF;
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (superRoleId, subRoleId, doapply); -- assumeV1
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (superRoleId, subRoleId)
ON CONFLICT DO NOTHING ; -- TODO: remove
END; $$;
CREATE OR REPLACE PROCEDURE revokeRoleFromRole(subRoleId uuid, superRoleId uuid)
LANGUAGE plpgsql AS $$
BEGIN
perform assertReferenceType('superRoleId (ascendant)', superRoleId, 'RbacRole');
perform assertReferenceType('subRoleId (descendant)', subRoleId, 'RbacRole');
IF ( isGranted(subRoleId, superRoleId) ) THEN
DELETE FROM RbacGrants WHERE ascendantUuid=superRoleId AND descendantUuid=subRoleId;
END IF;
END; $$;
CREATE OR REPLACE PROCEDURE grantRoleToUser(roleId uuid, userId uuid)
LANGUAGE plpgsql AS $$
BEGIN
perform assertReferenceType('roleId (ascendant)', roleId, 'RbacRole');
perform assertReferenceType('userId (descendant)', userId, 'RbacUser');
-- INSERT INTO RbacGrants (ascendantUuid, descendantUuid, apply) VALUES (userId, roleId, true); -- assumeV1
INSERT INTO RbacGrants (ascendantUuid, descendantUuid) VALUES (userId, roleId)
ON CONFLICT DO NOTHING ; -- TODO: remove
END; $$;
abort;
set local session authorization default;
CREATE OR REPLACE FUNCTION queryAccessibleObjectUuidsOfSubjectIds(
requiredOp RbacOp,
-- objectTable varchar, -- TODO: maybe another optimization? but test perforamance for joins!
subjectIds uuid[],
maxDepth integer = 8,
maxObjects integer = 16000)
RETURNS SETOF uuid
RETURNS NULL ON NULL INPUT
LANGUAGE plpgsql AS $$
DECLARE
foundRows bigint;
BEGIN
RETURN QUERY SELECT DISTINCT perm.objectUuid
FROM (
WITH RECURSIVE grants AS (
SELECT descendantUuid, ascendantUuid, 1 AS level
FROM RbacGrants
WHERE ascendantUuid = ANY(subjectIds)
UNION ALL
SELECT "grant".descendantUuid, "grant".ascendantUuid, level + 1 AS level
FROM RbacGrants "grant"
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
WHERE level <= maxDepth
) SELECT descendantUuid
FROM grants
-- LIMIT maxObjects+1
) as granted
JOIN RbacPermission perm ON granted.descendantUuid=perm.uuid AND perm.op IN ('*', requiredOp);
foundRows = lastRowCount();
IF foundRows > maxObjects THEN
RAISE EXCEPTION 'Too many accessible objects, limit is %, found %.', maxObjects, foundRows
USING
ERRCODE = 'P0003', -- 'HS-ADMIN-NG:ACC-OBJ-EXC',
HINT = 'Please assume a sub-role and try again.';
END IF;
END;
$$;
abort;
set local session authorization restricted;
begin transaction;
set local statement_timeout TO '60s';
select count(*)
from queryAccessibleObjectUuidsOfSubjectIds('view', ARRAY[findRbacUser('mike@hostsharing.net')], 4, 10000);
end transaction;
---
abort;
set local session authorization default;
CREATE OR REPLACE FUNCTION queryRequiredPermissionsOfSubjectIds(requiredOp RbacOp, subjectIds uuid[])
RETURNS SETOF RbacPermission
STRICT
LANGUAGE sql AS $$
SELECT DISTINCT *
FROM RbacPermission
WHERE op = '*' OR op = requiredOp
AND uuid IN (
WITH RECURSIVE grants AS (
SELECT DISTINCT
descendantUuid,
ascendantUuid
FROM RbacGrants
WHERE
ascendantUuid = ANY(subjectIds)
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM RbacGrants "grant"
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
) SELECT
descendantUuid
FROM grants
);
$$;
abort;
set local session authorization restricted;
begin transaction;
-- set local statement_timeout TO '5s';
set local statement_timeout TO '5min';
select count(*) from queryRequiredPermissionsOfSubjectIds('view', ARRAY[findRbacUser('mike@hostsharing.net')]);
end transaction;
---
abort;
set local session authorization default;
CREATE OR REPLACE FUNCTION queryAllPermissionsOfSubjectIds(subjectIds uuid[])
RETURNS SETOF RbacPermission
STRICT
LANGUAGE sql AS $$
SELECT DISTINCT * FROM RbacPermission WHERE uuid IN (
WITH RECURSIVE grants AS (
SELECT DISTINCT
descendantUuid,
ascendantUuid
FROM RbacGrants
WHERE
ascendantUuid = ANY(subjectIds)
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM RbacGrants "grant"
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
) SELECT
descendantUuid
FROM grants
);
$$;
abort;
set local session authorization restricted;
begin transaction;
set local statement_timeout TO '5s';
select count(*) from queryAllPermissionsOfSubjectIds(ARRAY[findRbacUser('mike@hostsharing.net')]);
end transaction;
---
CREATE OR REPLACE FUNCTION queryAllPermissionsOfSubjectId(subjectId uuid) -- TODO: remove?
RETURNS SETOF RbacPermission
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT * FROM RbacPermission WHERE uuid IN (
WITH RECURSIVE grants AS (
SELECT
descendantUuid,
ascendantUuid
FROM
RbacGrants
WHERE
ascendantUuid = subjectId
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM RbacGrants "grant"
INNER JOIN grants recur ON recur.descendantUuid = "grant".ascendantUuid
) SELECT
descendantUuid
FROM
grants
);
$$;
---
CREATE OR REPLACE FUNCTION queryAllRbacUsersWithPermissionsFor(objectId uuid)
RETURNS SETOF RbacUser
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT * FROM RbacUser WHERE uuid IN (
WITH RECURSIVE grants AS (
SELECT
descendantUuid,
ascendantUuid
FROM
RbacGrants
WHERE
descendantUuid = objectId
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM
RbacGrants "grant"
INNER JOIN grants recur ON recur.ascendantUuid = "grant".descendantUuid
) SELECT
ascendantUuid
FROM
grants
);
$$;
CREATE OR REPLACE FUNCTION findGrantees(grantedId uuid)
RETURNS SETOF RbacReference
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT reference.*
FROM (
WITH RECURSIVE grants AS (
SELECT
descendantUuid,
ascendantUuid
FROM
RbacGrants
WHERE
descendantUuid = grantedId
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM
RbacGrants "grant"
INNER JOIN grants recur ON recur.ascendantUuid = "grant".descendantUuid
) SELECT
ascendantUuid
FROM
grants
) as grantee
JOIN RbacReference reference ON reference.uuid=grantee.ascendantUuid;
$$;
CREATE OR REPLACE FUNCTION isGranted(granteeId uuid, grantedId uuid)
RETURNS bool
RETURNS NULL ON NULL INPUT
LANGUAGE sql AS $$
SELECT granteeId=grantedId OR granteeId IN (
WITH RECURSIVE grants AS (
SELECT
descendantUuid,
ascendantUuid
FROM
RbacGrants
WHERE
descendantUuid = grantedId
UNION ALL
SELECT
"grant".descendantUuid,
"grant".ascendantUuid
FROM
RbacGrants "grant"
INNER JOIN grants recur ON recur.ascendantUuid = "grant".descendantUuid
) SELECT
ascendantUuid
FROM
grants
);
$$;
CREATE OR REPLACE FUNCTION isPermissionGrantedToSubject(permissionId uuid, subjectId uuid)
RETURNS BOOL
STABLE LEAKPROOF
LANGUAGE sql AS $$
SELECT EXISTS (
SELECT * FROM RbacUser WHERE uuid IN (
WITH RECURSIVE grants AS (
SELECT
descendantUuid,
ascendantUuid
FROM
RbacGrants g
WHERE
g.descendantUuid = permissionId
UNION ALL
SELECT
g.descendantUuid,
g.ascendantUuid
FROM
RbacGrants g
INNER JOIN grants recur ON recur.ascendantUuid = g.descendantUuid
) SELECT
ascendantUuid
FROM
grants
WHERE ascendantUuid=subjectId
)
);
$$;
SET SESSION AUTHORIZATION DEFAULT;
CREATE ROLE admin;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
CREATE ROLE restricted;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
-- ========================================================
-- Current User
-- --------------------------------------------------------
CREATE OR REPLACE FUNCTION currentUser()
RETURNS varchar(63)
STABLE LEAKPROOF
LANGUAGE plpgsql AS $$
DECLARE
currentUser VARCHAR(63);
BEGIN
BEGIN
currentUser := current_setting('hsadminng.currentUser');
EXCEPTION WHEN OTHERS THEN
currentUser := NULL;
END;
IF (currentUser IS NULL OR currentUser = '') THEN
RAISE EXCEPTION 'hsadminng.currentUser must be defined, please use "SET LOCAL ...;"';
END IF;
RETURN currentUser;
END; $$;
SET SESSION AUTHORIZATION DEFAULT;
CREATE OR REPLACE FUNCTION currentUserId()
RETURNS uuid
STABLE LEAKPROOF
LANGUAGE plpgsql AS $$
DECLARE
currentUser VARCHAR(63);
currentUserId uuid;
BEGIN
currentUser := currentUser();
currentUserId = (SELECT uuid FROM RbacUser WHERE name = currentUser);
RETURN currentUserId;
END; $$;
CREATE OR REPLACE FUNCTION assumedRoles()
RETURNS varchar(63)[]
STABLE LEAKPROOF
LANGUAGE plpgsql AS $$
DECLARE
currentSubject VARCHAR(63);
BEGIN
BEGIN
currentSubject := current_setting('hsadminng.assumedRoles');
EXCEPTION WHEN OTHERS THEN
RETURN NULL;
END;
IF (currentSubject = '') THEN
RETURN NULL;
END IF;
RETURN string_to_array(currentSubject, ';');
END; $$;
-- ROLLBACK;
SET SESSION AUTHORIZATION DEFAULT;
CREATE OR REPLACE FUNCTION currentSubjectIds()
RETURNS uuid[]
STABLE LEAKPROOF
LANGUAGE plpgsql AS $$
DECLARE
assumedRoles VARCHAR(63)[];
currentUserId uuid;
assumedRoleIds uuid[];
assumedRoleId uuid;
BEGIN
currentUserId := currentUserId();
assumedRoles := assumedRoles();
IF ( assumedRoles IS NULL ) THEN
RETURN currentUserId;
END IF;
RAISE NOTICE 'assuming roles: %', assumedRoles;
SELECT ARRAY_AGG(uuid) FROM RbacRole WHERE name = ANY(assumedRoles) INTO assumedRoleIds;
FOREACH assumedRoleId IN ARRAY assumedRoleIds LOOP
IF ( NOT isGranted(currentUserId, assumedRoleId) ) THEN
RAISE EXCEPTION 'user % has no permission to assume role %', currentUser(), assumedRoleId;
END IF;
END LOOP;
RETURN assumedRoleIds;
END; $$;

89
sql/11-rbac-view.sql Normal file
View File

@ -0,0 +1,89 @@
-- ========================================================
-- Options for SELECT under RBAC rules
-- --------------------------------------------------------
-- access control via view policy and isPermissionGrantedToSubject - way too slow (33 s 617ms for 1 million rows)
SET SESSION AUTHORIZATION DEFAULT;
CREATE ROLE admin;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO admin;
CREATE ROLE restricted;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO restricted;
SET SESSION AUTHORIZATION DEFAULT;
ALTER TABLE customer DISABLE ROW LEVEL SECURITY;
ALTER TABLE customer ENABLE ROW LEVEL SECURITY;
ALTER TABLE customer FORCE ROW LEVEL SECURITY;
DROP POLICY IF EXISTS customer_policy ON customer;
CREATE POLICY customer_policy ON customer
FOR SELECT
TO restricted
USING (
-- id=1000
isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId())
);
SET SESSION AUTHORIZATION restricted;
SET hsadminng.currentUser TO 'alex@example.com';
SELECT * from customer;
-- access control via view-rule and isPermissionGrantedToSubject - way too slow (35 s 580 ms for 1 million rows)
SET SESSION SESSION AUTHORIZATION DEFAULT;
DROP VIEW cust_view;
CREATE VIEW cust_view AS
SELECT * FROM customer;
CREATE OR REPLACE RULE "_RETURN" AS
ON SELECT TO cust_view
DO INSTEAD
SELECT * FROM customer WHERE isPermissionGrantedToSubject(findPermissionId('customer', id, 'view'), currentUserId());
SELECT * from cust_view LIMIT 10;
select queryAllPermissionsOfSubjectId(findRbacUser('mike@hostsharing.net'));
-- access control via view-rule with join to recursive permissions - really fast (38ms for 1 million rows)
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE customer ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS cust_view;
CREATE OR REPLACE VIEW cust_view AS
SELECT *
FROM customer;
CREATE OR REPLACE RULE "_RETURN" AS
ON SELECT TO cust_view
DO INSTEAD
SELECT c.uuid, c.reference, c.prefix FROM customer AS c
JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
ON p.objectTable='customer' AND p.objectUuid=c.uuid AND p.op in ('*', 'view');
GRANT ALL PRIVILEGES ON cust_view TO restricted;
SET SESSION SESSION AUTHORIZATION restricted;
SET hsadminng.currentUser TO 'alex@example.com';
SELECT * from cust_view;
-- access control via view with join to recursive permissions - really fast (38ms for 1 million rows)
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE customer ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS cust_view;
CREATE OR REPLACE VIEW cust_view AS
SELECT c.uuid, c.reference, c.prefix
FROM customer AS c
JOIN queryAllPermissionsOfSubjectId(currentUserId()) AS p
ON p.objectUuid=c.uuid AND p.op in ('*', 'view');
GRANT ALL PRIVILEGES ON cust_view TO restricted;
SET SESSION SESSION AUTHORIZATION restricted;
-- SET hsadminng.currentUser TO 'alex@example.com';
SET hsadminng.currentUser TO 'mike@hostsharing.net';
-- SET hsadminng.currentUser TO 'aaaaouq@example.com';
SELECT * from cust_view where reference=1144150;
select rr.uuid, rr.type from RbacGrants g
join RbacReference RR on g.ascendantUuid = RR.uuid
where g.descendantUuid in (
select uuid from queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com'))
where objectTable='customer' and op in ('*', 'view'));
call grantRoleToUser(findRoleId('customer#aaa.admin'), findRbacUser('aaaaouq@example.com'));
select queryAllPermissionsOfSubjectId(findRbacUser('aaaaouq@example.com'));

50
sql/19-rbac-tests.sql Normal file
View File

@ -0,0 +1,50 @@
-- ========================================================
-- Some Tests
-- --------------------------------------------------------
select isGranted(findRoleId('administrators'), findRoleId('package#aaa00.owner'));
select isGranted(findRoleId('package#aaa00.owner'), findRoleId('administrators'));
-- call grantRoleToRole(findRoleId('package#aaa00.owner'), findRoleId('administrators'));
-- call grantRoleToRole(findRoleId('administrators'), findRoleId('package#aaa00.owner'));
select count(*)
FROM queryAllPermissionsOfSubjectIdForObjectUuids(findRbacUser('sven@hostsharing.net'),
ARRAY(select uuid from customer where reference < 1100000));
select count(*)
FROM queryAllPermissionsOfSubjectId(findRbacUser('sven@hostsharing.net'));
select *
FROM queryAllPermissionsOfSubjectId(findRbacUser('alex@example.com'));
select *
FROM queryAllPermissionsOfSubjectId(findRbacUser('rosa@example.com'));
select *
FROM queryAllRbacUsersWithPermissionsFor(findPermissionId('customer',
(SELECT uuid FROM RbacObject WHERE objectTable = 'customer' LIMIT 1),
'add-package'));
select *
FROM queryAllRbacUsersWithPermissionsFor(findPermissionId('package',
(SELECT uuid FROM RbacObject WHERE objectTable = 'package' LIMIT 1),
'delete'));
DO LANGUAGE plpgsql
$$
DECLARE
userId uuid;
result bool;
BEGIN
userId = findRbacUser('mike@hostsharing.net');
result = (SELECT * FROM isPermissionGrantedToSubject(findPermissionId('package', 94928, 'add-package'), userId));
IF (result) THEN
RAISE EXCEPTION 'expected permission NOT to be granted, but it is';
end if;
result = (SELECT * FROM isPermissionGrantedToSubject(findPermissionId('package', 94928, 'view'), userId));
IF (NOT result) THEN
RAISE EXCEPTION 'expected permission to be granted, but it is NOT';
end if;
RAISE LOG 'isPermissionGrantedToSubjectId test passed';
END;
$$;

18
sql/20-hs-base.sql Normal file
View File

@ -0,0 +1,18 @@
-- create administrators role with two assigned users
do language plpgsql $$
declare
admins uuid ;
begin
admins = createRole('administrators');
call grantRoleToUser(admins, createRbacUser('mike@hostsharing.net'));
call grantRoleToUser(admins, createRbacUser('sven@hostsharing.net'));
commit;
end;
$$;
BEGIN TRANSACTION;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
select * from RbacUser where uuid=currentUserId();
END TRANSACTION;

134
sql/21-hs-customer.sql Normal file
View File

@ -0,0 +1,134 @@
-- ========================================================
-- Customer example with RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT ;
CREATE TABLE IF NOT EXISTS customer (
uuid uuid UNIQUE REFERENCES RbacObject(uuid),
reference int not null unique CHECK (reference BETWEEN 10000 AND 99999),
prefix character(3) unique,
adminUserName varchar(63)
);
DROP TRIGGER IF EXISTS createRbacObjectForCustomer_Trigger ON customer;
CREATE TRIGGER createRbacObjectForCustomer_Trigger
BEFORE INSERT ON customer
FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION createRbacRulesForCustomer()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
adminUserNameUuid uuid;
customerOwnerRoleId uuid;
customerAdminRoleId uuid;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
-- an owner role is created and assigned to the administrators group
customerOwnerRoleId = createRole('customer#'||NEW.prefix||'.owner');
call grantRoleToRole(customerOwnerRoleId, getRoleId('administrators', 'create'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(customerOwnerRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
-- ... also a customer admin role is created and granted to the customer owner role
customerAdminRoleId = createRole('customer#'||NEW.prefix||'.admin');
call grantRoleToRole(customerAdminRoleId, customerOwnerRoleId);
-- ... to which a permission with view and add- ops is assigned
call grantPermissionsToRole(customerAdminRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view', 'add-package']));
-- if a admin user is given for the customer,
IF (NEW.adminUserName IS NOT NULL) THEN
-- ... the customer admin role is also assigned to the admin user of the customer
adminUserNameUuid = findRoleId(NEW.adminUserName);
IF ( adminUserNameUuid IS NULL ) THEN
adminUserNameUuid = createRbacUser(NEW.adminUserName);
END IF;
call grantRoleToUser(customerAdminRoleId, adminUserNameUuid);
END IF;
RETURN NEW;
END; $$;
DROP TRIGGER IF EXISTS createRbacRulesForCustomer_Trigger ON customer;
CREATE TRIGGER createRbacRulesForCustomer_Trigger
AFTER INSERT ON customer
FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForCustomer();
CREATE OR REPLACE FUNCTION deleteRbacRulesForCustomer()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
objectTable varchar = 'customer';
BEGIN
IF TG_OP = 'DELETE' THEN
-- delete the owner role (for admininstrators)
call deleteRole(findRoleId(objectTable||'#'||NEW.prefix||'.owner'));
-- delete the customer admin role
call deleteRole(findRoleId(objectTable||'#'||NEW.prefix||'.admin'));
ELSE
RAISE EXCEPTION 'invalid usage of TRIGGER BEFORE DELETE';
END IF;
END; $$;
DROP TRIGGER IF EXISTS deleteRbacRulesForCustomer_Trigger ON customer;
CREATE TRIGGER deleteRbacRulesForCustomer_Trigger
BEFORE DELETE ON customer
FOR EACH ROW EXECUTE PROCEDURE deleteRbacRulesForCustomer();
-- create RBAC restricted view
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE customer ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS cust_view;
DROP VIEW IF EXISTS customer_rv;
CREATE OR REPLACE VIEW customer_rv AS
SELECT DISTINCT target.*
FROM customer AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;
GRANT ALL PRIVILEGES ON customer_rv TO restricted;
-- generate Customer test data
DO LANGUAGE plpgsql $$
DECLARE
currentTask varchar;
custReference integer;
custRowId uuid;
custPrefix varchar;
custAdminName varchar;
BEGIN
SET hsadminng.currentUser TO '';
FOR t IN 0..9999 LOOP
currentTask = 'creating RBAC test customer #' || t;
SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = '';
SET LOCAL hsadminng.currentTask TO currentTask;
-- When a new customer is created,
custReference = 10000 + t;
custRowId = uuid_generate_v4();
custPrefix = intToVarChar(t, 3 );
custAdminName = 'admin@' || custPrefix || '.example.com';
raise notice 'creating customer %:%', custReference, custPrefix;
insert into customer (reference, prefix, adminUserName)
VALUES (custReference, custPrefix, custAdminName);
COMMIT;
END LOOP;
END;
$$;

117
sql/22-hs-packages.sql Normal file
View File

@ -0,0 +1,117 @@
-- ========================================================
-- Package example with RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT ;
CREATE TABLE IF NOT EXISTS package (
uuid uuid UNIQUE REFERENCES RbacObject(uuid),
name character varying(5),
customerUuid uuid REFERENCES customer(uuid)
);
DROP TRIGGER IF EXISTS createRbacObjectForPackage_Trigger ON package;
CREATE TRIGGER createRbacObjectForPackage_Trigger
BEFORE INSERT ON package
FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION createRbacRulesForPackage()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
parentCustomer customer;
packageOwnerRoleId uuid;
packageTenantRoleId uuid;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
SELECT * FROM customer AS c WHERE c.uuid=NEW.customerUuid INTO parentCustomer;
-- an owner role is created and assigned to the customer's admin group
packageOwnerRoleId = createRole('package#'||NEW.name||'.owner');
call grantRoleToRole(packageOwnerRoleId, getRoleId('customer#'||parentCustomer.prefix||'.admin', 'fail'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(packageOwnerRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
-- ... also a package tenant role is created and assigned to the package owner as well
packageTenantRoleId = createRole('package#'||NEW.name||'.tenant');
call grantRoleToRole(packageTenantRoleId, packageOwnerRoleId);
-- ... to which a permission with view operation is assigned
call grantPermissionsToRole(packageTenantRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view']));
RETURN NEW;
END; $$;
DROP TRIGGER IF EXISTS createRbacRulesForPackage_Trigger ON package;
CREATE TRIGGER createRbacRulesForPackage_Trigger
AFTER INSERT ON package
FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForPackage();
CREATE OR REPLACE FUNCTION deleteRbacRulesForPackage()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
BEGIN
IF TG_OP = 'DELETE' THEN
-- TODO
ELSE
RAISE EXCEPTION 'invalid usage of TRIGGER BEFORE DELETE';
END IF;
END; $$;
DROP TRIGGER IF EXISTS deleteRbacRulesForPackage_Trigger ON customer;
CREATE TRIGGER deleteRbacRulesForPackage_Trigger
BEFORE DELETE ON customer
FOR EACH ROW EXECUTE PROCEDURE deleteRbacRulesForPackage();
-- create RBAC restricted view
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE package ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS package_rv;
CREATE OR REPLACE VIEW package_rv AS
SELECT DISTINCT target.*
FROM package AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;
GRANT ALL PRIVILEGES ON package_rv TO restricted;
-- generate Package test data
DO LANGUAGE plpgsql $$
DECLARE
cust customer;
pacName varchar;
currentTask varchar;
custAdmin varchar;
BEGIN
SET hsadminng.currentUser TO '';
FOR cust IN (SELECT * FROM customer) LOOP
FOR t IN 0..9 LOOP
pacName = cust.prefix || TO_CHAR(t, 'fm00');
currentTask = 'creating RBAC test package #'|| pacName || ' for customer ' || cust.prefix || ' #' || cust.uuid;
RAISE NOTICE 'task: %', currentTask;
custAdmin = 'admin@' || cust.prefix || '.example.com';
SET LOCAL hsadminng.currentUser TO custAdmin;
SET LOCAL hsadminng.assumedRoles = '';
SET LOCAL hsadminng.currentTask TO currentTask;
insert into package (name, customerUuid)
VALUES (pacName, cust.uuid);
COMMIT;
END LOOP;
END LOOP;
END;
$$;

106
sql/23-hs-unixuser.sql Normal file
View File

@ -0,0 +1,106 @@
-- ========================================================
-- UnixUser example with RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT ;
CREATE TABLE IF NOT EXISTS UnixUser (
uuid uuid UNIQUE REFERENCES RbacObject(uuid),
name character varying(32),
packageUuid uuid REFERENCES package(uuid)
);
DROP TRIGGER IF EXISTS createRbacObjectForUnixUser_Trigger ON UnixUser;
CREATE TRIGGER createRbacObjectForUnixUser_Trigger
BEFORE INSERT ON UnixUser
FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION createRbacRulesForUnixUser()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
parentPackage package;
unixuserOwnerRoleId uuid;
unixuserAdminRoleId uuid;
unixuserTenantRoleId uuid;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
SELECT * FROM package WHERE uuid=NEW.packageUuid into parentPackage;
-- an owner role is created and assigned to the package owner group
unixuserOwnerRoleId = createRole('unixuser#'||NEW.name||'.owner');
call grantRoleToRole(unixuserOwnerRoleId, getRoleId('package#'||parentPackage.name||'.owner', 'fail'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(unixuserOwnerRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
-- ... also a unixuser admin role is created and assigned to the unixuser owner as well
unixuserAdminRoleId = createRole('unixuser#'||NEW.name||'.admin');
call grantRoleToRole(unixuserAdminRoleId, unixuserOwnerRoleId);
-- ... to which a permission with view operation is assigned
call grantPermissionsToRole(unixuserAdminRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['edit', 'add-domain']));
-- ... also a unixuser tenant role is created and assigned to the unixuser admin
unixuserTenantRoleId = createRole('unixuser#'||NEW.name||'.tenant');
call grantRoleToRole(unixuserTenantRoleId, unixuserAdminRoleId);
-- ... to which a permission with view operation is assigned
call grantPermissionsToRole(unixuserTenantRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['view']));
RETURN NEW;
END; $$;
DROP TRIGGER IF EXISTS createRbacRulesForUnixUser_Trigger ON UnixUser;
CREATE TRIGGER createRbacRulesForUnixUser_Trigger
AFTER INSERT ON UnixUser
FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForUnixUser();
-- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForUnixUser()
-- create RBAC restricted view
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE unixuser ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS unixuser_rv;
CREATE OR REPLACE VIEW unixuser_rv AS
SELECT DISTINCT target.*
FROM unixuser AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;
GRANT ALL PRIVILEGES ON unixuser_rv TO restricted;
-- generate UnixUser test data
DO LANGUAGE plpgsql $$
DECLARE
pac package;
pacAdmin varchar;
currentTask varchar;
BEGIN
SET hsadminng.currentUser TO '';
FOR pac IN (SELECT * FROM package) LOOP
FOR t IN 0..9 LOOP
currentTask = 'creating RBAC test unixuser #' || t || ' for package ' || pac.name|| ' #' || pac.uuid;
RAISE NOTICE 'task: %', currentTask;
pacAdmin = 'admin@' || pac.name || '.example.com';
SET LOCAL hsadminng.currentUser TO 'mike@hostsharing.net'; -- TODO: use a package-admin
SET LOCAL hsadminng.assumedRoles = '';
SET LOCAL hsadminng.currentTask TO currentTask;
INSERT INTO unixuser (name, packageUuid)
VALUES (pac.name||'-'|| intToVarChar(t, 4), pac.uuid);
COMMIT;
END LOOP;
END LOOP;
END;
$$;

98
sql/24-hs-domain.sql Normal file
View File

@ -0,0 +1,98 @@
-- ========================================================
-- Domain example with RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT ;
CREATE TABLE IF NOT EXISTS Domain (
uuid uuid UNIQUE REFERENCES RbacObject(uuid),
name character varying(32),
unixUserUuid uuid REFERENCES unixuser(uuid)
);
DROP TRIGGER IF EXISTS createRbacObjectForDomain_Trigger ON Domain;
CREATE TRIGGER createRbacObjectForDomain_Trigger
BEFORE INSERT ON Domain
FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION createRbacRulesForDomain()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
parentUser unixuser;
domainOwnerRoleId uuid;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
SELECT * FROM unixuser WHERE uuid=NEW.unixUserUuid into parentUser;
-- an owner role is created and assigned to the unix user admin
RAISE NOTICE 'creating domain owner role: %', 'domain#'||NEW.name||'.owner';
domainOwnerRoleId = getRoleId('domain#'||NEW.name||'.owner', 'create');
call grantRoleToRole(domainOwnerRoleId, getRoleId('unixuser#'||parentUser.name||'.admin', 'fail'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(domainOwnerRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
RETURN NEW;
END; $$;
DROP TRIGGER IF EXISTS createRbacRulesForDomain_Trigger ON Domain;
CREATE TRIGGER createRbacRulesForDomain_Trigger
AFTER INSERT ON Domain
FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForDomain();
-- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForDomain()
-- create RBAC restricted view
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE Domain ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS domain_rv;
CREATE OR REPLACE VIEW domain_rv AS
SELECT DISTINCT target.*
FROM Domain AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;
GRANT ALL PRIVILEGES ON domain_rv TO restricted;
-- generate Domain test data
DO LANGUAGE plpgsql $$
DECLARE
uu unixuser;
pac package;
pacAdmin varchar;
currentTask varchar;
BEGIN
SET hsadminng.currentUser TO '';
FOR uu IN (SELECT * FROM unixuser) LOOP
IF ( random() < 0.3 ) THEN
FOR t IN 0..2 LOOP
currentTask = 'creating RBAC test Domain #' || t || ' for UnixUser ' || uu.name|| ' #' || uu.uuid;
RAISE NOTICE 'task: %', currentTask;
SELECT * FROM package WHERE uuid=uu.packageUuid INTO pac;
pacAdmin = 'admin@' || pac.name || '.example.com';
SET LOCAL hsadminng.currentUser TO pacAdmin;
SET LOCAL hsadminng.assumedRoles = '';
SET LOCAL hsadminng.currentTask TO currentTask;
INSERT INTO Domain (name, unixUserUuid)
VALUES ('dom-' || t || '.' || pac.name || '.example.org' , uu.uuid);
COMMIT;
END LOOP;
END IF;
END LOOP;
END;
$$;

122
sql/25-hs-emailaddress.sql Normal file
View File

@ -0,0 +1,122 @@
-- ========================================================
-- EMailAddress example with RBAC
-- --------------------------------------------------------
SET SESSION SESSION AUTHORIZATION DEFAULT ;
CREATE TABLE IF NOT EXISTS EMailAddress (
uuid uuid UNIQUE REFERENCES RbacObject(uuid),
localPart character varying(64),
domainUuid uuid REFERENCES domain(uuid)
);
DROP TRIGGER IF EXISTS createRbacObjectForEMailAddress_Trigger ON EMailAddress;
CREATE TRIGGER createRbacObjectForEMailAddress_Trigger
BEFORE INSERT ON EMailAddress
FOR EACH ROW EXECUTE PROCEDURE createRbacObject();
CREATE OR REPLACE FUNCTION createRbacRulesForEMailAddress()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
eMailAddress varchar;
parentDomain domain;
eMailAddressOwnerRoleId uuid;
eMailAddressTenantRoleId uuid;
BEGIN
IF TG_OP <> 'INSERT' THEN
RAISE EXCEPTION 'invalid usage of TRIGGER AFTER INSERT';
END IF;
SELECT * FROM domain WHERE uuid=NEW.domainUuid into parentDomain;
eMailAddress = NEW.localPart || '@' || parentDomain.name;
-- an owner role is created and assigned to the domain owner
eMailAddressOwnerRoleId = getRoleId('emailaddress#'||eMailAddress||'.owner', 'create');
call grantRoleToRole(eMailAddressOwnerRoleId, getRoleId('domain#'||parentDomain.name||'.owner', 'fail'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(eMailAddressOwnerRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*']));
-- a tenant role is created and assigned to a user with the new email address
eMailAddressTenantRoleId = getRoleId('emailaddress#'||eMailAddress||'.tenant', 'create');
call grantRoleToUser(eMailAddressTenantRoleId, getRbacUserId(eMailAddress, 'create'));
-- ... and permissions for all ops are assigned
call grantPermissionsToRole(eMailAddressTenantRoleId,
createPermissions(forObjectUuid => NEW.uuid, permitOps => ARRAY['*'])); -- TODO '*' -> 'edit', 'view'
RETURN NEW;
END; $$;
DROP TRIGGER IF EXISTS createRbacRulesForEMailAddress_Trigger ON EMailAddress;
CREATE TRIGGER createRbacRulesForEMailAddress_Trigger
AFTER INSERT ON EMailAddress
FOR EACH ROW EXECUTE PROCEDURE createRbacRulesForEMailAddress();
-- TODO: CREATE OR REPLACE FUNCTION deleteRbacRulesForEMailAddress()
-- create RBAC restricted view
abort;
set session authorization default ;
START TRANSACTION;
SET LOCAL hsadminng.currentUser = 'mike@hostsharing.net';
SET LOCAL hsadminng.assumedRoles = 'customer#bbb.owner;customer#bbc.owner';
-- SET LOCAL hsadminng.assumedRoles = 'package#bbb00.owner;package#bbb01.owner';
select count(*) from queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds(), 7) as a
join rbacobject as o on a=o.uuid;
/* SELECT DISTINCT target.*
FROM EMailAddress AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;*/
END TRANSACTION;
SET SESSION SESSION AUTHORIZATION DEFAULT;
ALTER TABLE EMailAddress ENABLE ROW LEVEL SECURITY;
DROP VIEW IF EXISTS EMailAddress_rv;
CREATE OR REPLACE VIEW EMailAddress_rv AS
SELECT DISTINCT target.*
FROM EMailAddress AS target
JOIN queryAccessibleObjectUuidsOfSubjectIds( 'view', currentSubjectIds()) AS allowedObjId
ON target.uuid = allowedObjId;
GRANT ALL PRIVILEGES ON EMailAddress_rv TO restricted;
-- generate EMailAddress test data
DO LANGUAGE plpgsql $$
DECLARE
pac package;
uu unixuser;
dom domain;
pacAdmin varchar;
currentTask varchar;
BEGIN
SET hsadminng.currentUser TO '';
FOR dom IN (SELECT * FROM domain) LOOP
FOR t IN 0..5 LOOP
currentTask = 'creating RBAC test EMailAddress #' || t || ' for Domain ' || dom.name;
RAISE NOTICE 'task: %', currentTask;
SELECT * FROM unixuser WHERE uuid=dom.unixuserUuid INTO uu;
SELECT * FROM package WHERE uuid=uu.packageUuid INTO pac;
pacAdmin = 'admin@' || pac.name || '.example.com';
SET LOCAL hsadminng.currentUser TO pacAdmin;
SET LOCAL hsadminng.assumedRoles = '';
SET LOCAL hsadminng.currentTask TO currentTask;
INSERT INTO EMailAddress (localPart, domainUuid)
VALUES ('local' || t, dom.uuid);
COMMIT;
END LOOP;
END LOOP;
END;
$$;

24
sql/29-hs-statistics.sql Normal file
View File

@ -0,0 +1,24 @@
-- ========================================================
-- Some Business Table Statistics
-- --------------------------------------------------------
DROP VIEW IF EXISTS "BusinessTableStatisticsV";
CREATE VIEW "BusinessTableStatisticsV" AS
SELECT no, to_char("count", '999 999 999') as "count", to_char("required", '999 999 999') as "required", to_char("count"::float/"required"::float, '990.9') as "factor", "table"
FROM (select 1 as no, count(*) as "count", 7000 as "required", 'customers' as "table"
from customer
UNION
select 2 as no, count(*) as "count", 15000 as "required", 'packages' as "table"
from package
UNION
select 3 as no, count(*) as "count", 150000 as "required", 'unixuser' as "table"
from unixuser
UNION
select 4 as no, count(*) as "count", 100000 as "required", 'domain' as "table"
from domain
UNION
select 5 as no, count(*) as "count", 500000 as "required", 'emailaddress' as "table"
from emailaddress
) totals
ORDER BY totals.no;

62
sql/examples.sql Normal file
View File

@ -0,0 +1,62 @@
-- ========================================================
-- First Example Entity with History
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS customer (
"id" SERIAL PRIMARY KEY,
"reference" int not null unique, -- 10000-99999
"prefix" character(3) unique
);
CALL create_historicization('customer');
-- ========================================================
-- Second Example Entity with History
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS package_type (
"id" serial PRIMARY KEY,
"name" character varying(8)
);
CALL create_historicization('package_type');
-- ========================================================
-- Third Example Entity with History
-- --------------------------------------------------------
CREATE TABLE IF NOT EXISTS package (
"id" serial PRIMARY KEY,
"name" character varying(5),
"customer_id" INTEGER REFERENCES customer(id)
);
CALL create_historicization('package');
-- ========================================================
-- query historical data
-- --------------------------------------------------------
ABORT;
BEGIN TRANSACTION;
SET LOCAL hsadminng.currentUser TO 'mih42_customer_aaa';
SET LOCAL hsadminng.currentTask TO 'adding customer_aaa';
INSERT INTO package (customer_id, name) VALUES (10000, 'aaa00');
COMMIT;
SET SESSION SESSION AUTHORIZATION DEFAULT;
CREATE ROLE hs_sel_package_1000000;
GRANT hs_sel_package_1000000 to hs_sel_customer_10000;
SET SESSION SESSION AUTHORIZATION mih42_customer_aaa;
SELECT pg_has_role('hs_sel_package_1000000', 'MEMBER');
-- Usage:
SET hsadminng.timestamp TO '2022-07-12 08:53:27.723315';
SET hsadminng.timestamp TO '2022-07-12 11:38:27.723315';
SELECT * FROM customer_hv p WHERE prefix = 'aaa';

166
sql/historization.sql Normal file
View File

@ -0,0 +1,166 @@
-- ========================================================
-- Historization
-- --------------------------------------------------------
CREATE TABLE "tx_history" (
"tx_id" BIGINT NOT NULL UNIQUE,
"tx_timestamp" TIMESTAMP NOT NULL,
"user" VARCHAR(64) NOT NULL, -- references postgres user
"task" VARCHAR NOT NULL
);
CREATE TYPE "operation" AS ENUM ('INSERT', 'UPDATE', 'DELETE', 'TRUNCATE');
-- see https://www.postgresql.org/docs/current/plpgsql-trigger.html
CREATE OR REPLACE FUNCTION historicize()
RETURNS trigger
LANGUAGE plpgsql STRICT AS $$
DECLARE
currentUser VARCHAR(64);
currentTask varchar;
"row" RECORD;
"alive" BOOLEAN;
"sql" varchar;
BEGIN
-- determine user_id
BEGIN
currentUser := current_setting('hsadminng.currentUser');
EXCEPTION WHEN OTHERS THEN
currentUser := NULL;
END;
IF (currentUser IS NULL OR currentUser = '') THEN
RAISE EXCEPTION 'hsadminng.currentUser must be defined, please use "SET LOCAL ...;"';
END IF;
RAISE NOTICE 'currentUser: %', currentUser;
-- determine task
currentTask = current_setting('hsadminng.currentTask');
IF (currentTask IS NULL OR length(currentTask) < 12) THEN
RAISE EXCEPTION 'hsadminng.currentTask (%) must be defined and min 12 characters long, please use "SET LOCAL ...;"', currentTask;
END IF;
RAISE NOTICE 'currentTask: %', currentTask;
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN
"row" := NEW;
"alive" := TRUE;
ELSE -- DELETE or TRUNCATE
"row" := OLD;
"alive" := FALSE;
END IF;
sql := format('INSERT INTO tx_history VALUES (txid_current(), now(), %1L, %2L) ON CONFLICT DO NOTHING', currentUser, currentTask);
RAISE NOTICE 'sql: %', sql;
EXECUTE sql;
sql := format('INSERT INTO %3$I_versions VALUES (DEFAULT, txid_current(), %1$L, %2$L, $1.*)', TG_OP, alive, TG_TABLE_NAME);
RAISE NOTICE 'sql: %', sql;
EXECUTE sql USING "row";
RETURN "row";
END; $$;
CREATE OR REPLACE PROCEDURE create_historical_view(baseTable varchar)
LANGUAGE plpgsql AS $$
DECLARE
createTriggerSQL varchar;
viewName varchar;
versionsTable varchar;
createViewSQL varchar;
baseCols varchar;
BEGIN
viewName = quote_ident(format('%s_hv', baseTable));
versionsTable = quote_ident(format('%s_versions', baseTable));
baseCols = (SELECT string_agg(quote_ident(column_name), ', ')
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = baseTable);
createViewSQL = format(
'CREATE OR REPLACE VIEW %1$s AS' ||
'(' ||
' SELECT %2$s' ||
' FROM %3$s' ||
' WHERE alive = TRUE' ||
' AND version_id IN' ||
' (' ||
' SELECT max(vt.version_id) AS history_id' ||
' FROM %3$s AS vt' ||
' JOIN tx_history as txh ON vt.tx_id = txh.tx_id' ||
' WHERE txh.tx_timestamp <= current_setting(''hsadminng.timestamp'')::timestamp' ||
' GROUP BY id' ||
' )' ||
')',
viewName, baseCols, versionsTable
);
RAISE NOTICE 'sql: %', createViewSQL;
EXECUTE createViewSQL;
createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_historicize' ||
' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable ||
' FOR EACH ROW EXECUTE PROCEDURE historicize()';
RAISE NOTICE 'sql: %', createTriggerSQL;
EXECUTE createTriggerSQL;
END; $$;
CREATE OR REPLACE PROCEDURE create_historicization(baseTable varchar)
LANGUAGE plpgsql AS $$
DECLARE
createHistTableSql varchar;
createTriggerSQL varchar;
viewName varchar;
versionsTable varchar;
createViewSQL varchar;
baseCols varchar;
BEGIN
-- create the history table
createHistTableSql = '' ||
'CREATE TABLE ' || baseTable || '_versions (' ||
' version_id serial PRIMARY KEY,' ||
' tx_id bigint NOT NULL REFERENCES tx_history(tx_id),' ||
' trigger_op operation NOT NULL,' ||
' alive boolean not null,' ||
' LIKE ' || baseTable ||
' EXCLUDING CONSTRAINTS' ||
' EXCLUDING STATISTICS' ||
')';
RAISE NOTICE 'sql: %', createHistTableSql;
EXECUTE createHistTableSql;
-- create the historical view
viewName = quote_ident(format('%s_hv', baseTable));
versionsTable = quote_ident(format('%s_versions', baseTable));
baseCols = (SELECT string_agg(quote_ident(column_name), ', ')
FROM information_schema.columns
WHERE table_schema = 'public' AND table_name = baseTable);
createViewSQL = format(
'CREATE OR REPLACE VIEW %1$s AS' ||
'(' ||
' SELECT %2$s' ||
' FROM %3$s' ||
' WHERE alive = TRUE' ||
' AND version_id IN' ||
' (' ||
' SELECT max(vt.version_id) AS history_id' ||
' FROM %3$s AS vt' ||
' JOIN tx_history as txh ON vt.tx_id = txh.tx_id' ||
' WHERE txh.tx_timestamp <= current_setting(''hsadminng.timestamp'')::timestamp' ||
' GROUP BY id' ||
' )' ||
')',
viewName, baseCols, versionsTable
);
RAISE NOTICE 'sql: %', createViewSQL;
EXECUTE createViewSQL;
createTriggerSQL = 'CREATE TRIGGER ' || baseTable || '_historicize' ||
' AFTER INSERT OR DELETE OR UPDATE ON ' || baseTable ||
' FOR EACH ROW EXECUTE PROCEDURE historicize()';
RAISE NOTICE 'sql: %', createTriggerSQL;
EXECUTE createTriggerSQL;
END; $$;

View File

@ -1,105 +0,0 @@
--
-- Historization
--
CREATE TABLE history (
history_id serial PRIMARY KEY,
history_transaction bigint NOT NULL UNIQUE,
history_timestamp timestamp NOT NULL
);
CREATE FUNCTION historicize() RETURNS trigger
AS $$
BEGIN
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN
EXECUTE 'INSERT INTO history VALUES (DEFAULT, txid_current(), now()) ON CONFLICT DO NOTHING';
EXECUTE format('INSERT INTO %I_history VALUES (DEFAULT, txid_current(), False, $1.*)', TG_TABLE_NAME) USING NEW;
RETURN NEW;
ELSE
EXECUTE 'INSERT INTO history VALUES (DEFAULT, txid_current(), now()) ON CONFLICT DO NOTHING';
EXECUTE format('INSERT INTO %I_history VALUES (DEFAULT, txid_current(), True, $1.*)', TG_TABLE_NAME) USING OLD;
RETURN OLD;
END IF;
END;
$$
LANGUAGE plpgsql;
--
-- Entity with History
--
CREATE TABLE person (
id serial PRIMARY KEY,
name character varying(50) NOT NULL UNIQUE,
email character varying(50) NOT NULL UNIQUE
);
CREATE TABLE person_history (
history_id serial PRIMARY KEY,
history_transaction bigint NOT NULL REFERENCES history(history_transaction),
history_tombstone boolean NOT NULL,
id integer NOT NULL,
name character varying(50) NOT NULL,
email character varying(50) NOT NULL
);
CREATE TRIGGER person_historicize AFTER INSERT OR DELETE OR UPDATE ON person FOR EACH ROW EXECUTE PROCEDURE historicize();
--
-- Sample data
--
INSERT INTO person (name, email) VALUES ('michael', 'michael@hierweck.de');
INSERT INTO person (name, email) VALUES ('annika', 'annika@hierweck.de');
UPDATE person SET email='mh@hierweck.de' WHERE name='michael';
UPDATE person SET email='ah@hierweck.de' WHERE name='annika';
DELETE FROM person WHERE name='michael';
DELETE FROM person WHERE name='annika';
INSERT INTO person (name, email) VALUES ('michael', 'michael@hierweck.de');
INSERT INTO person (name, email) VALUES ('annika', 'annika@hierweck.de');
BEGIN;
INSERT INTO person (name, email) VALUES ('mx', 'mx@hierweck.de');
INSERT INTO person (name, email) VALUES ('ax', 'ax@hierweck.de');
UPDATE person SET email='mxx@hierweck.de' WHERE name='mx';
UPDATE person SET email='axx@hierweck.de' WHERE name='ax';
COMMIT;
--
-- Approach 1: Function
--
--
-- Usage:
--
-- SELECT * FROM person_history(12345, 'name');
--
CREATE OR REPLACE FUNCTION person_history(transaction bigint, VARIADIC groupby text[]) RETURNS TABLE (
history_id integer,
history_transaction bigint,
history_tombstone boolean,
id integer,
name character varying(50),
email character varying(50)
)
AS $$
BEGIN
RETURN QUERY EXECUTE format('SELECT * FROM person_history WHERE history_id IN (SELECT max(history_id) AS history_id FROM person_history WHERE history_transaction <= $1 GROUP BY %s)', array_to_string(groupby, ', ')) USING transaction;
END;
$$
LANGUAGE plpgsql;
--
-- Approach 2: View
--
-- Usage:
--
-- SET history_transaction = 12345;
-- SELECT * FROM person_history_view;
--
CREATE VIEW person_history_view
AS (SELECT * FROM person_history WHERE history_id IN (SELECT max(history_id) AS history_id FROM person_history WHERE history_transaction <= current_setting('history.transaction')::bigint GROUP BY name));

18
sql/rbac-statistics.sql Normal file
View File

@ -0,0 +1,18 @@
DROP VIEW "RbacStatisticsV";
CREATE VIEW "RbacStatisticsV" AS
SELECT no, to_char("count", '9 999 999 999') as "count", "table"
FROM (
select 1 as no, count(*) as "count", 'login users' as "table" from RbacUser
UNION
select 2 as no, count(*) as "count", 'roles' as "table" from RbacRole
UNION
select 3 as no, count(*) as "count", 'permissions' as "table" from RbacPermission
UNION
select 4 as no, count(*) as "count", 'references' as "table" from RbacReference
UNION
select 5 as no, count(*) as "count", 'grants' as "table" from RbacGrants
UNION
select 6 as no, count(*) as "count", 'objects' as "table" from RbacObject
) as totals
ORDER BY totals.no;

301
sql/rbac.md Normal file
View File

@ -0,0 +1,301 @@
## *hsadmin-ng*'s Role-Based-Access-Management (RBAC)
The requirements of *hsadmin-ng* include table-m row- and column-level-security for read and write access to business-objects.
More precisely, any access has to be controlled according to given rules depending on the accessing users, their roles and the accessed business-object.
Further, roles and business-objects are hierarchical.
To avoid misunderstandings, we are using the term "business-object" what's usually called a "domain-object".
But as we are in the context of a webhosting infrastructure provider, "domain" would have a double meaning.
Our implementation is based on Role-Based-Access-Management (RBAC) in conjunction with views and triggers on the business-objects.
As far as possible, we are using the same terms as defined in the RBAC standard, for our function names though, we chose more expressive names.
In RBAC, subjects can be assigned to roles, roles can be hierarchical and eventually have assigned permissions.
A permission allows a specific operation (e.g. view or edit) on a specific (business-) object.
You can find the entity structure as a UML class diagram as follows:
```plantuml
@startuml
' left to right direction
top to bottom direction
' hide the ugly E in a circle left to the entity name
hide circle
' use right-angled line routing
skinparam linetype ortho
package RBAC {
' forward declarations
entity RbacUser
entity RbacObject
together {
entity RbacRole
entity RbacPermission
enum RbacOperation
RbacUser -[hidden]> RbacRole
RbacRole -[hidden]> RbacUser
}
together {
entity RbacGrant
enum RbacReferenceType
entity RbacReference
}
RbacReference -[hidden]> RbacReferenceType
entity RbacGrant {
ascendantUuid: uuid(RbackReference)
descendantUuid: uuid(RbackReference)
auto
}
RbacGrant o-> RbacReference
RbacGrant o-> RbacReference
enum RbacReferenceType {
RbacUser
RbacRole
RbacPermission
}
RbacReferenceType ..> RbacUser
RbacReferenceType ..> RbacRole
RbacReferenceType ..> RbacPermission
entity RbacReference {
*uuid : uuid <<generated>>
--
type : RbacReferenceType
}
RbacReference o--> RbacReferenceType
entity RbacUser {
*uuid : uuid <<generated>>
--
name : varchar
}
RbacUser o-- RbacReference
entity RbacRole {
*uuid : uuid(RbacReference)
--
name : varchar
}
RbacRole o-- RbacReference
entity RbacPermission {
*uuid : uuid(RbacReference)
--
objectUuid: RbacObject
op: RbacOperation
}
RbacPermission o-- RbacReference
RbacPermission o-- RbacOperation
RbacPermission *-- RbacObject
enum RbacOperation {
add-package
add-domain
add-unixuser
...
view
edit
delete
}
entity RbacObject {
*uuid : uuid <<generated>>
--
objectTable: varchar
}
RbacObject o- "Business Objects"
}
package "Business Objects" {
entity package
package *--u- RbacObject
entity customer
customer *--u- RbacObject
entity "..." as moreBusinessObjects
moreBusinessObjects *-u- RbacObject
}
@enduml
```
### The RBAC Entity Types
#### RbacReference
An *RbacReference* is a generalization of all entity types which participate in the hierarchical role system, defined via *RbacGrant*.
The primary key of the *RbacReference* and its referred object is always identical.
#### RbacUser
An *RbacUser* is a type of RBAC-subject which references a login account outside this system, identified by a name (usually an email-address).
*RbacUser*s can be assigned to multiple *RbacRole*s, through which they can get permissions to *RbacObject*s.
The primary key of the *RbacUser* is identical to its related *RbacReference*.
#### RbacRole
An *RbacRole* represents a collection of directly or indirectly assigned *RbacPermission*s.
Each *RbacRole* can be assigned to *RbacUser*s or to another *RbacRole*.
Both kinds of assignments are represented via *RbacGrant*.
*RbacRole* entities can *RbacObject*s, or more precise
#### RbacPermission
An *RbacPermission* allows a specific *RbacOperation* on a specific *RbacObject*.
#### RbacOperation
An *RbacOperation* determines, <u>what</u> an *RbacPermission* allows to do.
It can be one of:
- **add-...** - permits creating new instances of specific entity types underneath the object specified by the permission, e.g. "add-package"
- **view** - permits reading the contents of the object specified by the permission
- **edit** - change the contents of the object specified by the permission
- **delete** - delete the object specified by the permission
This list is extensible according to the needs of the access rule system.
Please notice, that there is no **create-...** operation to create new instances of related business-object-types.
For such a singleton business-object-type, e.g. *Organization" or "Hostsharing" has to be defined, and its single entity is referred in the permission.
By this, the foreign key in *RbacPermission* can be defined as `NOT NULL`.
#### RbacGrant
The *RbacGrant* entities represent the access-rights structure from *RbacUser*s via hierarchical *RbacRoles* down to *RbacPermission*s.
The core SQL queries to determine access rights are all recursive queries on the *RbacGrant* table.
### Role naming
Automatically generated roles are named as such:
#### business-table#business-object-name.tenant
This role is assigned to users who manage objects underneath the object which is accessible through the role.
This rule usually gets only view permissions assigned.
**Example**
'dd'
## Example Users, Roles, Permissions and Business-Objects
```plantuml
@startuml
' left to right direction
top to bottom direction
' hide the ugly E in a circle left to the entity name
hide circle
' use right-angled line routing
' skinparam linetype ortho
package RbacUsers {
object UserMike
object UserSuse
object UserPaul
}
package RbacRoles {
object RoleAdministrators
object RoleCustXyz_Owner
object RoleCustXyz_Admin
object RolePackXyz00_Owner
}
RbacUsers -[hidden]> RbacRoles
package RbacPermissions {
object PermCustXyz_View
object PermCustXyz_Edit
object PermCustXyz_Delete
object PermCustXyz_AddPackage
object PermPackXyz00_View
object PermPackXyz00_Edit
object PermPackXyz00_Delete
object PermPackXyz00_AddUser
}
RbacRoles -[hidden]> RbacPermissions
package BusinessObjects {
object CustXyz
object PackXyz00
}
RbacPermissions -[hidden]> BusinessObjects
UserMike o---> RoleAdministrators
UserSuse o--> RoleCustXyz_Admin
UserPaul o--> RolePackXyz00_Owner
RoleAdministrators o..> RoleCustXyz_Owner
RoleCustXyz_Owner o-> RoleCustXyz_Admin
RoleCustXyz_Admin o-> RolePackXyz00_Owner
RoleCustXyz_Owner o--> PermCustXyz_Edit
RoleCustXyz_Owner o--> PermCustXyz_Delete
RoleCustXyz_Admin o--> PermCustXyz_View
RoleCustXyz_Admin o--> PermCustXyz_AddPackage
RolePackXyz00_Owner o--> PermPackXyz00_View
RolePackXyz00_Owner o--> PermPackXyz00_Edit
RolePackXyz00_Owner o--> PermPackXyz00_Delete
RolePackXyz00_Owner o--> PermPackXyz00_AddUser
PermCustXyz_View o--> CustXyz
PermCustXyz_Edit o--> CustXyz
PermCustXyz_Delete o--> CustXyz
PermCustXyz_AddPackage o--> CustXyz
PermPackXyz00_View o--> PackXyz00
PermPackXyz00_Edit o--> PackXyz00
PermPackXyz00_Delete o--> PackXyz00
PermPackXyz00_AddUser o--> PackXyz00
@enduml
```
```plantuml
@startuml
left to right direction
' top to bottom direction
' hide the ugly E in a circle left to the entity name
hide circle
' use right-angled line routing
' skinparam linetype ortho
package rbacPerms {
cust
}
package rbacRoles {
entity administrators
entity custXXX
}
package rbacUsers {
entity adminMike
adminMike <-- administrators
entity adminSven
entity custXXX
entity pacAdmXXX00
}
@enduml
```

2
sql/rbac.sql Normal file
View File

@ -0,0 +1,2 @@

View File

@ -1,14 +0,0 @@
# https://docs.docker.com/engine/reference/builder/#dockerignore-file
classes/
generated-sources/
generated-test-sources/
h2db/
maven-archiver/
maven-status/
reports/
surefire-reports/
test-classes/
test-results/
www/
!*.jar
!*.war

View File

@ -1,20 +0,0 @@
FROM openjdk:8-jre-alpine
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
JHIPSTER_SLEEP=0 \
JAVA_OPTS=""
# Add a jhipster user to run our application so that it doesn't need to run as root
RUN adduser -D -s /bin/sh jhipster
WORKDIR /home/jhipster
ADD entrypoint.sh entrypoint.sh
RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh
USER jhipster
ENTRYPOINT ["./entrypoint.sh"]
EXPOSE 8080
ADD *.war app.war

View File

@ -1,15 +0,0 @@
version: '2'
services:
hsadminng-app:
image: hsadminng
environment:
- _JAVA_OPTIONS=-Xmx512m -Xms256m
- SPRING_PROFILES_ACTIVE=prod,swagger
- SPRING_DATASOURCE_URL=jdbc:postgresql://hsadminng-postgresql:5432/hsadminNg
- JHIPSTER_SLEEP=10 # gives time for the database to boot before the application
ports:
- 8080:8080
hsadminng-postgresql:
extends:
file: postgresql.yml
service: hsadminng-postgresql

View File

@ -1,4 +0,0 @@
#!/bin/sh
echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP}
exec java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar "${HOME}/app.war" "$@"

View File

@ -1,15 +0,0 @@
version: '2'
services:
jenkins:
image: jenkins:latest
ports:
- 49001:8080
- 50000:50000
# uncomment for docker in docker
#privileged: true
#volumes:
# enable persistent volume (warning: make sure that the local jenkins_home folder is created)
#- ~/volumes/jenkins_home:/var/jenkins_home
# mount docker sock and binary for docker in docker (only works on linux)
#- /var/run/docker.sock:/var/run/docker.sock
#- /usr/bin/docker:/usr/bin/docker

View File

@ -1,11 +0,0 @@
version: '2'
services:
hsadminng-postgresql:
image: postgres:10.4
# volumes:
# - ~/volumes/jhipster/hsadminNg/postgresql/:/var/lib/postgresql/data/
environment:
- POSTGRES_USER=hsadminNg
- POSTGRES_PASSWORD=
ports:
- 5432:5432

View File

@ -1,7 +0,0 @@
version: '2'
services:
hsadminng-sonar:
image: sonarqube:7.1
ports:
- 9001:9000
- 9092:9092

View File

@ -1,6 +0,0 @@
version: '2'
services:
swagger-editor:
image: swaggerapi/swagger-editor:latest
ports:
- 7742:8080

View File

@ -1,23 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng;
import org.hostsharing.hsadminng.config.DefaultProfileUtil;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
/**
* This is a helper Java class that provides an alternative to creating a 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(HsadminNgApp.class);
}
}

View File

@ -1,111 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng;
import org.hostsharing.hsadminng.config.ApplicationProperties;
import org.hostsharing.hsadminng.config.DefaultProfileUtil;
import org.hostsharing.hsadminng.service.accessfilter.Role;
import io.github.jhipster.config.JHipsterConstants;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.core.env.Environment;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Collection;
import javax.annotation.PostConstruct;
@SpringBootApplication
@EnableConfigurationProperties({ LiquibaseProperties.class, ApplicationProperties.class })
public class HsadminNgApp {
private static final Logger log = LoggerFactory.getLogger(HsadminNgApp.class);
private final Environment env;
public HsadminNgApp(Environment env) {
this.env = env;
// TODO mhoennig rather use @PostConstruct or something more decentral
Role.init();
}
/**
* Initializes hsadminNg.
* <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(HsadminNgApp.class);
DefaultProfileUtil.addDefaultProfile(app);
Environment env = app.run(args).getEnvironment();
logApplicationStartup(env);
}
private static void logApplicationStartup(Environment env) {
String protocol = "http";
if (env.getProperty("server.ssl.key-store") != null) {
protocol = "https";
}
String serverPort = env.getProperty("server.port");
String contextPath = env.getProperty("server.servlet.context-path");
if (StringUtils.isBlank(contextPath)) {
contextPath = "/";
}
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(
"\n----------------------------------------------------------\n\t" +
"Application '{}' is running! Access URLs:\n\t" +
"Local: \t\t{}://localhost:{}{}\n\t" +
"External: \t{}://{}:{}{}\n\t" +
"Profile(s): \t{}\n----------------------------------------------------------",
env.getProperty("spring.application.name"),
protocol,
serverPort,
contextPath,
protocol,
hostAddress,
serverPort,
contextPath,
env.getActiveProfiles());
}
}

View File

@ -1,116 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.aop.logging;
import io.github.jhipster.config.JHipsterConstants;
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 java.util.Arrays;
/**
* 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 Logger log = LoggerFactory.getLogger(this.getClass());
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.hostsharing.hsadminng.repository..*)" +
" || within(org.hostsharing.hsadminng.service..*)" +
" || within(org.hostsharing.hsadminng.web.rest..*)")
public void applicationPackagePointcut() {
// Method is empty as this is just a Pointcut, the implementations are in the advices.
}
/**
* 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(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
log.error(
"Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'",
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(),
e.getCause() != null ? e.getCause() : "NULL",
e.getMessage(),
e);
} else {
log.error(
"Exception in {}.{}() with cause = {}",
joinPoint.getSignature().getDeclaringTypeName(),
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 IllegalArgumentException
*/
@Around("applicationPackagePointcut() && springBeanPointcut()")
public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
if (log.isDebugEnabled()) {
log.debug(
"Enter: {}.{}() with argument[s] = {}",
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(),
Arrays.toString(joinPoint.getArgs()));
}
try {
Object result = joinPoint.proceed();
if (log.isDebugEnabled()) {
log.debug(
"Exit: {}.{}() with result = {}",
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName(),
result);
}
return result;
} catch (IllegalArgumentException e) {
log.error(
"Illegal argument: {} in {}.{}()",
Arrays.toString(joinPoint.getArgs()),
joinPoint.getSignature().getDeclaringTypeName(),
joinPoint.getSignature().getName());
throw e;
}
}
}

View File

@ -1,15 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* Properties specific to Hsadmin Ng.
* <p>
* Properties are configured in the application.yml file.
* See {@link io.github.jhipster.config.JHipsterProperties} for a good example.
*/
@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
public class ApplicationProperties {
}

View File

@ -1,60 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
import io.github.jhipster.config.JHipsterProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.*;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer, SchedulingConfigurer {
private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
private final JHipsterProperties jHipsterProperties;
public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
this.jHipsterProperties = jHipsterProperties;
}
@Override
@Bean(name = "taskExecutor")
public Executor getAsyncExecutor() {
log.debug("Creating Async Task Executor");
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
executor.setThreadNamePrefix("hsadmin-ng-Executor-");
return new ExceptionHandlingAsyncTaskExecutor(executor);
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return new SimpleAsyncUncaughtExceptionHandler();
}
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(scheduledTaskExecutor());
}
@Bean
public Executor scheduledTaskExecutor() {
return Executors.newScheduledThreadPool(jHipsterProperties.getAsync().getCorePoolSize());
}
}

View File

@ -1,45 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.JHipsterProperties;
import org.ehcache.config.builders.*;
import org.ehcache.jsr107.Eh107Configuration;
import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.*;
import java.time.Duration;
@Configuration
@EnableCaching
public class CacheConfiguration {
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 -> {
cm.createCache(org.hostsharing.hsadminng.repository.UserRepository.USERS_BY_LOGIN_CACHE, jcacheConfiguration);
cm.createCache(org.hostsharing.hsadminng.repository.UserRepository.USERS_BY_EMAIL_CACHE, jcacheConfiguration);
// jhipster-needle-ehcache-add-entry
cm.createCache(
org.hostsharing.hsadminng.repository.UserRoleAssignmentRepository.CURRENT_USER_ROLE_ASSIGNMENTS_CACHE,
jcacheConfiguration);
};
}
}

View File

@ -1,28 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.JHipsterConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cloud.config.java.AbstractCloudConfig;
import org.springframework.context.annotation.*;
import javax.sql.DataSource;
@Configuration
@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
public class CloudDatabaseConfiguration extends AbstractCloudConfig {
private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
private static final String CLOUD_CONFIGURATION_HIKARI_PREFIX = "spring.datasource.hikari";
@Bean
@ConfigurationProperties(CLOUD_CONFIGURATION_HIKARI_PREFIX)
public DataSource dataSource() {
log.info("Configuring JDBC datasource from a cloud provider");
return connectionFactory().dataSource();
}
}

View File

@ -1,18 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
/**
* Application constants.
*/
public final class Constants {
// Regex for acceptable logins
public static final String LOGIN_REGEX = "^[_.@A-Za-z0-9-]*$";
public static final String SYSTEM_ACCOUNT = "system";
public static final String ANONYMOUS_USER = "anonymoususer";
public static final String DEFAULT_LANGUAGE = "de";
private Constants() {
}
}

View File

@ -1,60 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.h2.H2ConfigurationHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import java.sql.SQLException;
@Configuration
@EnableJpaRepositories("org.hostsharing.hsadminng.repository")
@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
@EnableTransactionManagement
public class DatabaseConfiguration {
private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
private final Environment env;
public DatabaseConfiguration(Environment env) {
this.env = env;
}
/**
* Open the TCP port for the H2 database, so it is available remotely.
*
* @return the H2 database TCP server
* @throws SQLException if the server failed to start
*/
@Bean(initMethod = "start", destroyMethod = "stop")
@Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
public Object h2TCPServer() throws SQLException {
String port = getValidPortForH2();
log.debug("H2 database is available on port {}", port);
return H2ConfigurationHelper.createServer(port);
}
private String getValidPortForH2() {
int port = Integer.parseInt(env.getProperty("server.port"));
if (port < 10000) {
port = 10000 + port;
} else {
if (port < 63536) {
port = port + 2000;
} else {
port = port - 2000;
}
}
return String.valueOf(port);
}
}

View File

@ -1,21 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.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);
}
}

View File

@ -1,52 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.JHipsterConstants;
import org.springframework.boot.SpringApplication;
import org.springframework.core.env.Environment;
import java.util.*;
/**
* Utility class to load a Spring profile to be used as default
* when there is no <code>spring.profiles.active</code> set in the environment or as command line argument.
* If the value is not available in <code>application.yml</code> then <code>dev</code> profile will be used as default.
*/
public final class DefaultProfileUtil {
private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
private DefaultProfileUtil() {
}
/**
* Set a default to use when no profile is configured.
*
* @param app the Spring application
*/
public static void addDefaultProfile(SpringApplication app) {
Map<String, Object> defProperties = new HashMap<>();
/*
* The default profile to use when no other profiles are defined
* This cannot be set in the <code>application.yml</code> file.
* See https://github.com/spring-projects/spring-boot/issues/1219
*/
defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
app.setDefaultProperties(defProperties);
}
/**
* Get the profiles that are applied else get default profiles.
*
* @param env spring environment
* @return profiles
*/
public static String[] getActiveProfiles(Environment env) {
String[] profiles = env.getActiveProfiles();
if (profiles.length == 0) {
return env.getDefaultProfiles();
}
return profiles;
}
}

View File

@ -1,64 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.zalando.problem.ProblemModule;
import org.zalando.problem.violations.ConstraintViolationProblemModule;
@Configuration
public class JacksonConfiguration {
/**
* Support for Java date and time API.
*
* @return the corresponding Jackson module.
*/
@Bean
public JavaTimeModule javaTimeModule() {
return new JavaTimeModule();
}
@Bean
public Jdk8Module jdk8TimeModule() {
return new Jdk8Module();
}
/*
* Support for Hibernate types in Jackson.
*/
@Bean
public Hibernate5Module hibernate5Module() {
return new Hibernate5Module();
}
/*
* Jackson Afterburner module to speed up serialization/deserialization.
*/
@Bean
public AfterburnerModule afterburnerModule() {
return new AfterburnerModule();
}
/*
* Module for serialization/deserialization of RFC7807 Problem.
*/
@Bean
ProblemModule problemModule() {
return new ProblemModule();
}
/*
* Module for serialization/deserialization of ConstraintViolationProblem.
*/
@Bean
ConstraintViolationProblemModule constraintViolationProblemModule() {
return new ConstraintViolationProblemModule();
}
}

View File

@ -1,52 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
import liquibase.integration.spring.SpringLiquibase;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.core.task.TaskExecutor;
import javax.sql.DataSource;
@Configuration
public class LiquibaseConfiguration {
private final Logger log = LoggerFactory.getLogger(LiquibaseConfiguration.class);
private final Environment env;
public LiquibaseConfiguration(Environment env) {
this.env = env;
}
@Bean
public SpringLiquibase liquibase(
@Qualifier("taskExecutor") TaskExecutor taskExecutor,
DataSource dataSource,
LiquibaseProperties liquibaseProperties) {
// Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
liquibase.setDataSource(dataSource);
liquibase.setChangeLog("classpath:config/liquibase/master.xml");
liquibase.setContexts(liquibaseProperties.getContexts());
liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
liquibase.setDropFirst(liquibaseProperties.isDropFirst());
liquibase.setChangeLogParameters(liquibaseProperties.getParameters());
if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
liquibase.setShouldRun(false);
} else {
liquibase.setShouldRun(liquibaseProperties.isEnabled());
log.debug("Configuring Liquibase");
}
return liquibase;
}
}

View File

@ -1,28 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
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;
@Configuration
public class LocaleConfiguration implements WebMvcConfigurer {
@Bean(name = "localeResolver")
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);
}
}

View File

@ -1,20 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import org.hostsharing.hsadminng.aop.logging.LoggingAspect;
import io.github.jhipster.config.JHipsterConstants;
import org.springframework.context.annotation.*;
import org.springframework.core.env.Environment;
@Configuration
@EnableAspectJAutoProxy
public class LoggingAspectConfiguration {
@Bean
@Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
public LoggingAspect loggingAspect(Environment env) {
return new LoggingAspect(env);
}
}

View File

@ -1,160 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import ch.qos.logback.classic.AsyncAppender;
import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.boolex.OnMarkerEvaluator;
import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.classic.spi.LoggerContextListener;
import ch.qos.logback.core.Appender;
import ch.qos.logback.core.filter.EvaluatorFilter;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.spi.FilterReply;
import io.github.jhipster.config.JHipsterProperties;
import net.logstash.logback.appender.LogstashTcpSocketAppender;
import net.logstash.logback.encoder.LogstashEncoder;
import net.logstash.logback.stacktrace.ShortenedThrowableConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import java.net.InetSocketAddress;
import java.util.Iterator;
@Configuration
public class LoggingConfiguration {
private static final String LOGSTASH_APPENDER_NAME = "LOGSTASH";
private static final String ASYNC_LOGSTASH_APPENDER_NAME = "ASYNC_LOGSTASH";
private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
private final String appName;
private final String serverPort;
private final JHipsterProperties jHipsterProperties;
public LoggingConfiguration(
@Value("${spring.application.name}") String appName,
@Value("${server.port}") String serverPort,
JHipsterProperties jHipsterProperties) {
this.appName = appName;
this.serverPort = serverPort;
this.jHipsterProperties = jHipsterProperties;
if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
addLogstashAppender(context);
addContextListener(context);
}
if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
setMetricsMarkerLogbackFilter(context);
}
}
private void addContextListener(LoggerContext context) {
LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener();
loggerContextListener.setContext(context);
context.addListener(loggerContextListener);
}
private void addLogstashAppender(LoggerContext context) {
log.info("Initializing Logstash logging");
LogstashTcpSocketAppender logstashAppender = new LogstashTcpSocketAppender();
logstashAppender.setName(LOGSTASH_APPENDER_NAME);
logstashAppender.setContext(context);
String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"}";
// More documentation is available at: https://github.com/logstash/logstash-logback-encoder
LogstashEncoder logstashEncoder = new LogstashEncoder();
// Set the Logstash appender config from JHipster properties
logstashAppender.addDestinations(
new InetSocketAddress(
jHipsterProperties.getLogging().getLogstash().getHost(),
jHipsterProperties.getLogging().getLogstash().getPort()));
ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter();
throwableConverter.setRootCauseFirst(true);
logstashEncoder.setThrowableConverter(throwableConverter);
logstashEncoder.setCustomFields(customFields);
logstashAppender.setEncoder(logstashEncoder);
logstashAppender.start();
// Wrap the appender in an Async appender for performance
AsyncAppender asyncLogstashAppender = new AsyncAppender();
asyncLogstashAppender.setContext(context);
asyncLogstashAppender.setName(ASYNC_LOGSTASH_APPENDER_NAME);
asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
asyncLogstashAppender.addAppender(logstashAppender);
asyncLogstashAppender.start();
context.getLogger("ROOT").addAppender(asyncLogstashAppender);
}
// Configure a log filter to remove "metrics" logs from all appenders except the "LOGSTASH" appender
private void setMetricsMarkerLogbackFilter(LoggerContext context) {
log.info("Filtering metrics logs from all appenders except the {} appender", LOGSTASH_APPENDER_NAME);
OnMarkerEvaluator onMarkerMetricsEvaluator = new OnMarkerEvaluator();
onMarkerMetricsEvaluator.setContext(context);
onMarkerMetricsEvaluator.addMarker("metrics");
onMarkerMetricsEvaluator.start();
EvaluatorFilter<ILoggingEvent> metricsFilter = new EvaluatorFilter<>();
metricsFilter.setContext(context);
metricsFilter.setEvaluator(onMarkerMetricsEvaluator);
metricsFilter.setOnMatch(FilterReply.DENY);
metricsFilter.start();
for (ch.qos.logback.classic.Logger logger : context.getLoggerList()) {
for (Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders(); it.hasNext();) {
Appender<ILoggingEvent> appender = it.next();
if (!appender.getName().equals(ASYNC_LOGSTASH_APPENDER_NAME)) {
log.debug("Filter metrics logs from the {} appender", appender.getName());
appender.setContext(context);
appender.addFilter(metricsFilter);
appender.start();
}
}
}
}
/**
* Logback configuration is achieved by configuration file and API.
* When configuration file change is detected, the configuration is reset.
* This listener ensures that the programmatic configuration is also re-applied after reset.
*/
class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener {
@Override
public boolean isResetResistant() {
return true;
}
@Override
public void onStart(LoggerContext context) {
addLogstashAppender(context);
}
@Override
public void onReset(LoggerContext context) {
addLogstashAppender(context);
}
@Override
public void onStop(LoggerContext context) {
// Nothing to do.
}
@Override
public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) {
// Nothing to do.
}
}
}

View File

@ -1,128 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import org.hostsharing.hsadminng.security.*;
import org.hostsharing.hsadminng.security.jwt.*;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.filter.CorsFilter;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
import javax.annotation.PostConstruct;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private final AuthenticationManagerBuilder authenticationManagerBuilder;
private final UserDetailsService userDetailsService;
private final TokenProvider tokenProvider;
private final CorsFilter corsFilter;
private final SecurityProblemSupport problemSupport;
public SecurityConfiguration(
AuthenticationManagerBuilder authenticationManagerBuilder,
UserDetailsService userDetailsService,
TokenProvider tokenProvider,
CorsFilter corsFilter,
SecurityProblemSupport problemSupport) {
this.authenticationManagerBuilder = authenticationManagerBuilder;
this.userDetailsService = userDetailsService;
this.tokenProvider = tokenProvider;
this.corsFilter = corsFilter;
this.problemSupport = problemSupport;
}
@PostConstruct
public void init() {
try {
authenticationManagerBuilder
.userDetailsService(userDetailsService)
.passwordEncoder(passwordEncoder());
} catch (Exception e) {
throw new BeanInitializationException("Security configuration failed", e);
}
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring()
.antMatchers(HttpMethod.OPTIONS, "/**")
.antMatchers("/app/**/*.{js,html}")
.antMatchers("/i18n/**")
.antMatchers("/content/**")
.antMatchers("/h2-console/**")
.antMatchers("/swagger-ui/index.html")
.antMatchers("/test/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.csrf()
.disable()
.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.headers()
.frameOptions()
.disable()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/api/register").permitAll()
.antMatchers("/api/activate").permitAll()
.antMatchers("/api/authenticate").permitAll()
.antMatchers("/api/account/reset-password/init").permitAll()
.antMatchers("/api/account/reset-password/finish").permitAll()
.antMatchers("/api/**").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.and()
.apply(securityConfigurerAdapter());
// @formatter:on
}
private JWTConfigurer securityConfigurerAdapter() {
return new JWTConfigurer(tokenProvider);
}
}

View File

@ -1,172 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config;
import static java.net.URLDecoder.decode;
import io.github.jhipster.config.JHipsterConstants;
import io.github.jhipster.config.JHipsterProperties;
import io.github.jhipster.config.h2.H2ConfigurationHelper;
import io.github.jhipster.web.filter.CachingHttpHeadersFilter;
import io.undertow.UndertowOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
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.http.MediaType;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Paths;
import java.util.*;
import javax.servlet.*;
/**
* 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());
}
EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
initCachingHttpHeadersFilter(servletContext, disps);
}
if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
initH2Console(servletContext);
}
log.info("Web application fully configured");
}
/**
* Customize the Servlet engine: Mime types, the document root, the cache.
*/
@Override
public void customize(WebServerFactory server) {
setMimeMappings(server);
// When running in an IDE or with ./gradlew bootRun, set location of the static web assets.
setLocationForStaticAssets(server);
/*
* Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
* HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
* See the JHipsterProperties class and your application-*.yml configuration files
* for more information.
*/
if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) &&
server instanceof UndertowServletWebServerFactory) {
((UndertowServletWebServerFactory) server)
.addBuilderCustomizers(builder -> builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
}
}
private void setMimeMappings(WebServerFactory server) {
if (server instanceof ConfigurableServletWebServerFactory) {
MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
// IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
mappings.add("html", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase());
// CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
mappings.add("json", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase());
ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server;
servletWebServer.setMimeMappings(mappings);
}
}
private void setLocationForStaticAssets(WebServerFactory server) {
if (server instanceof ConfigurableServletWebServerFactory) {
ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server;
File root;
String prefixPath = resolvePathPrefix();
root = new File(prefixPath + "build/www/");
if (root.exists() && root.isDirectory()) {
servletWebServer.setDocumentRoot(root);
}
}
}
/**
* Resolve path prefix to static resources.
*/
private String resolvePathPrefix() {
String fullExecutablePath;
try {
fullExecutablePath = decode(this.getClass().getResource("").getPath(), StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
/* try without decoding if this ever happens */
fullExecutablePath = this.getClass().getResource("").getPath();
}
String rootPath = Paths.get(".").toUri().normalize().getPath();
String extractedPath = fullExecutablePath.replace(rootPath, "");
int extractionEndIndex = extractedPath.indexOf("build/");
if (extractionEndIndex <= 0) {
return "";
}
return extractedPath.substring(0, extractionEndIndex);
}
/**
* Initializes the caching HTTP Headers Filter.
*/
private void initCachingHttpHeadersFilter(
ServletContext servletContext,
EnumSet<DispatcherType> disps) {
log.debug("Registering Caching HTTP Headers Filter");
FilterRegistration.Dynamic cachingHttpHeadersFilter = servletContext.addFilter(
"cachingHttpHeadersFilter",
new CachingHttpHeadersFilter(jHipsterProperties));
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/i18n/*");
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*");
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*");
cachingHttpHeadersFilter.setAsyncSupported(true);
}
@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = jHipsterProperties.getCors();
if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
log.debug("Registering CORS filter");
source.registerCorsConfiguration("/api/**", config);
source.registerCorsConfiguration("/management/**", config);
source.registerCorsConfiguration("/v2/api-docs", config);
}
return new CorsFilter(source);
}
/**
* Initializes H2 console.
*/
private void initH2Console(ServletContext servletContext) {
log.debug("Initialize H2 console");
H2ConfigurationHelper.initH2Console(servletContext);
}
}

View File

@ -1,90 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.config.audit;
import org.hostsharing.hsadminng.domain.PersistentAuditEvent;
import org.springframework.boot.actuate.audit.AuditEvent;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;
import java.util.*;
@Component
public class AuditEventConverter {
/**
* Convert a list of PersistentAuditEvent to a list of AuditEvent
*
* @param persistentAuditEvents the list to convert
* @return the converted list.
*/
public List<AuditEvent> convertToAuditEvent(Iterable<PersistentAuditEvent> persistentAuditEvents) {
if (persistentAuditEvents == null) {
return Collections.emptyList();
}
List<AuditEvent> auditEvents = new ArrayList<>();
for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) {
auditEvents.add(convertToAuditEvent(persistentAuditEvent));
}
return auditEvents;
}
/**
* Convert a PersistentAuditEvent to an AuditEvent
*
* @param persistentAuditEvent the event to convert
* @return the converted list.
*/
public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) {
if (persistentAuditEvent == null) {
return null;
}
return new AuditEvent(
persistentAuditEvent.getAuditEventDate(),
persistentAuditEvent.getPrincipal(),
persistentAuditEvent.getAuditEventType(),
convertDataToObjects(persistentAuditEvent.getData()));
}
/**
* Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface
*
* @param data the data to convert
* @return a map of String, Object
*/
public Map<String, Object> convertDataToObjects(Map<String, String> data) {
Map<String, Object> results = new HashMap<>();
if (data != null) {
for (Map.Entry<String, String> entry : data.entrySet()) {
results.put(entry.getKey(), entry.getValue());
}
}
return results;
}
/**
* Internal conversion. This method will allow to save additional data.
* By default, it will save the object as string
*
* @param data the data to convert
* @return a map of String, String
*/
public Map<String, String> convertDataToStrings(Map<String, Object> data) {
Map<String, String> results = new HashMap<>();
if (data != null) {
for (Map.Entry<String, Object> entry : data.entrySet()) {
// Extract the data that will be saved.
if (entry.getValue() instanceof WebAuthenticationDetails) {
WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) entry.getValue();
results.put("remoteAddress", authenticationDetails.getRemoteAddress());
results.put("sessionId", authenticationDetails.getSessionId());
} else {
results.put(entry.getKey(), Objects.toString(entry.getValue()));
}
}
}
return results;
}
}

View File

@ -1,4 +0,0 @@
/**
* Audit specific code.
*/
package org.hostsharing.hsadminng.config.audit;

View File

@ -1,4 +0,0 @@
/**
* Spring Framework configuration files.
*/
package org.hostsharing.hsadminng.config;

View File

@ -1,82 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.hibernate.envers.Audited;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.io.Serializable;
import java.time.Instant;
import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
/**
* Base abstract class for entities which will hold definitions for created, last modified by and created,
* last modified by date.
*/
@MappedSuperclass
@Audited
@EntityListeners(AuditingEntityListener.class)
public abstract class AbstractAuditingEntity implements Serializable {
private static final long serialVersionUID = 1L;
@CreatedBy
@Column(name = "created_by", nullable = false, length = 50, updatable = false)
@JsonIgnore
private String createdBy;
@CreatedDate
@Column(name = "created_date", updatable = false)
@JsonIgnore
private Instant createdDate = Instant.now();
@LastModifiedBy
@Column(name = "last_modified_by", length = 50)
@JsonIgnore
private String lastModifiedBy;
@LastModifiedDate
@Column(name = "last_modified_date")
@JsonIgnore
private Instant lastModifiedDate = Instant.now();
public String getCreatedBy() {
return createdBy;
}
public void setCreatedBy(String createdBy) {
this.createdBy = createdBy;
}
public Instant getCreatedDate() {
return createdDate;
}
public void setCreatedDate(Instant createdDate) {
this.createdDate = createdDate;
}
public String getLastModifiedBy() {
return lastModifiedBy;
}
public void setLastModifiedBy(String lastModifiedBy) {
this.lastModifiedBy = lastModifiedBy;
}
public Instant getLastModifiedDate() {
return lastModifiedDate;
}
public void setLastModifiedDate(Instant lastModifiedDate) {
this.lastModifiedDate = lastModifiedDate;
}
}

View File

@ -1,184 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import org.hostsharing.hsadminng.domain.enumeration.AssetAction;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* A Asset.
*/
@Entity
@Table(name = "asset")
public class Asset implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_NAME = "asset";
public static final String ENTITY_TYPE_ID = "customer.asset";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Column(name = "document_date", nullable = false)
private LocalDate documentDate;
@NotNull
@Column(name = "value_date", nullable = false)
private LocalDate valueDate;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "action", nullable = false)
private AssetAction action;
@NotNull
@Column(name = "amount", precision = 10, scale = 2, nullable = false)
private BigDecimal amount;
@Size(max = 160)
@Column(name = "remark", length = 160)
private String remark;
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("assets")
private Membership membership;
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public Asset id(Long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public LocalDate getDocumentDate() {
return documentDate;
}
public Asset documentDate(LocalDate documentDate) {
this.documentDate = documentDate;
return this;
}
public void setDocumentDate(LocalDate documentDate) {
this.documentDate = documentDate;
}
public LocalDate getValueDate() {
return valueDate;
}
public Asset valueDate(LocalDate valueDate) {
this.valueDate = valueDate;
return this;
}
public void setValueDate(LocalDate valueDate) {
this.valueDate = valueDate;
}
public AssetAction getAction() {
return action;
}
public Asset action(AssetAction action) {
this.action = action;
return this;
}
public void setAction(AssetAction action) {
this.action = action;
}
public BigDecimal getAmount() {
return amount;
}
public Asset amount(BigDecimal amount) {
this.amount = amount;
return this;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getRemark() {
return remark;
}
public Asset remark(String remark) {
this.remark = remark;
return this;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Membership getMembership() {
return membership;
}
public Asset membership(Membership membership) {
this.membership = membership;
return this;
}
public void setMembership(Membership membership) {
this.membership = membership;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Asset asset = (Asset) o;
if (asset.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), asset.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Asset{" +
"id=" + getId() +
", documentDate='" + getDocumentDate() + "'" +
", valueDate='" + getValueDate() + "'" +
", action='" + getAction() + "'" +
", amount=" + getAmount() +
", remark='" + getRemark() + "'" +
"}";
}
}

View File

@ -1,61 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* An authority (a security role) used by Spring Security.
*/
@Entity
@Table(name = "jhi_authority")
public class Authority implements Serializable {
private static final long serialVersionUID = 1L;
@NotNull
@Size(max = 50)
@Id
@Column(length = 50)
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Authority authority = (Authority) o;
return !(name != null ? !name.equals(authority.name) : authority.name != null);
}
@Override
public int hashCode() {
return name != null ? name.hashCode() : 0;
}
@Override
public String toString() {
return "Authority{" +
"name='" + name + '\'' +
"}";
}
}

View File

@ -1,408 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import org.hostsharing.hsadminng.domain.enumeration.CustomerKind;
import org.hostsharing.hsadminng.domain.enumeration.VatRegion;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.*;
/**
* A Customer.
*/
@Entity
@Table(name = "customer")
public class Customer implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_TYPE_ID = "customer.Customer";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Min(value = 10000)
@Max(value = 99999)
@Column(name = "reference", nullable = false, unique = true)
private Integer reference;
@NotNull
@Size(max = 3)
@Pattern(regexp = "[a-z][a-z0-9]+")
@Column(name = "prefix", length = 3, nullable = false, unique = true)
private String prefix;
@NotNull
@Size(max = 80)
@Column(name = "name", length = 80, nullable = false)
private String name;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "kind", nullable = false)
private CustomerKind kind;
@Column(name = "birth_date")
private LocalDate birthDate;
@Size(max = 80)
@Column(name = "birth_place", length = 80)
private String birthPlace;
@Size(max = 80)
@Column(name = "registration_court", length = 80)
private String registrationCourt;
@Size(max = 80)
@Column(name = "registration_number", length = 80)
private String registrationNumber;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "vat_region", nullable = false)
private VatRegion vatRegion;
@Size(max = 40)
@Column(name = "vat_number", length = 40)
private String vatNumber;
@Size(max = 80)
@Column(name = "contractual_salutation", length = 80)
private String contractualSalutation;
@NotNull
@Size(max = 400)
@Column(name = "contractual_address", length = 400, nullable = false)
private String contractualAddress;
@Size(max = 80)
@Column(name = "billing_salutation", length = 80)
private String billingSalutation;
@Size(max = 400)
@Column(name = "billing_address", length = 400)
private String billingAddress;
@Size(max = 160)
@Column(name = "remark", length = 160)
private String remark;
@OneToMany(mappedBy = "customer")
private Set<Membership> memberships = new HashSet<>();
@OneToMany(mappedBy = "customer")
private Set<SepaMandate> sepamandates = new HashSet<>();
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public Customer id(long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public Integer getReference() {
return reference;
}
public Customer reference(Integer reference) {
this.reference = reference;
return this;
}
public void setReference(Integer reference) {
this.reference = reference;
}
public String getPrefix() {
return prefix;
}
public Customer prefix(String prefix) {
this.prefix = prefix;
return this;
}
public void setPrefix(String prefix) {
this.prefix = prefix;
}
public String getName() {
return name;
}
public Customer name(String name) {
this.name = name;
return this;
}
public void setName(String name) {
this.name = name;
}
public CustomerKind getKind() {
return kind;
}
public Customer kind(CustomerKind kind) {
this.kind = kind;
return this;
}
public void setKind(CustomerKind kind) {
this.kind = kind;
}
public LocalDate getBirthDate() {
return birthDate;
}
public Customer birthDate(LocalDate birthDate) {
this.birthDate = birthDate;
return this;
}
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
public String getBirthPlace() {
return birthPlace;
}
public Customer birthPlace(String birthPlace) {
this.birthPlace = birthPlace;
return this;
}
public void setBirthPlace(String birthPlace) {
this.birthPlace = birthPlace;
}
public String getRegistrationCourt() {
return registrationCourt;
}
public Customer registrationCourt(String registrationCourt) {
this.registrationCourt = registrationCourt;
return this;
}
public void setRegistrationCourt(String registrationCourt) {
this.registrationCourt = registrationCourt;
}
public String getRegistrationNumber() {
return registrationNumber;
}
public Customer registrationNumber(String registrationNumber) {
this.registrationNumber = registrationNumber;
return this;
}
public void setRegistrationNumber(String registrationNumber) {
this.registrationNumber = registrationNumber;
}
public VatRegion getVatRegion() {
return vatRegion;
}
public Customer vatRegion(VatRegion vatRegion) {
this.vatRegion = vatRegion;
return this;
}
public void setVatRegion(VatRegion vatRegion) {
this.vatRegion = vatRegion;
}
public String getVatNumber() {
return vatNumber;
}
public Customer vatNumber(String vatNumber) {
this.vatNumber = vatNumber;
return this;
}
public void setVatNumber(String vatNumber) {
this.vatNumber = vatNumber;
}
public String getContractualSalutation() {
return contractualSalutation;
}
public Customer contractualSalutation(String contractualSalutation) {
this.contractualSalutation = contractualSalutation;
return this;
}
public void setContractualSalutation(String contractualSalutation) {
this.contractualSalutation = contractualSalutation;
}
public String getContractualAddress() {
return contractualAddress;
}
public Customer contractualAddress(String contractualAddress) {
this.contractualAddress = contractualAddress;
return this;
}
public void setContractualAddress(String contractualAddress) {
this.contractualAddress = contractualAddress;
}
public String getBillingSalutation() {
return billingSalutation;
}
public Customer billingSalutation(String billingSalutation) {
this.billingSalutation = billingSalutation;
return this;
}
public void setBillingSalutation(String billingSalutation) {
this.billingSalutation = billingSalutation;
}
public String getBillingAddress() {
return billingAddress;
}
public Customer billingAddress(String billingAddress) {
this.billingAddress = billingAddress;
return this;
}
public void setBillingAddress(String billingAddress) {
this.billingAddress = billingAddress;
}
public String getRemark() {
return remark;
}
public Customer remark(String remark) {
this.remark = remark;
return this;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Set<Membership> getMemberships() {
return memberships;
}
public Customer memberships(Set<Membership> memberships) {
this.memberships = memberships;
return this;
}
public Customer addMembership(Membership membership) {
this.memberships.add(membership);
membership.setCustomer(this);
return this;
}
public Customer removeMembership(Membership membership) {
this.memberships.remove(membership);
membership.setCustomer(null);
return this;
}
public void setMemberships(Set<Membership> memberships) {
this.memberships = memberships;
}
public Set<SepaMandate> getSepamandates() {
return sepamandates;
}
public Customer sepamandates(Set<SepaMandate> sepaMandates) {
this.sepamandates = sepaMandates;
return this;
}
public Customer addSepamandate(SepaMandate sepaMandate) {
this.sepamandates.add(sepaMandate);
sepaMandate.setCustomer(this);
return this;
}
public Customer removeSepamandate(SepaMandate sepaMandate) {
this.sepamandates.remove(sepaMandate);
sepaMandate.setCustomer(null);
return this;
}
public void setSepamandates(Set<SepaMandate> sepaMandates) {
this.sepamandates = sepaMandates;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Customer customer = (Customer) o;
if (customer.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), customer.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Customer{" +
"id=" + getId() +
", reference=" + getReference() +
", prefix='" + getPrefix() + "'" +
", name='" + getName() + "'" +
", kind='" + getKind() + "'" +
", birthDate='" + getBirthDate() + "'" +
", birthPlace='" + getBirthPlace() + "'" +
", registrationCourt='" + getRegistrationCourt() + "'" +
", registrationNumber='" + getRegistrationNumber() + "'" +
", vatRegion='" + getVatRegion() + "'" +
", vatNumber='" + getVatNumber() + "'" +
", contractualSalutation='" + getContractualSalutation() + "'" +
", contractualAddress='" + getContractualAddress() + "'" +
", billingSalutation='" + getBillingSalutation() + "'" +
", billingAddress='" + getBillingAddress() + "'" +
", remark='" + getRemark() + "'" +
"}";
}
}

View File

@ -1,238 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* A Membership.
*/
@Entity
@Table(name = "membership")
public class Membership implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_NAME = "membership";
public static final String ENTITY_TYPE_ID = "customer.Membership";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Column(name = "admission_document_date", nullable = false)
private LocalDate admissionDocumentDate;
@Column(name = "cancellation_document_date")
private LocalDate cancellationDocumentDate;
@NotNull
@Column(name = "member_from_date", nullable = false)
private LocalDate memberFromDate;
@Column(name = "member_until_date")
private LocalDate memberUntilDate;
@Size(max = 160)
@Column(name = "remark", length = 160)
private String remark;
@OneToMany(mappedBy = "membership")
private Set<Share> shares = new HashSet<>();
@OneToMany(mappedBy = "membership")
private Set<Asset> assets = new HashSet<>();
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("memberships")
private Customer customer;
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public Membership id(Long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public LocalDate getAdmissionDocumentDate() {
return admissionDocumentDate;
}
public Membership admissionDocumentDate(LocalDate admissionDocumentDate) {
this.admissionDocumentDate = admissionDocumentDate;
return this;
}
public void setAdmissionDocumentDate(LocalDate admissionDocumentDate) {
this.admissionDocumentDate = admissionDocumentDate;
}
public LocalDate getCancellationDocumentDate() {
return cancellationDocumentDate;
}
public Membership cancellationDocumentDate(LocalDate cancellationDocumentDate) {
this.cancellationDocumentDate = cancellationDocumentDate;
return this;
}
public void setCancellationDocumentDate(LocalDate cancellationDocumentDate) {
this.cancellationDocumentDate = cancellationDocumentDate;
}
public LocalDate getMemberFromDate() {
return memberFromDate;
}
public Membership memberFromDate(LocalDate memberFromDate) {
this.memberFromDate = memberFromDate;
return this;
}
public void setMemberFromDate(LocalDate memberFromDate) {
this.memberFromDate = memberFromDate;
}
public LocalDate getMemberUntilDate() {
return memberUntilDate;
}
public Membership memberUntilDate(LocalDate memberUntilDate) {
this.memberUntilDate = memberUntilDate;
return this;
}
public void setMemberUntilDate(LocalDate memberUntilDate) {
this.memberUntilDate = memberUntilDate;
}
public String getRemark() {
return remark;
}
public Membership remark(String remark) {
this.remark = remark;
return this;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Set<Share> getShares() {
return shares;
}
public Membership shares(Set<Share> shares) {
this.shares = shares;
return this;
}
public Membership addShare(Share share) {
this.shares.add(share);
share.setMembership(this);
return this;
}
public Membership removeShare(Share share) {
this.shares.remove(share);
share.setMembership(null);
return this;
}
public void setShares(Set<Share> shares) {
this.shares = shares;
}
public Set<Asset> getAssets() {
return assets;
}
public Membership assets(Set<Asset> assets) {
this.assets = assets;
return this;
}
public Membership addAsset(Asset asset) {
this.assets.add(asset);
asset.setMembership(this);
return this;
}
public Membership removeAsset(Asset asset) {
this.assets.remove(asset);
asset.setMembership(null);
return this;
}
public void setAssets(Set<Asset> assets) {
this.assets = assets;
}
public Customer getCustomer() {
return customer;
}
public Membership customer(Customer customer) {
this.customer = customer;
return this;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Membership membership = (Membership) o;
if (membership.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), membership.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Membership{" +
"id=" + getId() +
", admissionDocumentDate='" + getAdmissionDocumentDate() + "'" +
", cancellationDocumentDate='" + getCancellationDocumentDate() + "'" +
", memberFromDate='" + getMemberFromDate() + "'" +
", memberUntilDate='" + getMemberUntilDate() + "'" +
", remark='" + getRemark() + "'" +
"}";
}
}

View File

@ -1,113 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import java.io.Serializable;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
/**
* Persist AuditEvent managed by the Spring Boot actuator.
*
* @see org.springframework.boot.actuate.audit.AuditEvent
*/
@Entity
@Table(name = "jhi_persistent_audit_event")
public class PersistentAuditEvent implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@Column(name = "event_id")
private Long id;
@NotNull
@Column(nullable = false)
private String principal;
@Column(name = "event_date")
private Instant auditEventDate;
@Column(name = "event_type")
private String auditEventType;
@ElementCollection
@MapKeyColumn(name = "name")
@Column(name = "value")
@CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns = @JoinColumn(name = "event_id"))
private Map<String, String> data = new HashMap<>();
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getPrincipal() {
return principal;
}
public void setPrincipal(String principal) {
this.principal = principal;
}
public Instant getAuditEventDate() {
return auditEventDate;
}
public void setAuditEventDate(Instant auditEventDate) {
this.auditEventDate = auditEventDate;
}
public String getAuditEventType() {
return auditEventType;
}
public void setAuditEventType(String auditEventType) {
this.auditEventType = auditEventType;
}
public Map<String, String> getData() {
return data;
}
public void setData(Map<String, String> data) {
this.data = data;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
PersistentAuditEvent persistentAuditEvent = (PersistentAuditEvent) o;
return !(persistentAuditEvent.getId() == null || getId() == null)
&& Objects.equals(getId(), persistentAuditEvent.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "PersistentAuditEvent{" +
"principal='" + principal + '\'' +
", auditEventDate=" + auditEventDate +
", auditEventType='" + auditEventType + '\'' +
'}';
}
}

View File

@ -1,250 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* A SepaMandate.
*/
@Entity
@Table(name = "sepa_mandate")
public class SepaMandate implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_TYPE_ID = "customer.SepaMandate";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Size(max = 40)
@Column(name = "reference", length = 40, nullable = false, unique = true)
private String reference;
@Size(max = 34)
@Column(name = "iban", length = 34)
private String iban;
@Size(max = 11)
@Column(name = "bic", length = 11)
private String bic;
@NotNull
@Column(name = "granting_document_date", nullable = false)
private LocalDate grantingDocumentDate;
@Column(name = "revokation_document_date")
private LocalDate revokationDocumentDate;
@NotNull
@Column(name = "valid_from_date", nullable = false)
private LocalDate validFromDate;
@Column(name = "valid_until_date")
private LocalDate validUntilDate;
@Column(name = "last_used_date")
private LocalDate lastUsedDate;
@Size(max = 160)
@Column(name = "remark", length = 160)
private String remark;
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("sepamandates")
private Customer customer;
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public SepaMandate id(final Long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public String getReference() {
return reference;
}
public SepaMandate reference(String reference) {
this.reference = reference;
return this;
}
public void setReference(String reference) {
this.reference = reference;
}
public String getIban() {
return iban;
}
public SepaMandate iban(String iban) {
this.iban = iban;
return this;
}
public void setIban(String iban) {
this.iban = iban;
}
public String getBic() {
return bic;
}
public SepaMandate bic(String bic) {
this.bic = bic;
return this;
}
public void setBic(String bic) {
this.bic = bic;
}
public LocalDate getGrantingDocumentDate() {
return grantingDocumentDate;
}
public SepaMandate grantingDocumentDate(LocalDate grantingDocumentDate) {
this.grantingDocumentDate = grantingDocumentDate;
return this;
}
public void setGrantingDocumentDate(LocalDate grantingDocumentDate) {
this.grantingDocumentDate = grantingDocumentDate;
}
public LocalDate getRevokationDocumentDate() {
return revokationDocumentDate;
}
public SepaMandate revokationDocumentDate(LocalDate revokationDocumentDate) {
this.revokationDocumentDate = revokationDocumentDate;
return this;
}
public void setRevokationDocumentDate(LocalDate revokationDocumentDate) {
this.revokationDocumentDate = revokationDocumentDate;
}
public LocalDate getValidFromDate() {
return validFromDate;
}
public SepaMandate validFromDate(LocalDate validFromDate) {
this.validFromDate = validFromDate;
return this;
}
public void setValidFromDate(LocalDate validFromDate) {
this.validFromDate = validFromDate;
}
public LocalDate getValidUntilDate() {
return validUntilDate;
}
public SepaMandate validUntilDate(LocalDate validUntilDate) {
this.validUntilDate = validUntilDate;
return this;
}
public void setValidUntilDate(LocalDate validUntilDate) {
this.validUntilDate = validUntilDate;
}
public LocalDate getLastUsedDate() {
return lastUsedDate;
}
public SepaMandate lastUsedDate(LocalDate lastUsedDate) {
this.lastUsedDate = lastUsedDate;
return this;
}
public void setLastUsedDate(LocalDate lastUsedDate) {
this.lastUsedDate = lastUsedDate;
}
public String getRemark() {
return remark;
}
public SepaMandate remark(String remark) {
this.remark = remark;
return this;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Customer getCustomer() {
return customer;
}
public SepaMandate customer(Customer customer) {
this.customer = customer;
return this;
}
public void setCustomer(Customer customer) {
this.customer = customer;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
SepaMandate sepaMandate = (SepaMandate) o;
if (sepaMandate.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), sepaMandate.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "SepaMandate{" +
"id=" + getId() +
", reference='" + getReference() + "'" +
", iban='" + getIban() + "'" +
", bic='" + getBic() + "'" +
", grantingDocumentDate='" + getGrantingDocumentDate() + "'" +
", revokationDocumentDate='" + getRevokationDocumentDate() + "'" +
", validFromDate='" + getValidFromDate() + "'" +
", validUntilDate='" + getValidUntilDate() + "'" +
", lastUsedDate='" + getLastUsedDate() + "'" +
", remark='" + getRemark() + "'" +
"}";
}
}

View File

@ -1,183 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import org.hostsharing.hsadminng.domain.enumeration.ShareAction;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* A Share.
*/
@Entity
@Table(name = "share")
public class Share implements Serializable {
private static final long serialVersionUID = 1L;
public static final String ENTITY_NAME = "share";
public static final String ENTITY_TYPE_ID = "customer.share";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Column(name = "document_date", nullable = false)
private LocalDate documentDate;
@NotNull
@Column(name = "value_date", nullable = false)
private LocalDate valueDate;
@NotNull
@Enumerated(EnumType.STRING)
@Column(name = "action", nullable = false)
private ShareAction action;
@NotNull
@Column(name = "quantity", nullable = false)
private Integer quantity;
@Size(max = 160)
@Column(name = "remark", length = 160)
private String remark;
@ManyToOne(optional = false)
@NotNull
@JsonIgnoreProperties("shares")
private Membership membership;
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public Share id(final Long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public LocalDate getDocumentDate() {
return documentDate;
}
public Share documentDate(LocalDate documentDate) {
this.documentDate = documentDate;
return this;
}
public void setDocumentDate(LocalDate documentDate) {
this.documentDate = documentDate;
}
public LocalDate getValueDate() {
return valueDate;
}
public Share valueDate(LocalDate valueDate) {
this.valueDate = valueDate;
return this;
}
public void setValueDate(LocalDate valueDate) {
this.valueDate = valueDate;
}
public ShareAction getAction() {
return action;
}
public Share action(ShareAction action) {
this.action = action;
return this;
}
public void setAction(ShareAction action) {
this.action = action;
}
public Integer getQuantity() {
return quantity;
}
public Share quantity(Integer quantity) {
this.quantity = quantity;
return this;
}
public void setQuantity(Integer quantity) {
this.quantity = quantity;
}
public String getRemark() {
return remark;
}
public Share remark(String remark) {
this.remark = remark;
return this;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Membership getMembership() {
return membership;
}
public Share membership(Membership membership) {
this.membership = membership;
return this;
}
public void setMembership(Membership membership) {
this.membership = membership;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Share share = (Share) o;
if (share.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), share.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "Share{" +
"id=" + getId() +
", documentDate='" + getDocumentDate() + "'" +
", valueDate='" + getValueDate() + "'" +
", action='" + getAction() + "'" +
", quantity=" + getQuantity() +
", remark='" + getRemark() + "'" +
"}";
}
}

View File

@ -1,240 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import org.hostsharing.hsadminng.config.Constants;
import org.hostsharing.hsadminng.service.dto.FluentBuilder;
import com.fasterxml.jackson.annotation.JsonIgnore;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.annotations.BatchSize;
import java.io.Serializable;
import java.time.Instant;
import java.util.HashSet;
import java.util.Locale;
import java.util.Objects;
import java.util.Set;
import javax.persistence.*;
import javax.validation.constraints.Email;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
/**
* A user.
*/
@Entity
@Table(name = "jhi_user")
public class User extends AbstractAuditingEntity implements FluentBuilder<User>, Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
private Long id;
@NotNull
@Pattern(regexp = Constants.LOGIN_REGEX)
@Size(min = 1, max = 50)
@Column(length = 50, unique = true, nullable = false)
private String login;
@JsonIgnore
@NotNull
@Size(min = 60, max = 60)
@Column(name = "password_hash", length = 60, nullable = false)
private String password;
@Size(max = 50)
@Column(name = "first_name", length = 50)
private String firstName;
@Size(max = 50)
@Column(name = "last_name", length = 50)
private String lastName;
@Email
@Size(min = 5, max = 254)
@Column(length = 254, unique = true)
private String email;
@NotNull
@Column(nullable = false)
private boolean activated = false;
@Size(min = 2, max = 6)
@Column(name = "lang_key", length = 6)
private String langKey;
@Size(max = 256)
@Column(name = "image_url", length = 256)
private String imageUrl;
@Size(max = 20)
@Column(name = "activation_key", length = 20)
@JsonIgnore
private String activationKey;
@Size(max = 20)
@Column(name = "reset_key", length = 20)
@JsonIgnore
private String resetKey;
@Column(name = "reset_date")
private Instant resetDate = null;
@JsonIgnore
@ManyToMany
@JoinTable(
name = "jhi_user_authority",
joinColumns = { @JoinColumn(name = "user_id", referencedColumnName = "id") },
inverseJoinColumns = { @JoinColumn(name = "authority_name", referencedColumnName = "name") })
@BatchSize(size = 20)
private Set<Authority> authorities = new HashSet<>();
public Long getId() {
return id;
}
public User id(final long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public String getLogin() {
return login;
}
// Lowercase the login before saving it in database
public void setLogin(String login) {
this.login = StringUtils.lowerCase(login, Locale.ENGLISH);
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getImageUrl() {
return imageUrl;
}
public void setImageUrl(String imageUrl) {
this.imageUrl = imageUrl;
}
public boolean getActivated() {
return activated;
}
public void setActivated(boolean activated) {
this.activated = activated;
}
public String getActivationKey() {
return activationKey;
}
public void setActivationKey(String activationKey) {
this.activationKey = activationKey;
}
public String getResetKey() {
return resetKey;
}
public void setResetKey(String resetKey) {
this.resetKey = resetKey;
}
public Instant getResetDate() {
return resetDate;
}
public void setResetDate(Instant resetDate) {
this.resetDate = resetDate;
}
public String getLangKey() {
return langKey;
}
public void setLangKey(String langKey) {
this.langKey = langKey;
}
public Set<Authority> getAuthorities() {
return authorities;
}
public void setAuthorities(Set<Authority> authorities) {
this.authorities = authorities;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
User user = (User) o;
return !(user.getId() == null || getId() == null) && Objects.equals(getId(), user.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "User{" +
"login='" + login + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", email='" + email + '\'' +
", imageUrl='" + imageUrl + '\'' +
", activated='" + activated + '\'' +
", langKey='" + langKey + '\'' +
", activationKey='" + activationKey + '\'' +
"}";
}
}

View File

@ -1,214 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain;
import static org.hostsharing.hsadminng.service.util.ReflectionUtil.of;
import org.hostsharing.hsadminng.repository.UserRepository;
import org.hostsharing.hsadminng.service.UserRoleAssignmentService;
import org.hostsharing.hsadminng.service.accessfilter.*;
import org.hostsharing.hsadminng.service.accessfilter.Role.Admin;
import org.hostsharing.hsadminng.service.accessfilter.Role.Supporter;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.TreeNode;
import org.springframework.boot.jackson.JsonComponent;
import org.springframework.context.ApplicationContext;
import java.lang.reflect.Field;
import java.util.Objects;
import javax.persistence.*;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;
/**
* A UserRoleAssignment.
*/
@Entity
@Table(name = "user_role_assignment")
@EntityTypeId(UserRoleAssignment.ENTITY_TYPE_ID)
@JsonAutoDetect(
fieldVisibility = JsonAutoDetect.Visibility.ANY,
getterVisibility = JsonAutoDetect.Visibility.NONE,
setterVisibility = JsonAutoDetect.Visibility.NONE)
public class UserRoleAssignment implements AccessMappings {
private static final long serialVersionUID = 1L;
private static final String USER_FIELD_NAME = "user";
public static final String ENTITY_TYPE_ID = "rights.UserRoleAssignment";
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
@SequenceGenerator(name = "sequenceGenerator")
@SelfId(resolver = UserRoleAssignmentService.class)
@AccessFor(read = Supporter.class)
private Long id;
@NotNull
@Size(max = 32)
@Column(name = "entity_type_id", length = 32, nullable = false)
@AccessFor(init = Admin.class, update = Admin.class, read = Supporter.class)
private String entityTypeId;
@NotNull
@Column(name = "entity_object_id", nullable = false)
@AccessFor(init = Admin.class, update = Admin.class, read = Supporter.class)
private Long entityObjectId;
@NotNull
@Column(name = "assigned_role", nullable = false)
@AccessFor(init = Admin.class, update = Admin.class, read = Supporter.class)
private String assignedRole;
@ManyToOne
@JsonIgnoreProperties("requireds")
@AccessFor(init = Admin.class, update = Admin.class, read = Supporter.class)
private User user;
// jhipster-needle-entity-add-field - JHipster will add fields here, do not remove
public Long getId() {
return id;
}
public UserRoleAssignment id(final long id) {
this.id = id;
return this;
}
public void setId(Long id) {
this.id = id;
}
public String getEntityTypeId() {
return entityTypeId;
}
public UserRoleAssignment entityTypeId(String entityTypeId) {
this.entityTypeId = entityTypeId;
return this;
}
public void setEntityTypeId(String entityTypeId) {
this.entityTypeId = entityTypeId;
}
public Long getEntityObjectId() {
return entityObjectId;
}
public UserRoleAssignment entityObjectId(Long entityObjectId) {
this.entityObjectId = entityObjectId;
return this;
}
public void setEntityObjectId(Long entityObjectId) {
this.entityObjectId = entityObjectId;
}
public Role getAssignedRole() {
return assignedRole != null ? Role.of(assignedRole) : null;
}
public UserRoleAssignment assignedRole(Role assignedRole) {
this.assignedRole = of(assignedRole, Role::name);
return this;
}
public void setAssignedRole(Role assignedRole) {
this.assignedRole = of(assignedRole, Role::name);
}
public User getUser() {
return user;
}
public UserRoleAssignment user(User user) {
this.user = user;
return this;
}
public void setUser(User user) {
this.user = user;
}
// jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
UserRoleAssignment userRoleAssignment = (UserRoleAssignment) o;
if (userRoleAssignment.getId() == null || getId() == null) {
return false;
}
return Objects.equals(getId(), userRoleAssignment.getId());
}
@Override
public int hashCode() {
return Objects.hashCode(getId());
}
@Override
public String toString() {
return "UserRoleAssignment{" +
"id=" + getId() +
", entityTypeId='" + entityTypeId + "'" +
", entityObjectId=" + entityObjectId +
", assignedRole='" + assignedRole + "'" +
"}";
}
@JsonComponent
public static class UserRoleAssignmentJsonSerializer extends JsonSerializerWithAccessFilter<UserRoleAssignment> {
public UserRoleAssignmentJsonSerializer(
final ApplicationContext ctx,
final UserRoleAssignmentService userRoleAssignmentService) {
super(ctx, userRoleAssignmentService);
}
@Override
protected JSonFieldWriter<UserRoleAssignment> jsonFieldWriter(final Field field) {
if (USER_FIELD_NAME.equals(field.getName())) {
return (final UserRoleAssignment dto, final JsonGenerator jsonGenerator) -> jsonGenerator
.writeNumberField(USER_FIELD_NAME, dto.getUser().getId());
}
return super.jsonFieldWriter(field);
}
}
@JsonComponent
public static class UserRoleAssignmentJsonDeserializer extends JsonDeserializerWithAccessFilter<UserRoleAssignment> {
private final UserRepository userRepository;
public UserRoleAssignmentJsonDeserializer(
final UserRepository userRepository,
final ApplicationContext ctx,
final UserRoleAssignmentService userRoleAssignmentService) {
super(ctx, userRoleAssignmentService);
this.userRepository = userRepository;
}
@Override
protected JSonFieldReader<UserRoleAssignment> jsonFieldReader(final TreeNode treeNode, final Field field) {
if ("user".equals(field.getName())) {
return (final UserRoleAssignment target) -> target
.setUser(userRepository.getOne(getSubNode(treeNode, "id").asLong()));
}
return super.jsonFieldReader(treeNode, field);
}
}
}

View File

@ -1,14 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain.enumeration;
/**
* The AssetAction enumeration.
*/
public enum AssetAction {
PAYMENT,
HANDOVER,
ADOPTION,
LOSS,
CLEARING,
PAYBACK
}

View File

@ -1,10 +0,0 @@
// Licensed under Apache-2.0
package org.hostsharing.hsadminng.domain.enumeration;
/**
* The CustomerKind enumeration.
*/
public enum CustomerKind {
NATURAL,
LEGAL
}

Some files were not shown because too many files have changed in this diff Show More