automatic project update
This commit is contained in:
parent
231b2d9297
commit
ed41ad9816
|
@ -0,0 +1,6 @@
|
|||
# more info here - http://eslint.org/docs/user-guide/configuring.html#ignoring-files-and-directories
|
||||
|
||||
# node_modules ignored by default
|
||||
|
||||
# ignore bower_components
|
||||
src/main/webapp/bower_components
|
|
@ -0,0 +1,29 @@
|
|||
// See: http://eslint.org/
|
||||
// See: https://www.npmjs.com/package/eslint-plugin-angular
|
||||
{
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"angular"
|
||||
],
|
||||
"env": {
|
||||
"node": true,
|
||||
"browser": true
|
||||
},
|
||||
// severity for a rule should be one of the following: 0 = off, 1 = warning, 2 = error
|
||||
"rules": {
|
||||
// coding style
|
||||
"wrap-iife": [2, "inside"],
|
||||
"eqeqeq": 2,
|
||||
"no-use-before-define": [2, "nofunc"],
|
||||
"no-unused-vars": [2, {"vars": "local", "args": "none"}],
|
||||
"no-multi-str": 2,
|
||||
"no-irregular-whitespace": 2,
|
||||
"semi": [2, "always"],
|
||||
"indent": 2,
|
||||
|
||||
// os/git options
|
||||
// we want to run on all OSes
|
||||
"linebreak-style": 0,
|
||||
"eol-last": 2
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
######################
|
||||
# Project Specific
|
||||
######################
|
||||
/src/main/webapp/dist
|
||||
/target/www/**
|
||||
|
||||
######################
|
||||
# Node
|
||||
|
@ -126,3 +126,8 @@ Desktop.ini
|
|||
# Maven Wrapper
|
||||
######################
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
|
||||
######################
|
||||
# ESLint
|
||||
######################
|
||||
.eslintcache
|
||||
|
|
|
@ -1 +1 @@
|
|||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.3/apache-maven-3.3.3-bin.zip
|
||||
distributionUrl=https://repo1.maven.org/maven2/org/apache/maven/apache-maven/3.3.9/apache-maven-3.3.9-bin.zip
|
||||
|
|
|
@ -2,9 +2,9 @@ language: node_js
|
|||
node_js:
|
||||
- "0.12"
|
||||
sudo: false
|
||||
before_install: npm install -g grunt-cli
|
||||
before_install: npm install -g gulp
|
||||
install: npm install
|
||||
before_script: grunt build
|
||||
before_script: gulp build
|
||||
notifications:
|
||||
webhooks:
|
||||
on_success: change # options: [always|never|change] default: always
|
||||
|
|
15
.yo-rc.json
15
.yo-rc.json
|
@ -12,15 +12,20 @@
|
|||
"prodDatabaseType": "mysql",
|
||||
"useCompass": false,
|
||||
"buildTool": "maven",
|
||||
"frontendBuilder": "grunt",
|
||||
"javaVersion": "8",
|
||||
"rememberMeKey": "5c37379956bd1242f5636c8cb322c2966ad81277",
|
||||
"searchEngine": "no",
|
||||
"enableTranslation": true,
|
||||
"useSass": false,
|
||||
"applicationType": "monolith",
|
||||
"testFrameworks": [
|
||||
"gatling"
|
||||
"gatling",
|
||||
"protractor"
|
||||
],
|
||||
"enableSocialSignIn": false
|
||||
"languages": [
|
||||
"en"
|
||||
],
|
||||
"serverPort": 8080,
|
||||
"jhipsterVersion": "3.0.0",
|
||||
"enableSocialSignIn": false,
|
||||
"useSass": false
|
||||
}
|
||||
}
|
362
Gruntfile.js
362
Gruntfile.js
|
@ -1,362 +0,0 @@
|
|||
// Generated on 2016-03-07 using generator-jhipster 2.27.2
|
||||
'use strict';
|
||||
var fs = require('fs');
|
||||
|
||||
var parseString = require('xml2js').parseString;
|
||||
// Returns the second occurence of the version number
|
||||
var parseVersionFromPomXml = function() {
|
||||
var version;
|
||||
var pomXml = fs.readFileSync('pom.xml', "utf8");
|
||||
parseString(pomXml, function (err, result){
|
||||
if (result.project.version && result.project.version[0]) {
|
||||
version = result.project.version[0];
|
||||
} else if (result.project.parent && result.project.parent[0] && result.project.parent[0].version && result.project.parent[0].version[0]) {
|
||||
version = result.project.parent[0].version[0]
|
||||
} else {
|
||||
throw new Error('pom.xml is malformed. No version is defined');
|
||||
}
|
||||
});
|
||||
return version;
|
||||
};
|
||||
|
||||
// usemin custom step
|
||||
var useminAutoprefixer = {
|
||||
name: 'autoprefixer',
|
||||
createConfig: function(context, block) {
|
||||
if(block.src.length === 0) {
|
||||
return {};
|
||||
} else {
|
||||
return require('grunt-usemin/lib/config/cssmin').createConfig(context, block) // Reuse cssmins createConfig
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = function (grunt) {
|
||||
require('load-grunt-tasks')(grunt);
|
||||
require('time-grunt')(grunt);
|
||||
|
||||
grunt.initConfig({
|
||||
yeoman: {
|
||||
// configurable paths
|
||||
app: require('./bower.json').appPath || 'app',
|
||||
dist: 'src/main/webapp/dist'
|
||||
},
|
||||
watch: {
|
||||
bower: {
|
||||
files: ['bower.json'],
|
||||
tasks: ['wiredep']
|
||||
},
|
||||
ngconstant: {
|
||||
files: ['Gruntfile.js', 'pom.xml'],
|
||||
tasks: ['ngconstant:dev']
|
||||
}
|
||||
},
|
||||
autoprefixer: {
|
||||
// src and dest is configured in a subtask called "generated" by usemin
|
||||
},
|
||||
wiredep: {
|
||||
app: {
|
||||
src: ['src/main/webapp/index.html'],
|
||||
exclude: [
|
||||
/angular-i18n/ // localizations are loaded dynamically
|
||||
]
|
||||
},
|
||||
test: {
|
||||
src: 'src/test/javascript/karma.conf.js',
|
||||
exclude: [/angular-i18n/, /angular-scenario/],
|
||||
ignorePath: /\.\.\/\.\.\//, // remove ../../ from paths of injected javascripts
|
||||
devDependencies: true,
|
||||
fileTypes: {
|
||||
js: {
|
||||
block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
|
||||
detect: {
|
||||
js: /'(.*\.js)'/gi
|
||||
},
|
||||
replace: {
|
||||
js: '\'{{filePath}}\','
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
browserSync: {
|
||||
dev: {
|
||||
bsFiles: {
|
||||
src : [
|
||||
'src/main/webapp/**/*.html',
|
||||
'src/main/webapp/**/*.json',
|
||||
'src/main/webapp/assets/styles/**/*.css',
|
||||
'src/main/webapp/scripts/**/*.{js,html}',
|
||||
'src/main/webapp/assets/images/**/*.{png,jpg,jpeg,gif,webp,svg}',
|
||||
'tmp/**/*.{css,js}'
|
||||
]
|
||||
}
|
||||
},
|
||||
options: {
|
||||
watchTask: true,
|
||||
proxy: {
|
||||
target: "localhost:8080",
|
||||
proxyOptions: {
|
||||
xfwd: true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
clean: {
|
||||
dist: {
|
||||
files: [{
|
||||
dot: true,
|
||||
src: [
|
||||
'.tmp',
|
||||
'<%= yeoman.dist %>/*',
|
||||
'!<%= yeoman.dist %>/.git*'
|
||||
]
|
||||
}]
|
||||
},
|
||||
server: '.tmp'
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: '.jshintrc'
|
||||
},
|
||||
all: [
|
||||
'Gruntfile.js',
|
||||
'src/main/webapp/scripts/app.js',
|
||||
'src/main/webapp/scripts/app/**/*.js',
|
||||
'src/main/webapp/scripts/components/**/*.js'
|
||||
]
|
||||
},
|
||||
concat: {
|
||||
// src and dest is configured in a subtask called "generated" by usemin
|
||||
},
|
||||
uglifyjs: {
|
||||
// src and dest is configured in a subtask called "generated" by usemin
|
||||
},
|
||||
rev: {
|
||||
dist: {
|
||||
files: {
|
||||
src: [
|
||||
'<%= yeoman.dist %>/scripts/**/*.js',
|
||||
'<%= yeoman.dist %>/assets/styles/**/*.css',
|
||||
'<%= yeoman.dist %>/assets/images/**/*.{png,jpg,jpeg,gif,webp,svg}',
|
||||
'<%= yeoman.dist %>/assets/fonts/*'
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
useminPrepare: {
|
||||
html: 'src/main/webapp/index.html',
|
||||
options: {
|
||||
dest: '<%= yeoman.dist %>',
|
||||
flow: {
|
||||
html: {
|
||||
steps: {
|
||||
js: ['concat', 'uglifyjs'],
|
||||
css: ['cssmin', useminAutoprefixer] // Let cssmin concat files so it corrects relative paths to fonts and images
|
||||
},
|
||||
post: {}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
usemin: {
|
||||
html: ['<%= yeoman.dist %>/**/*.html'],
|
||||
css: ['<%= yeoman.dist %>/assets/styles/**/*.css'],
|
||||
js: ['<%= yeoman.dist %>/scripts/**/*.js'],
|
||||
options: {
|
||||
assetsDirs: ['<%= yeoman.dist %>', '<%= yeoman.dist %>/assets/styles', '<%= yeoman.dist %>/assets/images', '<%= yeoman.dist %>/assets/fonts'],
|
||||
patterns: {
|
||||
js: [
|
||||
[/(assets\/images\/.*?\.(?:gif|jpeg|jpg|png|webp|svg))/gm, 'Update the JS to reference our revved images']
|
||||
]
|
||||
},
|
||||
dirs: ['<%= yeoman.dist %>']
|
||||
}
|
||||
},
|
||||
imagemin: {
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: 'src/main/webapp/assets/images',
|
||||
src: '**/*.{jpg,jpeg}', // we don't optimize PNG files as it doesn't work on Linux. If you are not on Linux, feel free to use '**/*.{png,jpg,jpeg}'
|
||||
dest: '<%= yeoman.dist %>/assets/images'
|
||||
}]
|
||||
}
|
||||
},
|
||||
svgmin: {
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: 'src/main/webapp/assets/images',
|
||||
src: '**/*.svg',
|
||||
dest: '<%= yeoman.dist %>/assets/images'
|
||||
}]
|
||||
}
|
||||
},
|
||||
cssmin: {
|
||||
// src and dest is configured in a subtask called "generated" by usemin
|
||||
},
|
||||
ngtemplates: {
|
||||
dist: {
|
||||
cwd: 'src/main/webapp',
|
||||
src: ['scripts/app/**/*.html', 'scripts/components/**/*.html',],
|
||||
dest: '.tmp/templates/templates.js',
|
||||
options: {
|
||||
module: 'sampleapplicationApp',
|
||||
usemin: 'scripts/app.js',
|
||||
htmlmin: '<%= htmlmin.dist.options %>'
|
||||
}
|
||||
}
|
||||
},
|
||||
htmlmin: {
|
||||
dist: {
|
||||
options: {
|
||||
removeCommentsFromCDATA: true,
|
||||
// https://github.com/yeoman/grunt-usemin/issues/44
|
||||
collapseWhitespace: true,
|
||||
collapseBooleanAttributes: true,
|
||||
conservativeCollapse: true,
|
||||
removeAttributeQuotes: true,
|
||||
removeRedundantAttributes: true,
|
||||
useShortDoctype: true,
|
||||
removeEmptyAttributes: true,
|
||||
keepClosingSlash: true
|
||||
},
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: '<%= yeoman.dist %>',
|
||||
src: ['*.html'],
|
||||
dest: '<%= yeoman.dist %>'
|
||||
}]
|
||||
}
|
||||
},
|
||||
// Put files not handled in other tasks here
|
||||
copy: {
|
||||
fonts: {
|
||||
files: [{
|
||||
expand: true,
|
||||
dot: true,
|
||||
flatten: true,
|
||||
cwd: 'src/main/webapp',
|
||||
dest: '<%= yeoman.dist %>/assets/fonts',
|
||||
src: [
|
||||
'bower_components/bootstrap/fonts/*.*'
|
||||
]
|
||||
}]
|
||||
},
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
dot: true,
|
||||
cwd: 'src/main/webapp',
|
||||
dest: '<%= yeoman.dist %>',
|
||||
src: [
|
||||
'*.html',
|
||||
'scripts/**/*.html',
|
||||
'assets/images/**/*.{png,gif,webp,jpg,jpeg,svg}',
|
||||
'assets/fonts/*'
|
||||
]
|
||||
}, {
|
||||
expand: true,
|
||||
cwd: '.tmp/assets/images',
|
||||
dest: '<%= yeoman.dist %>/assets/images',
|
||||
src: [
|
||||
'generated/*'
|
||||
]
|
||||
}]
|
||||
}
|
||||
},
|
||||
karma: {
|
||||
unit: {
|
||||
configFile: 'src/test/javascript/karma.conf.js',
|
||||
singleRun: true
|
||||
}
|
||||
},
|
||||
ngAnnotate: {
|
||||
dist: {
|
||||
files: [{
|
||||
expand: true,
|
||||
cwd: '.tmp/concat/scripts',
|
||||
src: '*.js',
|
||||
dest: '.tmp/concat/scripts'
|
||||
}]
|
||||
}
|
||||
},
|
||||
buildcontrol: {
|
||||
options: {
|
||||
commit: true,
|
||||
push: false,
|
||||
connectCommits: false,
|
||||
message: 'Built %sourceName% from commit %sourceCommit% on branch %sourceBranch%'
|
||||
}
|
||||
},
|
||||
ngconstant: {
|
||||
options: {
|
||||
name: 'sampleapplicationApp',
|
||||
deps: false,
|
||||
wrap: '"use strict";\n// DO NOT EDIT THIS FILE, EDIT THE GRUNT TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n{%= __ngModule %}'
|
||||
},
|
||||
dev: {
|
||||
options: {
|
||||
dest: 'src/main/webapp/scripts/app/app.constants.js'
|
||||
},
|
||||
constants: {
|
||||
ENV: 'dev',
|
||||
VERSION: parseVersionFromPomXml()
|
||||
}
|
||||
},
|
||||
prod: {
|
||||
options: {
|
||||
dest: '.tmp/scripts/app/app.constants.js'
|
||||
},
|
||||
constants: {
|
||||
ENV: 'prod',
|
||||
VERSION: parseVersionFromPomXml()
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask('serve', [
|
||||
'clean:server',
|
||||
'wiredep',
|
||||
'ngconstant:dev',
|
||||
'browserSync',
|
||||
'watch'
|
||||
]);
|
||||
|
||||
grunt.registerTask('server', function (target) {
|
||||
grunt.log.warn('The `server` task has been deprecated. Use `grunt serve` to start a server.');
|
||||
grunt.task.run([target ? ('serve:' + target) : 'serve']);
|
||||
});
|
||||
|
||||
grunt.registerTask('test', [
|
||||
'clean:server',
|
||||
'wiredep:test',
|
||||
'ngconstant:dev',
|
||||
'karma'
|
||||
]);
|
||||
|
||||
grunt.registerTask('build', [
|
||||
'clean:dist',
|
||||
'wiredep:app',
|
||||
'ngconstant:prod',
|
||||
'useminPrepare',
|
||||
'ngtemplates',
|
||||
'imagemin',
|
||||
'svgmin',
|
||||
'concat',
|
||||
'copy:fonts',
|
||||
'copy:dist',
|
||||
'ngAnnotate',
|
||||
'cssmin',
|
||||
'autoprefixer',
|
||||
'uglify',
|
||||
'rev',
|
||||
'usemin',
|
||||
'htmlmin'
|
||||
]);
|
||||
|
||||
|
||||
grunt.registerTask('default', ['serve']);
|
||||
};
|
38
README.md
38
README.md
|
@ -2,6 +2,8 @@
|
|||
|
||||
This application was generated using JHipster, you can find documentation and help at [https://jhipster.github.io](https://jhipster.github.io).
|
||||
|
||||
## 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.
|
||||
|
@ -12,25 +14,26 @@ After installing Node, you should be able to run the following command to instal
|
|||
|
||||
npm install
|
||||
|
||||
We use [Grunt][] as our build system. Install the grunt command-line tool globally with:
|
||||
We use [Gulp][] as our build system. Install the Gulp command-line tool globally with:
|
||||
|
||||
npm install -g grunt-cli
|
||||
npm install -g gulp
|
||||
|
||||
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.
|
||||
|
||||
mvn
|
||||
grunt
|
||||
./mvnw
|
||||
gulp
|
||||
|
||||
Bower is used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by
|
||||
specifying a newer version in `bower.json`. You can also run `bower update` and `bower install` to manage dependencies.
|
||||
Add the `-h` flag on any command to see how you can use it. For example, `bower update -h`.
|
||||
|
||||
# Building for production
|
||||
|
||||
## Building for production
|
||||
|
||||
To optimize the sampleApplication client for production, run:
|
||||
|
||||
mvn -Pprod clean package
|
||||
./mvnw -Pprod clean package
|
||||
|
||||
This will concatenate and minify CSS and JavaScript files. It will also modify `index.html` so it references
|
||||
these new files.
|
||||
|
@ -41,15 +44,16 @@ To ensure everything worked, run:
|
|||
|
||||
Then navigate to [http://localhost:8080](http://localhost:8080) in your browser.
|
||||
|
||||
# Testing
|
||||
## Testing
|
||||
|
||||
Unit tests are run by [Karma][] and written with [Jasmine][]. They're located in `src/test/javascript` and can be run with:
|
||||
Unit tests are run by [Karma][] and written with [Jasmine][]. They're located in `src/test/javascript/` and can be run with:
|
||||
|
||||
grunt test
|
||||
gulp test
|
||||
|
||||
UI end-to-end tests are powered by [Protractor][], which is built on top of WebDriverJS. They're located in `src/test/javascript/e2e`
|
||||
and can be run by starting Spring Boot in one terminal (`./mvnw spring-boot:run`) and running the tests (`gulp itest`) in a second one.
|
||||
|
||||
|
||||
# Continuous Integration
|
||||
## Continuous Integration
|
||||
|
||||
To setup this project in Jenkins, use the following configuration:
|
||||
|
||||
|
@ -62,13 +66,21 @@ To setup this project in Jenkins, use the following configuration:
|
|||
* Poll SCM / Schedule: `H/5 * * * *`
|
||||
* Build
|
||||
* Invoke Maven / Tasks: `-Pprod clean package`
|
||||
* Execute Shell / Command:
|
||||
````
|
||||
./mvnw spring-boot:run &
|
||||
bootPid=$!
|
||||
sleep 30s
|
||||
gulp itest
|
||||
kill $bootPid
|
||||
````
|
||||
* Post-build Actions
|
||||
* Publish JUnit test result report / Test Report XMLs: `build/test-results/*.xml`
|
||||
* Publish JUnit test result report / Test Report XMLs: `build/test-results/*.xml,build/reports/e2e/*.xml`
|
||||
|
||||
[JHipster]: https://jhipster.github.io/
|
||||
[Node.js]: https://nodejs.org/
|
||||
[Bower]: http://bower.io/
|
||||
[Grunt]: http://gruntjs.com/
|
||||
[Gulp]: http://gulpjs.com/
|
||||
[BrowserSync]: http://www.browsersync.io/
|
||||
[Karma]: http://karma-runner.github.io/
|
||||
[Jasmine]: http://jasmine.github.io/2.0/introduction.html
|
||||
|
|
69
bower.json
69
bower.json
|
@ -1,49 +1,62 @@
|
|||
{
|
||||
"name": "sampleApplication",
|
||||
"version": "0.0.0",
|
||||
"appPath": "src/main/webapp",
|
||||
"name": "sampleApplication",
|
||||
"appPath": "src/main/webapp/",
|
||||
"testPath": "src/test/javascript/spec",
|
||||
"dependencies": {
|
||||
"angular": "1.4.8",
|
||||
"angular-aria": "1.4.8",
|
||||
"angular-bootstrap": "0.14.3",
|
||||
"angular": "1.5.2",
|
||||
"angular-aria": "1.5.2",
|
||||
"angular-bootstrap": "1.2.5",
|
||||
"angular-cache-buster": "0.4.3",
|
||||
"angular-cookies": "1.4.8",
|
||||
"angular-dynamic-locale": "0.1.28",
|
||||
"angular-i18n": "1.4.8",
|
||||
"angular-local-storage": "0.2.3",
|
||||
"angular-loading-bar": "0.8.0",
|
||||
"angular-resource": "1.4.8",
|
||||
"angular-sanitize": "1.4.8",
|
||||
"angular-translate": "2.8.1",
|
||||
"angular-translate-interpolation-messageformat": "2.8.1",
|
||||
"angular-translate-loader-partial": "2.8.1",
|
||||
"angular-translate-storage-cookie": "2.8.1",
|
||||
"angular-ui-router": "0.2.15",
|
||||
"bootstrap": "3.3.5",
|
||||
"jquery": "2.1.4",
|
||||
"angular-cookies": "1.5.2",
|
||||
"angular-dynamic-locale": "0.1.30",
|
||||
"angular-i18n": "1.5.2",
|
||||
"ngstorage": "0.3.10",
|
||||
"angular-loading-bar": "0.9.0",
|
||||
"angular-resource": "1.5.2",
|
||||
"angular-sanitize": "1.5.2",
|
||||
"angular-translate": "2.11.0",
|
||||
"angular-translate-interpolation-messageformat": "2.11.0",
|
||||
"angular-translate-loader-partial": "2.11.0",
|
||||
"angular-translate-storage-cookie": "2.11.0",
|
||||
"angular-ui-router": "0.2.18",
|
||||
"bootstrap": "3.3.6",
|
||||
"bootstrap-ui-datetime-picker": "2.2.3",
|
||||
"jquery": "2.2.2",
|
||||
"json3": "3.3.2",
|
||||
"modernizr": "3.2.0",
|
||||
"ng-file-upload": "10.0.2",
|
||||
"ngInfiniteScroll": "1.2.1",
|
||||
"swagger-ui": "2.1.3"
|
||||
"modernizr": "3.3.1",
|
||||
"ng-file-upload": "12.0.4",
|
||||
"ngInfiniteScroll": "1.2.2",
|
||||
"swagger-ui": "2.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"angular-mocks": "1.4.8",
|
||||
"angular-scenario": "1.4.8"
|
||||
"angular-mocks": "1.5.2",
|
||||
"angular-scenario": "1.5.2"
|
||||
},
|
||||
"overrides": {
|
||||
"angular": {
|
||||
"dependencies": {
|
||||
"jquery": "2.2.2"
|
||||
}
|
||||
},
|
||||
"bootstrap": {
|
||||
"main": [
|
||||
"dist/js/bootstrap.js",
|
||||
"dist/css/bootstrap.css",
|
||||
"less/bootstrap.less"
|
||||
]
|
||||
},
|
||||
"messageformat": {
|
||||
"main": [
|
||||
"messageformat.js",
|
||||
"locale/en.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
"resolutions": {
|
||||
"angular": "1.4.8",
|
||||
"angular-cookies": "1.4.8",
|
||||
"jquery": "2.1.4"
|
||||
"angular": "1.5.2",
|
||||
"angular-cookies": "1.5.2",
|
||||
"angular-bootstrap": "1.2.5",
|
||||
"jquery": "2.2.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
var fs = require('fs'),
|
||||
gulp = require('gulp'),
|
||||
lazypipe = require('lazypipe'),
|
||||
footer = require('gulp-footer'),
|
||||
sourcemaps = require('gulp-sourcemaps'),
|
||||
rev = require('gulp-rev'),
|
||||
htmlmin = require('gulp-htmlmin'),
|
||||
ngAnnotate = require('gulp-ng-annotate'),
|
||||
prefix = require('gulp-autoprefixer'),
|
||||
cssnano = require('gulp-cssnano'),
|
||||
uglify = require('gulp-uglify'),
|
||||
useref = require("gulp-useref"),
|
||||
revReplace = require("gulp-rev-replace")
|
||||
plumber = require('gulp-plumber'),
|
||||
gulpIf = require('gulp-if'),
|
||||
handleErrors = require('./handleErrors');
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
var initTask = lazypipe()
|
||||
.pipe(sourcemaps.init)
|
||||
.pipe(footer, ';');
|
||||
var jsTask = lazypipe()
|
||||
.pipe(ngAnnotate)
|
||||
.pipe(uglify);
|
||||
var cssTask = lazypipe()
|
||||
.pipe(prefix)
|
||||
.pipe(cssnano);
|
||||
|
||||
module.exports = function() {
|
||||
var templates = fs.readFileSync(config.tmp + '/templates.js');
|
||||
var manifest = gulp.src(config.revManifest);
|
||||
|
||||
return gulp.src([config.app + '**/*.html',
|
||||
'!' + config.app + 'app/**/*.html',
|
||||
'!' + config.app + 'swagger-ui/**/*',
|
||||
'!' + config.bower + '**/*.html'])
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
//init sourcemaps and prepend semicolon
|
||||
.pipe(useref({}, initTask))
|
||||
//append html templates
|
||||
.pipe(gulpIf('**/app.js', footer(templates)))
|
||||
.pipe(gulpIf('*.js', jsTask()))
|
||||
.pipe(gulpIf('*.css', cssTask()))
|
||||
.pipe(gulpIf('*.html', htmlmin({collapseWhitespace: true})))
|
||||
.pipe(gulpIf('**/*.!(html)', rev()))
|
||||
.pipe(revReplace({manifest}))
|
||||
.pipe(sourcemaps.write('.'))
|
||||
.pipe(gulp.dest(config.dist));
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
module.exports = {
|
||||
app: 'src/main/webapp/',
|
||||
dist: 'target/www/',
|
||||
test: 'src/test/javascript/',
|
||||
bower: 'src/main/webapp/bower_components/',
|
||||
tmp: 'target/tmp',
|
||||
revManifest: 'target/tmp/rev-manifest.json',
|
||||
port: 9000,
|
||||
apiPort: 8080,
|
||||
liveReloadPort: 35729,
|
||||
uri: 'http://localhost:'
|
||||
};
|
|
@ -0,0 +1,20 @@
|
|||
var notify = require("gulp-notify");
|
||||
var argv = require('yargs').argv;
|
||||
|
||||
module.exports = function() {
|
||||
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var notification = argv.notification === undefined ? true : argv.notification;
|
||||
// Send error to notification center with gulp-notify
|
||||
if(notification) {
|
||||
notify.onError({
|
||||
title: "JHipster Gulp Build",
|
||||
subtitle: "Failure!",
|
||||
message: "Error: <%= error.message %>",
|
||||
sound: "Beep"
|
||||
}).apply(this, args);
|
||||
}
|
||||
// Keep gulp from hanging on this task
|
||||
this.emit('end');
|
||||
|
||||
};
|
|
@ -0,0 +1,60 @@
|
|||
var gulp = require('gulp'),
|
||||
util = require('./utils'),
|
||||
url = require('url'),
|
||||
browserSync = require('browser-sync'),
|
||||
proxy = require('proxy-middleware');
|
||||
|
||||
var config = require('./config');
|
||||
|
||||
module.exports = function () {
|
||||
var baseUri = config.uri + config.apiPort;
|
||||
// Routes to proxy to the backend. Routes ending with a / will setup
|
||||
// a redirect so that if accessed without a trailing slash, will
|
||||
// redirect. This is required for some endpoints for proxy-middleware
|
||||
// to correctly handle them.
|
||||
var proxyRoutes = [
|
||||
'/'
|
||||
];
|
||||
|
||||
var requireTrailingSlash = proxyRoutes.filter(function (r) {
|
||||
return util.endsWith(r, '/');
|
||||
}).map(function (r) {
|
||||
// Strip trailing slash so we can use the route to match requests
|
||||
// with non trailing slash
|
||||
return r.substr(0, r.length - 1);
|
||||
});
|
||||
|
||||
var proxies = [
|
||||
// Ensure trailing slash in routes that require it
|
||||
function (req, res, next) {
|
||||
requireTrailingSlash.forEach(function (route){
|
||||
if (url.parse(req.url).path === route) {
|
||||
res.statusCode = 301;
|
||||
res.setHeader('Location', route + '/');
|
||||
res.end();
|
||||
}
|
||||
});
|
||||
|
||||
next();
|
||||
}
|
||||
]
|
||||
.concat(
|
||||
// Build a list of proxies for routes: [route1_proxy, route2_proxy, ...]
|
||||
proxyRoutes.map(function (r) {
|
||||
var options = url.parse(baseUri + r);
|
||||
options.route = r;
|
||||
options.preserveHost = true;
|
||||
return proxy(options);
|
||||
}));
|
||||
|
||||
browserSync({
|
||||
open: true,
|
||||
port: config.port,
|
||||
server: {
|
||||
baseDir: config.app,
|
||||
middleware: proxies
|
||||
}
|
||||
});
|
||||
|
||||
gulp.start('watch');
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
'use strict';
|
||||
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = {
|
||||
endsWith : endsWith,
|
||||
parseVersion : parseVersion,
|
||||
isLintFixed : isLintFixed
|
||||
}
|
||||
|
||||
function endsWith(str, suffix) {
|
||||
return str.indexOf('/', str.length - suffix.length) !== -1;
|
||||
};
|
||||
|
||||
var parseString = require('xml2js').parseString;
|
||||
// return the version number from `pom.xml` file
|
||||
function parseVersion() {
|
||||
var version;
|
||||
var pomXml = fs.readFileSync('pom.xml', 'utf8');
|
||||
parseString(pomXml, function (err, result) {
|
||||
if (result.project.version && result.project.version[0]) {
|
||||
version = result.project.version[0];
|
||||
} else if (result.project.parent && result.project.parent[0] && result.project.parent[0].version && result.project.parent[0].version[0]) {
|
||||
version = result.project.parent[0].version[0];
|
||||
} else {
|
||||
throw new Error('pom.xml is malformed. No version is defined');
|
||||
}
|
||||
});
|
||||
return version;
|
||||
}
|
||||
|
||||
|
||||
function isLintFixed(file) {
|
||||
// Has ESLint fixed the file contents?
|
||||
return file.eslint !== null && file.eslint.fixed;
|
||||
}
|
|
@ -0,0 +1,275 @@
|
|||
// Generated on 2016-03-23 using generator-jhipster 3.0.0
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp'),
|
||||
rev = require('gulp-rev'),
|
||||
templateCache = require('gulp-angular-templatecache'),
|
||||
htmlmin = require('gulp-htmlmin'),
|
||||
imagemin = require('gulp-imagemin'),
|
||||
ngConstant = require('gulp-ng-constant-fork'),
|
||||
eslint = require('gulp-eslint'),
|
||||
argv = require('yargs').argv,
|
||||
gutil = require('gulp-util'),
|
||||
protractor = require('gulp-protractor').protractor,
|
||||
es = require('event-stream'),
|
||||
flatten = require('gulp-flatten'),
|
||||
del = require('del'),
|
||||
wiredep = require('wiredep').stream,
|
||||
runSequence = require('run-sequence'),
|
||||
browserSync = require('browser-sync'),
|
||||
KarmaServer = require('karma').Server,
|
||||
plumber = require('gulp-plumber'),
|
||||
changed = require('gulp-changed'),
|
||||
gulpIf = require('gulp-if'),
|
||||
inject = require('gulp-inject'),
|
||||
angularFilesort = require('gulp-angular-filesort');
|
||||
|
||||
var handleErrors = require('./gulp/handleErrors'),
|
||||
serve = require('./gulp/serve'),
|
||||
util = require('./gulp/utils'),
|
||||
build = require('./gulp/build');
|
||||
|
||||
var yorc = require('./.yo-rc.json')['generator-jhipster'];
|
||||
|
||||
var config = require('./gulp/config');
|
||||
|
||||
gulp.task('clean', function () {
|
||||
return del([config.dist], { dot: true });
|
||||
});
|
||||
|
||||
gulp.task('copy', function () {
|
||||
return es.merge(
|
||||
gulp.src(config.app + 'i18n/**')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.dist + 'i18n/'))
|
||||
.pipe(gulp.dest(config.dist + 'i18n/')),
|
||||
gulp.src(config.bower + 'bootstrap/fonts/*.*')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.dist + 'content/fonts/'))
|
||||
.pipe(rev())
|
||||
.pipe(gulp.dest(config.dist + 'content/fonts/'))
|
||||
.pipe(rev.manifest(config.revManifest, {
|
||||
base: config.dist,
|
||||
merge: true
|
||||
}))
|
||||
.pipe(gulp.dest(config.dist)),
|
||||
gulp.src(config.app + 'content/**/*.{woff,woff2,svg,ttf,eot,otf}')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.dist + 'content/fonts/'))
|
||||
.pipe(flatten())
|
||||
.pipe(rev())
|
||||
.pipe(gulp.dest(config.dist + 'content/fonts/'))
|
||||
.pipe(rev.manifest(config.revManifest, {
|
||||
base: config.dist,
|
||||
merge: true
|
||||
}))
|
||||
.pipe(gulp.dest(config.dist)),
|
||||
gulp.src([config.app + 'robots.txt', config.app + 'favicon.ico', config.app + '.htaccess'], { dot: true })
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.dist))
|
||||
.pipe(gulp.dest(config.dist))
|
||||
);
|
||||
});
|
||||
|
||||
gulp.task('images', function () {
|
||||
return gulp.src(config.app + 'content/images/**')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.dist + 'content/images'))
|
||||
.pipe(imagemin({optimizationLevel: 5, progressive: true, interlaced: true}))
|
||||
.pipe(rev())
|
||||
.pipe(gulp.dest(config.dist + 'content/images'))
|
||||
.pipe(rev.manifest(config.revManifest, {
|
||||
base: config.dist,
|
||||
merge: true
|
||||
}))
|
||||
.pipe(gulp.dest(config.dist))
|
||||
.pipe(browserSync.reload({stream: true}));
|
||||
});
|
||||
|
||||
|
||||
gulp.task('languages', function () {
|
||||
var locales = yorc.languages.map(function (locale) {
|
||||
return config.bower + 'angular-i18n/angular-locale_' + locale + '.js';
|
||||
});
|
||||
return gulp.src(locales)
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(changed(config.app + 'i18n/'))
|
||||
.pipe(gulp.dest(config.app + 'i18n/'));
|
||||
});
|
||||
|
||||
gulp.task('styles', [], function () {
|
||||
return gulp.src(config.app + 'content/css')
|
||||
.pipe(browserSync.reload({stream: true}));
|
||||
});
|
||||
|
||||
gulp.task('inject', function () {
|
||||
return gulp.src(config.app + 'index.html')
|
||||
.pipe(inject(gulp.src(config.app + 'app/**/*.js').pipe(angularFilesort()), {relative: true}))
|
||||
.pipe(gulp.dest(config.app));
|
||||
});
|
||||
|
||||
gulp.task('wiredep', ['wiredep:test', 'wiredep:app']);
|
||||
|
||||
gulp.task('wiredep:app', function () {
|
||||
var stream = gulp.src(config.app + 'index.html')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(wiredep({
|
||||
exclude: [
|
||||
/angular-i18n/, // localizations are loaded dynamically
|
||||
'bower_components/bootstrap/dist/js/' // exclude bootstrap js files as we use ui-bootstrap
|
||||
]
|
||||
}))
|
||||
.pipe(gulp.dest(config.app));
|
||||
|
||||
return stream;
|
||||
});
|
||||
|
||||
gulp.task('wiredep:test', function () {
|
||||
return gulp.src(config.test + 'karma.conf.js')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(wiredep({
|
||||
exclude: [
|
||||
/angular-i18n/, // localizations are loaded dynamically
|
||||
/angular-scenario/,
|
||||
'bower_components/bootstrap/dist/js/' // exclude Bootstrap js files as we use ui-bootstrap
|
||||
],
|
||||
ignorePath: /\.\.\/\.\.\//, // remove ../../ from paths of injected JavaScript files
|
||||
devDependencies: true,
|
||||
fileTypes: {
|
||||
js: {
|
||||
block: /(([\s\t]*)\/\/\s*bower:*(\S*))(\n|\r|.)*?(\/\/\s*endbower)/gi,
|
||||
detect: {
|
||||
js: /'(.*\.js)'/gi
|
||||
},
|
||||
replace: {
|
||||
js: '\'src/{{filePath}}\','
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
.pipe(gulp.dest(config.test));
|
||||
});
|
||||
|
||||
gulp.task('assets:prod', ['images', 'styles', 'html'], build);
|
||||
|
||||
gulp.task('html', function () {
|
||||
return gulp.src(config.app + 'app/**/*.html')
|
||||
.pipe(htmlmin({collapseWhitespace: true}))
|
||||
.pipe(templateCache({
|
||||
module: 'sampleApplicationApp',
|
||||
root: 'app/',
|
||||
moduleSystem: 'IIFE'
|
||||
}))
|
||||
.pipe(gulp.dest(config.tmp));
|
||||
});
|
||||
|
||||
gulp.task('ngconstant:dev', function () {
|
||||
return ngConstant({
|
||||
dest: 'app.constants.js',
|
||||
name: 'sampleApplicationApp',
|
||||
deps: false,
|
||||
noFile: true,
|
||||
interpolate: /\{%=(.+?)%\}/g,
|
||||
wrap:
|
||||
'(function () {\n' +
|
||||
' "use strict";\n' +
|
||||
' // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
|
||||
' {%= __ngModule %}\n' +
|
||||
'})();\n',
|
||||
constants: {
|
||||
ENV: 'dev',
|
||||
VERSION: util.parseVersion()
|
||||
}
|
||||
})
|
||||
.pipe(gulp.dest(config.app + 'app/'));
|
||||
});
|
||||
|
||||
gulp.task('ngconstant:prod', function () {
|
||||
return ngConstant({
|
||||
dest: 'app.constants.js',
|
||||
name: 'sampleApplicationApp',
|
||||
deps: false,
|
||||
noFile: true,
|
||||
interpolate: /\{%=(.+?)%\}/g,
|
||||
wrap:
|
||||
'(function () {\n' +
|
||||
' "use strict";\n' +
|
||||
' // DO NOT EDIT THIS FILE, EDIT THE GULP TASK NGCONSTANT SETTINGS INSTEAD WHICH GENERATES THIS FILE\n' +
|
||||
' {%= __ngModule %}\n' +
|
||||
'})();\n',
|
||||
constants: {
|
||||
ENV: 'prod',
|
||||
VERSION: util.parseVersion()
|
||||
}
|
||||
})
|
||||
.pipe(gulp.dest(config.app + 'app/'));
|
||||
});
|
||||
|
||||
// check app for eslint errors
|
||||
gulp.task('eslint', function () {
|
||||
return gulp.src(['gulpfile.js', config.app + 'app/**/*.js'])
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(eslint())
|
||||
.pipe(eslint.format())
|
||||
.pipe(eslint.failOnError());
|
||||
});
|
||||
|
||||
// check app for eslint errors anf fix some of them
|
||||
gulp.task('eslint:fix', function () {
|
||||
return gulp.src(config.app + 'app/**/*.js')
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(eslint({
|
||||
fix: true
|
||||
}))
|
||||
.pipe(eslint.format())
|
||||
.pipe(gulpIf(util.isLintFixed, gulp.dest(config.app + 'app')));
|
||||
});
|
||||
|
||||
gulp.task('test', ['wiredep:test', 'ngconstant:dev'], function (done) {
|
||||
new KarmaServer({
|
||||
configFile: __dirname + '/' + config.test + 'karma.conf.js',
|
||||
singleRun: true
|
||||
}, done).start();
|
||||
});
|
||||
|
||||
/* to run individual suites pass `gulp itest --suite suiteName` */
|
||||
gulp.task('protractor', function () {
|
||||
var configObj = {
|
||||
configFile: config.test + 'protractor.conf.js'
|
||||
};
|
||||
if (argv.suite) {
|
||||
configObj['args'] = ['--suite', argv.suite];
|
||||
}
|
||||
return gulp.src([])
|
||||
.pipe(plumber({errorHandler: handleErrors}))
|
||||
.pipe(protractor(configObj))
|
||||
.on('error', function () {
|
||||
gutil.log('E2E Tests failed');
|
||||
process.exit(1);
|
||||
});
|
||||
});
|
||||
|
||||
gulp.task('itest', ['protractor']);
|
||||
|
||||
gulp.task('watch', function () {
|
||||
gulp.watch('bower.json', ['install']);
|
||||
gulp.watch(['gulpfile.js', 'pom.xml'], ['ngconstant:dev']);
|
||||
gulp.watch(config.app + 'content/css/**/*.css', ['styles']);
|
||||
gulp.watch(config.app + 'content/images/**', ['images']);
|
||||
gulp.watch(config.app + 'app/**/*.js', ['inject']);
|
||||
gulp.watch([config.app + '*.html', config.app + 'app/**', config.app + 'i18n/**']).on('change', browserSync.reload);
|
||||
});
|
||||
|
||||
gulp.task('install', function () {
|
||||
runSequence(['wiredep', 'ngconstant:dev'], 'languages', 'inject');
|
||||
});
|
||||
|
||||
gulp.task('serve', function () {
|
||||
runSequence('install', serve);
|
||||
});
|
||||
|
||||
gulp.task('build', ['clean'], function (cb) {
|
||||
runSequence(['copy', 'wiredep:app', 'ngconstant:prod', 'languages'], 'inject', 'assets:prod', cb);
|
||||
});
|
||||
|
||||
gulp.task('default', ['serve']);
|
99
package.json
99
package.json
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"name": "sampleapplication",
|
||||
"name": "sample-application",
|
||||
"version": "0.0.0",
|
||||
"description": "Description for sampleApplication",
|
||||
"private": true,
|
||||
|
@ -11,57 +11,62 @@
|
|||
"bower": "^1.6.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "0.4.5",
|
||||
"grunt-autoprefixer": "3.0.3",
|
||||
"grunt-build-control": "0.6.1",
|
||||
"grunt-wiredep": "2.0.0",
|
||||
"grunt-browser-sync": "2.2.0",
|
||||
"browser-sync": "2.10.0",
|
||||
"grunt-contrib-copy": "0.8.2",
|
||||
"grunt-contrib-clean": "0.7.0",
|
||||
"grunt-contrib-concat": "0.5.1",
|
||||
"grunt-contrib-cssmin": "0.14.0",
|
||||
"grunt-contrib-htmlmin": "0.6.0",
|
||||
"grunt-contrib-imagemin": "1.0.0",
|
||||
"grunt-contrib-jshint": "0.11.3",
|
||||
"grunt-contrib-uglify": "0.10.1",
|
||||
"grunt-contrib-watch": "0.6.1",
|
||||
"grunt-modernizr": "1.0.1",
|
||||
"grunt-ng-annotate": "1.0.1",
|
||||
"grunt-ng-constant": "1.1.0",
|
||||
"grunt-rev": "0.1.0",
|
||||
"grunt-svgmin": "3.1.0",
|
||||
"grunt-text-replace": "0.4.0",
|
||||
"grunt-usemin": "3.1.1",
|
||||
"grunt-angular-templates":"0.5.7",
|
||||
"load-grunt-tasks": "3.3.0",
|
||||
"grunt-karma": "0.12.1",
|
||||
"time-grunt": "1.2.2",
|
||||
"browser-sync": "2.11.2",
|
||||
"del": "2.2.0",
|
||||
"eslint-config-angular": "0.5.0",
|
||||
"eslint-plugin-angular": "1.0.0",
|
||||
"event-stream": "3.3.2",
|
||||
"jshint-stylish": "2.1.0",
|
||||
"karma-script-launcher": "0.1.0",
|
||||
"karma-chrome-launcher": "0.2.1",
|
||||
"karma-html2js-preprocessor": "0.1.0",
|
||||
"karma-jasmine": "0.3.6",
|
||||
"karma-requirejs": "0.2.2",
|
||||
"karma-phantomjs-launcher": "0.2.1",
|
||||
"phantomjs": "1.9.18",
|
||||
"karma": "0.13.19",
|
||||
"karma-coverage": "0.5.3",
|
||||
"generator-jhipster": "3.0.0",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-angular-filesort": "1.1.1",
|
||||
"gulp-angular-templatecache": "1.8.0",
|
||||
"gulp-autoprefixer": "3.1.0",
|
||||
"gulp-changed": "1.3.0",
|
||||
"gulp-cssnano": "2.1.1",
|
||||
"gulp-eslint": "2.0.0",
|
||||
"gulp-flatten": "0.2.0",
|
||||
"gulp-footer": "1.0.5",
|
||||
"gulp-htmlmin": "1.3.0",
|
||||
"gulp-if": "2.0.0",
|
||||
"gulp-imagemin": "2.4.0",
|
||||
"gulp-inject": "3.0.0",
|
||||
"gulp-ng-annotate": "2.0.0",
|
||||
"gulp-ng-constant-fork": "0.4.1",
|
||||
"gulp-notify": "2.2.0",
|
||||
"gulp-plumber": "1.1.0",
|
||||
"gulp-protractor": "2.1.0",
|
||||
"gulp-util": "3.0.7",
|
||||
"gulp-rev": "7.0.0",
|
||||
"gulp-rev-replace": "^0.4.3",
|
||||
"gulp-sourcemaps": "1.6.0",
|
||||
"gulp-uglify": "1.5.3",
|
||||
"gulp-useref": "3.0.7",
|
||||
"jasmine-core": "2.4.1",
|
||||
"jasmine-reporters": "2.1.1",
|
||||
"karma": "0.13.22",
|
||||
"karma-chrome-launcher": "0.2.3",
|
||||
"karma-coverage": "0.5.5",
|
||||
"karma-jasmine": "0.3.8",
|
||||
"karma-jenkins-reporter": "0.0.2",
|
||||
"generator-jhipster": "2.27.2",
|
||||
"lodash": "3.10.1",
|
||||
"xml2js": "0.4.15",
|
||||
"yo": ">=1.3.0",
|
||||
"requirejs": "2.1",
|
||||
"jasmine-core": "2.3.4",
|
||||
"zeparser": "0.0.7",
|
||||
"wiredep": "2.2.2"
|
||||
"karma-phantomjs-launcher": "1.0.0",
|
||||
"karma-script-launcher": "0.2.0",
|
||||
"lazypipe": "1.0.1",
|
||||
"lodash": "4.6.1",
|
||||
"map-stream": "0.0.6",
|
||||
"phantomjs-prebuilt": "2.1.4",
|
||||
"protractor": "3.1.1",
|
||||
"protractor-jasmine2-screenshot-reporter": "0.3.0",
|
||||
"proxy-middleware": "0.15.0",
|
||||
"run-sequence": "1.1.5",
|
||||
"wiredep": "4.0.0",
|
||||
"xml2js": "0.4.16",
|
||||
"yargs": "4.3.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "^0.12 || ^4.2"
|
||||
"node": "^4.3"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "grunt test"
|
||||
"test": "gulp test",
|
||||
"postinstall": "webdriver-manager update"
|
||||
}
|
||||
}
|
||||
|
|
163
pom.xml
163
pom.xml
|
@ -5,12 +5,12 @@
|
|||
<parent>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<version>1.3.1.RELEASE</version>
|
||||
<version>1.3.3.RELEASE</version>
|
||||
<relativePath/>
|
||||
</parent>
|
||||
|
||||
<groupId>com.mycompany.myapp</groupId>
|
||||
<artifactId>sampleapplication</artifactId>
|
||||
<artifactId>sample-application</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<packaging>war</packaging>
|
||||
<name>sampleApplication</name>
|
||||
|
@ -33,9 +33,9 @@
|
|||
</prerequisites>
|
||||
|
||||
<properties>
|
||||
<hikaricp.version>2.4.1</hikaricp.version>
|
||||
<assertj-core.version>3.1.0</assertj-core.version>
|
||||
<awaitility.version>1.4.0</awaitility.version>
|
||||
<hikaricp.version>2.4.3</hikaricp.version>
|
||||
<assertj-core.version>3.3.0</assertj-core.version>
|
||||
<awaitility.version>1.7.0</awaitility.version>
|
||||
<commons-io.version>2.4</commons-io.version>
|
||||
<commons-lang.version>2.6</commons-lang.version>
|
||||
<gatling.version>2.1.7</gatling.version>
|
||||
|
@ -50,18 +50,19 @@
|
|||
<liquibase-hibernate4.version>3.5</liquibase-hibernate4.version>
|
||||
<mapstruct.version>1.0.0.Final</mapstruct.version>
|
||||
<maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>
|
||||
<maven-enforcer-plugin.version>1.3.1</maven-enforcer-plugin.version>
|
||||
<maven-sortpom-plugin.version>2.3.0</maven-sortpom-plugin.version>
|
||||
<maven-enforcer-plugin.version>1.4.1</maven-enforcer-plugin.version>
|
||||
<sortpom-maven-plugin.version>2.5.0</sortpom-maven-plugin.version>
|
||||
<metrics-spark-reporter.version>1.2</metrics-spark-reporter.version>
|
||||
<metrics-spring.version>3.1.2</metrics-spring.version>
|
||||
<metrics-spring.version>3.1.3</metrics-spring.version>
|
||||
<logstash-logback-encoder.version>4.6</logstash-logback-encoder.version>
|
||||
<run.addResources>false</run.addResources>
|
||||
<spring-security.version>4.0.2.RELEASE</spring-security.version>
|
||||
<springfox.version>2.0.3</springfox.version>
|
||||
<spring-security.version>4.0.4.RELEASE</spring-security.version>
|
||||
<springfox.version>2.4.0</springfox.version>
|
||||
<!-- Sonar properties -->
|
||||
<project.testresult.directory>${project.build.directory}/test-results</project.testresult.directory>
|
||||
<sonar-maven-plugin.version>2.6</sonar-maven-plugin.version>
|
||||
<jacoco-maven-plugin.version>0.7.4.201502262128</jacoco-maven-plugin.version>
|
||||
<sonar.exclusions>src/main/webapp/assets/**/*.*, src/main/webapp/bower_components/**/*.*, src/main/webapp/dist/**/*.*</sonar.exclusions>
|
||||
<sonar-maven-plugin.version>2.7.1</sonar-maven-plugin.version>
|
||||
<jacoco-maven-plugin.version>0.7.6.201602180812</jacoco-maven-plugin.version>
|
||||
<sonar.exclusions>src/main/webapp/content/**/*.*, src/main/webapp/bower_components/**/*.*, target/www/**/*.*</sonar.exclusions>
|
||||
<sonar.java.codeCoveragePlugin>jacoco</sonar.java.codeCoveragePlugin>
|
||||
<sonar.jacoco.itReportPath>${project.testresult.directory}/coverage/jacoco/jacoco-it.exec</sonar.jacoco.itReportPath>
|
||||
<sonar.jacoco.reportPath>${project.testresult.directory}/coverage/jacoco/jacoco.exec</sonar.jacoco.reportPath>
|
||||
|
@ -204,12 +205,13 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
<!-- The HikariCP Java Agent is disabled by default, as it is experimental
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-agent</artifactId>
|
||||
<version>${HikariCP.version}</version>
|
||||
</dependency>
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>com.zaxxer</groupId>
|
||||
<artifactId>HikariCP-agent</artifactId>
|
||||
<version>${HikariCP.version}</version>
|
||||
</dependency>
|
||||
-->
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
<artifactId>commons-io</artifactId>
|
||||
|
@ -336,6 +338,25 @@
|
|||
</exclusions>
|
||||
</dependency>
|
||||
<!-- Spring Cloud -->
|
||||
<dependency>
|
||||
<groupId>net.logstash.logback</groupId>
|
||||
<artifactId>logstash-logback-encoder</artifactId>
|
||||
<version>${logstash-logback-encoder.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-access</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-cloudfoundry-connector</artifactId>
|
||||
|
@ -365,14 +386,14 @@
|
|||
<defaultGoal>spring-boot:run</defaultGoal>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<directory>src/main/resources/</directory>
|
||||
<filtering>true</filtering>
|
||||
<includes>
|
||||
<include>**/*.xml</include>
|
||||
</includes>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<directory>src/main/resources/</directory>
|
||||
<filtering>false</filtering>
|
||||
<excludes>
|
||||
<exclude>**/*.xml</exclude>
|
||||
|
@ -381,9 +402,9 @@
|
|||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.google.code.sortpom</groupId>
|
||||
<artifactId>maven-sortpom-plugin</artifactId>
|
||||
<version>${maven-sortpom-plugin.version}</version>
|
||||
<groupId>com.github.ekryd.sortpom</groupId>
|
||||
<artifactId>sortpom-maven-plugin</artifactId>
|
||||
<version>${sortpom-maven-plugin.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>verify</phase>
|
||||
|
@ -453,18 +474,11 @@
|
|||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>-Xmx256m ${surefireArgLine}</argLine>
|
||||
<argLine>-Djava.security.egd=file:/dev/./urandom -Xmx256m ${surefireArgLine}</argLine>
|
||||
<!-- Force alphabetical order to have a reproducible build -->
|
||||
<runOrder>alphabetical</runOrder>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<packagingExcludes>WEB-INF/lib/tomcat-*.jar</packagingExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.jacoco</groupId>
|
||||
<artifactId>jacoco-maven-plugin</artifactId>
|
||||
|
@ -546,7 +560,7 @@
|
|||
<defaultSchemaName></defaultSchemaName>
|
||||
<username></username>
|
||||
<password></password>
|
||||
<referenceUrl>hibernate:spring:com.mycompany.myapp.domain?dialect=</referenceUrl>
|
||||
<referenceUrl>hibernate:spring:com.mycompany.myapp.domain?dialect=&hibernate.ejb.naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy</referenceUrl>
|
||||
<verbose>true</verbose>
|
||||
<logging>debug</logging>
|
||||
</configuration>
|
||||
|
@ -573,12 +587,31 @@
|
|||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<executable>true</executable>
|
||||
<!--
|
||||
Enable the line below to have remote debugging of your application on port 5005
|
||||
<jvmArguments>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005</jvmArguments>
|
||||
-->
|
||||
<arguments>
|
||||
<argument>--spring.profiles.active=dev</argument>
|
||||
</arguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>docker-maven-plugin</artifactId>
|
||||
<version>0.4.1</version>
|
||||
<configuration>
|
||||
<imageName>sampleapplication</imageName>
|
||||
<dockerDirectory>src/main/docker</dockerDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<targetPath>/</targetPath>
|
||||
<directory>${project.build.directory}</directory>
|
||||
<include>${project.build.finalName}.war</include>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- jhipster-needle-maven-add-plugin -->
|
||||
</plugins>
|
||||
<pluginManagement>
|
||||
|
@ -612,6 +645,23 @@
|
|||
<ignore/>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
<pluginExecution>
|
||||
<pluginExecutionFilter>
|
||||
<groupId>com.github.trecloux</groupId>
|
||||
<artifactId>
|
||||
yeoman-maven-plugin
|
||||
</artifactId>
|
||||
<versionRange>
|
||||
[0.5,)
|
||||
</versionRange>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</pluginExecutionFilter>
|
||||
<action>
|
||||
<ignore/>
|
||||
</action>
|
||||
</pluginExecution>
|
||||
</pluginExecutions>
|
||||
</lifecycleMappingMetadata>
|
||||
</configuration>
|
||||
|
@ -641,34 +691,14 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>fast</id>
|
||||
<properties>
|
||||
<!-- log configuration -->
|
||||
<logback.loglevel>DEBUG</logback.loglevel>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-undertow</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-devtools</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<executable>true</executable>
|
||||
<arguments>
|
||||
<argument>--spring.profiles.active=dev,fast</argument>
|
||||
</arguments>
|
||||
<warSourceDirectory>src/main/webapp/</warSourceDirectory>
|
||||
<packagingExcludes>WEB-INF/lib/tomcat-*.jar</packagingExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
@ -687,7 +717,7 @@
|
|||
<plugin>
|
||||
<groupId>com.github.trecloux</groupId>
|
||||
<artifactId>yeoman-maven-plugin</artifactId>
|
||||
<version>0.4</version>
|
||||
<version>0.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>run-frontend-build</id>
|
||||
|
@ -696,8 +726,8 @@
|
|||
<goal>build</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<buildTool>grunt</buildTool>
|
||||
<buildArgs>build --no-color</buildArgs>
|
||||
<buildTool>gulp</buildTool>
|
||||
<buildArgs>build --no-notification</buildArgs>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
|
@ -711,10 +741,7 @@
|
|||
<configuration>
|
||||
<filesets>
|
||||
<fileset>
|
||||
<directory>src/main/webapp/dist</directory>
|
||||
</fileset>
|
||||
<fileset>
|
||||
<directory>.tmp</directory>
|
||||
<directory>target/www/</directory>
|
||||
</fileset>
|
||||
<fileset>
|
||||
<directory>node_modules</directory>
|
||||
|
@ -722,6 +749,14 @@
|
|||
</filesets>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<warSourceDirectory>target/www/</warSourceDirectory>
|
||||
<packagingExcludes>WEB-INF/lib/tomcat-*.jar</packagingExcludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
FROM java:openjdk-8-jdk-alpine
|
||||
|
||||
# add directly the war
|
||||
ADD *.war /app.war
|
||||
|
||||
RUN sh -c 'touch /app.war'
|
||||
VOLUME /tmp
|
||||
CMD ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.war"]
|
||||
|
||||
EXPOSE 8080
|
|
@ -0,0 +1,15 @@
|
|||
version: '2'
|
||||
services:
|
||||
sampleapplication-app:
|
||||
image: sampleapplication
|
||||
external_links:
|
||||
- sampleapplication-mysql:mysql
|
||||
environment:
|
||||
- SPRING_PROFILES_ACTIVE=prod
|
||||
- SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/sampleapplication?useUnicode=true&characterEncoding=utf8&useSSL=false
|
||||
ports:
|
||||
- 8080:8080
|
||||
sampleapplication-mysql:
|
||||
extends:
|
||||
file: mysql.yml
|
||||
service: sampleapplication-mysql
|
|
@ -0,0 +1,14 @@
|
|||
version: '2'
|
||||
services:
|
||||
sampleapplication-mysql:
|
||||
container_name: sampleapplication-mysql
|
||||
image: mysql:5.7.11
|
||||
# volumes:
|
||||
# - ~/volumes/jhipster/sampleApplication/mysql/:/var/lib/mysql/
|
||||
environment:
|
||||
- MYSQL_USER=root
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
- MYSQL_DATABASE=sampleapplication
|
||||
ports:
|
||||
- 3306:3306
|
||||
command: mysqld --lower_case_table_names=1
|
|
@ -1,12 +0,0 @@
|
|||
sampleapplication-mysql:
|
||||
container_name: sampleapplication-mysql
|
||||
image: mysql:5.7.9
|
||||
# volumes:
|
||||
# - ~/volumes/jhipster/sampleApplication/mysql/:/var/lib/mysql/
|
||||
environment:
|
||||
- MYSQL_USER=root
|
||||
- MYSQL_ALLOW_EMPTY_PASSWORD=yes
|
||||
- MYSQL_DATABASE=sampleapplication
|
||||
ports:
|
||||
- "3306:3306"
|
||||
command: mysqld --lower_case_table_names=1
|
|
@ -1,6 +1,8 @@
|
|||
sampleapplication-sonar:
|
||||
container_name: sampleapplication-sonar
|
||||
image: sonarqube:4.5.6
|
||||
ports:
|
||||
- "9000:9000"
|
||||
- "9092:9092"
|
||||
version: '2'
|
||||
services:
|
||||
sampleapplication-sonar:
|
||||
container_name: sampleapplication-sonar
|
||||
image: sonarqube:5.3
|
||||
ports:
|
||||
- 9000:9000
|
||||
- 9092:9092
|
||||
|
|
|
@ -17,7 +17,7 @@ public class ApplicationWebXml extends SpringBootServletInitializer {
|
|||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.profiles(addDefaultProfile())
|
||||
.sources(Application.class);
|
||||
.sources(SampleApplicationApp.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -6,8 +6,7 @@ import com.mycompany.myapp.config.JHipsterProperties;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.autoconfigure.MetricFilterAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.MetricRepositoryAutoConfiguration;
|
||||
import org.springframework.boot.actuate.autoconfigure.*;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
|
@ -17,7 +16,6 @@ import org.springframework.core.env.SimpleCommandLinePropertySource;
|
|||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
|
@ -26,24 +24,22 @@ import java.util.Collection;
|
|||
@ComponentScan
|
||||
@EnableAutoConfiguration(exclude = { MetricFilterAutoConfiguration.class, MetricRepositoryAutoConfiguration.class })
|
||||
@EnableConfigurationProperties({ JHipsterProperties.class, LiquibaseProperties.class })
|
||||
public class Application {
|
||||
public class SampleApplicationApp {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Application.class);
|
||||
private static final Logger log = LoggerFactory.getLogger(SampleApplicationApp.class);
|
||||
|
||||
@Inject
|
||||
private Environment env;
|
||||
|
||||
/**
|
||||
* Initializes sampleApplication.
|
||||
* <p/>
|
||||
* Spring profiles can be configured with a program arguments --spring.profiles.active=your-active-profile
|
||||
* <p/>
|
||||
* <p>
|
||||
* You can find more information on how profiles work with JHipster on <a href="http://jhipster.github.io/profiles.html">http://jhipster.github.io/profiles.html</a>.
|
||||
* </p>
|
||||
* Spring profiles can be configured with a program arguments --spring.profiles.active=your-active-profile
|
||||
* <p>
|
||||
* You can find more information on how profiles work with JHipster on <a href="http://jhipster.github.io/profiles/">http://jhipster.github.io/profiles/</a>.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void initApplication() throws IOException {
|
||||
public void initApplication() {
|
||||
if (env.getActiveProfiles().length == 0) {
|
||||
log.warn("No Spring profile configured, running with default configuration");
|
||||
} else {
|
||||
|
@ -53,10 +49,6 @@ public class Application {
|
|||
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(Constants.SPRING_PROFILE_PRODUCTION) && activeProfiles.contains(Constants.SPRING_PROFILE_FAST)) {
|
||||
log.error("You have misconfigured your application! " +
|
||||
"It should not run with both the 'prod' and 'fast' profiles at the same time.");
|
||||
}
|
||||
if (activeProfiles.contains(Constants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(Constants.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.");
|
||||
|
@ -66,15 +58,20 @@ public class Application {
|
|||
|
||||
/**
|
||||
* Main method, used to run the application.
|
||||
*
|
||||
* @param args the command line arguments
|
||||
* @throws UnknownHostException if the local host name could not be resolved into an address
|
||||
*/
|
||||
public static void main(String[] args) throws UnknownHostException {
|
||||
SpringApplication app = new SpringApplication(Application.class);
|
||||
SpringApplication app = new SpringApplication(SampleApplicationApp.class);
|
||||
SimpleCommandLinePropertySource source = new SimpleCommandLinePropertySource(args);
|
||||
addDefaultProfile(app, source);
|
||||
Environment env = app.run(args).getEnvironment();
|
||||
log.info("Access URLs:\n----------------------------------------------------------\n\t" +
|
||||
log.info("\n----------------------------------------------------------\n\t" +
|
||||
"Application '{}' is running! Access URLs:\n\t" +
|
||||
"Local: \t\thttp://127.0.0.1:{}\n\t" +
|
||||
"External: \thttp://{}:{}\n----------------------------------------------------------",
|
||||
env.getProperty("spring.application.name"),
|
||||
env.getProperty("server.port"),
|
||||
InetAddress.getLocalHost().getHostAddress(),
|
||||
env.getProperty("server.port"));
|
|
@ -22,7 +22,7 @@ public class ExceptionHandlingAsyncTaskExecutor implements AsyncTaskExecutor,
|
|||
|
||||
@Override
|
||||
public void execute(Runnable task) {
|
||||
executor.execute(task);
|
||||
executor.execute(createWrappedRunnable(task));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -33,7 +33,7 @@ public class AsyncConfiguration implements AsyncConfigurer {
|
|||
executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
|
||||
executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
|
||||
executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
|
||||
executor.setThreadNamePrefix("sampleapplication-Executor-");
|
||||
executor.setThreadNamePrefix("sample-application-Executor-");
|
||||
return new ExceptionHandlingAsyncTaskExecutor(executor);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.SortedSet;
|
|||
@Configuration
|
||||
@EnableCaching
|
||||
@AutoConfigureAfter(value = { MetricsConfiguration.class, DatabaseConfiguration.class })
|
||||
@Profile("!" + Constants.SPRING_PROFILE_FAST)
|
||||
public class CacheConfiguration {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
|
||||
|
|
|
@ -5,14 +5,17 @@ package com.mycompany.myapp.config;
|
|||
*/
|
||||
public final class Constants {
|
||||
|
||||
// Spring profile for development, production and "fast", see http://jhipster.github.io/profiles.html
|
||||
// Spring profile for development and production, see http://jhipster.github.io/profiles/
|
||||
public static final String SPRING_PROFILE_DEVELOPMENT = "dev";
|
||||
public static final String SPRING_PROFILE_PRODUCTION = "prod";
|
||||
public static final String SPRING_PROFILE_FAST = "fast";
|
||||
// Spring profile used when deploying with Spring Cloud (used when deploying to CloudFoundry)
|
||||
public static final String SPRING_PROFILE_CLOUD = "cloud";
|
||||
// Spring profile used when deploying to Heroku
|
||||
public static final String SPRING_PROFILE_HEROKU = "heroku";
|
||||
// Spring profile used to disable swagger
|
||||
public static final String SPRING_PROFILE_NO_SWAGGER = "no-swagger";
|
||||
// Spring profile used to disable running liquibase
|
||||
public static final String SPRING_PROFILE_NO_LIQUIBASE = "no-liquibase";
|
||||
|
||||
public static final String SYSTEM_ACCOUNT = "system";
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.mycompany.myapp.config.liquibase.AsyncSpringLiquibase;
|
|||
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.fasterxml.jackson.datatype.hibernate4.Hibernate4Module;
|
||||
import com.zaxxer.hikari.HikariConfig;
|
||||
import com.zaxxer.hikari.HikariDataSource;
|
||||
import liquibase.integration.spring.SpringLiquibase;
|
||||
import org.h2.tools.Server;
|
||||
|
@ -12,8 +11,10 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceBuilder;
|
||||
import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties;
|
||||
import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.ApplicationContextException;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
@ -43,8 +44,9 @@ public class DatabaseConfiguration {
|
|||
private MetricRegistry metricRegistry;
|
||||
|
||||
@Bean(destroyMethod = "close")
|
||||
@ConditionalOnExpression("#{!environment.acceptsProfiles('cloud') && !environment.acceptsProfiles('heroku')}")
|
||||
public DataSource dataSource(DataSourceProperties dataSourceProperties, JHipsterProperties jHipsterProperties) {
|
||||
@ConditionalOnExpression("#{!environment.acceptsProfiles('" + Constants.SPRING_PROFILE_CLOUD + "') && !environment.acceptsProfiles('" + Constants.SPRING_PROFILE_HEROKU + "')}")
|
||||
@ConfigurationProperties(prefix = "spring.datasource.hikari")
|
||||
public DataSource dataSource(DataSourceProperties dataSourceProperties) {
|
||||
log.debug("Configuring Datasource");
|
||||
if (dataSourceProperties.getUrl() == null) {
|
||||
log.error("Your database connection pool configuration is incorrect! The application" +
|
||||
|
@ -53,34 +55,26 @@ public class DatabaseConfiguration {
|
|||
|
||||
throw new ApplicationContextException("Database connection pool is not configured correctly");
|
||||
}
|
||||
HikariConfig config = new HikariConfig();
|
||||
config.setDataSourceClassName(dataSourceProperties.getDriverClassName());
|
||||
config.addDataSourceProperty("url", dataSourceProperties.getUrl());
|
||||
if (dataSourceProperties.getUsername() != null) {
|
||||
config.addDataSourceProperty("user", dataSourceProperties.getUsername());
|
||||
} else {
|
||||
config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
|
||||
}
|
||||
if (dataSourceProperties.getPassword() != null) {
|
||||
config.addDataSourceProperty("password", dataSourceProperties.getPassword());
|
||||
} else {
|
||||
config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
|
||||
}
|
||||
HikariDataSource hikariDataSource = (HikariDataSource) DataSourceBuilder
|
||||
.create(dataSourceProperties.getClassLoader())
|
||||
.type(HikariDataSource.class)
|
||||
.driverClassName(dataSourceProperties.getDriverClassName())
|
||||
.url(dataSourceProperties.getUrl())
|
||||
.username(dataSourceProperties.getUsername())
|
||||
.password(dataSourceProperties.getPassword())
|
||||
.build();
|
||||
|
||||
//MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
|
||||
if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) {
|
||||
config.addDataSourceProperty("cachePrepStmts", jHipsterProperties.getDatasource().isCachePrepStmts());
|
||||
config.addDataSourceProperty("prepStmtCacheSize", jHipsterProperties.getDatasource().getPrepStmtCacheSize());
|
||||
config.addDataSourceProperty("prepStmtCacheSqlLimit", jHipsterProperties.getDatasource().getPrepStmtCacheSqlLimit());
|
||||
}
|
||||
if (metricRegistry != null) {
|
||||
config.setMetricRegistry(metricRegistry);
|
||||
hikariDataSource.setMetricRegistry(metricRegistry);
|
||||
}
|
||||
return new HikariDataSource(config);
|
||||
return hikariDataSource;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(Constants.SPRING_PROFILE_DEVELOPMENT)
|
||||
|
@ -99,18 +93,13 @@ public class DatabaseConfiguration {
|
|||
liquibase.setContexts(liquibaseProperties.getContexts());
|
||||
liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
|
||||
liquibase.setDropFirst(liquibaseProperties.isDropFirst());
|
||||
liquibase.setShouldRun(liquibaseProperties.isEnabled());
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_FAST)) {
|
||||
if ("org.h2.jdbcx.JdbcDataSource".equals(dataSourceProperties.getDriverClassName())) {
|
||||
liquibase.setShouldRun(true);
|
||||
log.warn("Using '{}' profile with H2 database in memory is not optimal, you should consider switching to" +
|
||||
" MySQL or Postgresql to avoid rebuilding your database upon each start.", Constants.SPRING_PROFILE_FAST);
|
||||
} else {
|
||||
liquibase.setShouldRun(false);
|
||||
}
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_NO_LIQUIBASE)) {
|
||||
liquibase.setShouldRun(false);
|
||||
} else {
|
||||
liquibase.setShouldRun(liquibaseProperties.isEnabled());
|
||||
log.debug("Configuring Liquibase");
|
||||
}
|
||||
|
||||
return liquibase;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import javax.validation.constraints.NotNull;
|
|||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.web.cors.CorsConfiguration;
|
||||
|
||||
|
||||
/**
|
||||
* Properties specific to JHipster.
|
||||
*
|
||||
|
@ -19,8 +20,6 @@ public class JHipsterProperties {
|
|||
|
||||
private final Http http = new Http();
|
||||
|
||||
private final Datasource datasource = new Datasource();
|
||||
|
||||
private final Cache cache = new Cache();
|
||||
|
||||
private final Mail mail = new Mail();
|
||||
|
@ -33,8 +32,6 @@ public class JHipsterProperties {
|
|||
|
||||
private final CorsConfiguration cors = new CorsConfiguration();
|
||||
|
||||
|
||||
|
||||
public Async getAsync() {
|
||||
return async;
|
||||
}
|
||||
|
@ -43,10 +40,6 @@ public class JHipsterProperties {
|
|||
return http;
|
||||
}
|
||||
|
||||
public Datasource getDatasource() {
|
||||
return datasource;
|
||||
}
|
||||
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
@ -71,7 +64,6 @@ public class JHipsterProperties {
|
|||
return cors;
|
||||
}
|
||||
|
||||
|
||||
public static class Async {
|
||||
|
||||
private int corePoolSize = 2;
|
||||
|
@ -115,7 +107,7 @@ public class JHipsterProperties {
|
|||
|
||||
public static class Cache {
|
||||
|
||||
private int timeToLiveInDays = 31;
|
||||
private int timeToLiveInDays = 1461;
|
||||
|
||||
public int getTimeToLiveInDays() {
|
||||
return timeToLiveInDays;
|
||||
|
@ -127,49 +119,6 @@ public class JHipsterProperties {
|
|||
}
|
||||
}
|
||||
|
||||
public static class Datasource {
|
||||
|
||||
private boolean cachePrepStmts = true;
|
||||
|
||||
private int prepStmtCacheSize = 250;
|
||||
|
||||
private int prepStmtCacheSqlLimit = 2048;
|
||||
|
||||
private boolean useServerPrepStmts = true;
|
||||
|
||||
public boolean isCachePrepStmts() {
|
||||
return cachePrepStmts;
|
||||
}
|
||||
|
||||
public void setCachePrepStmts(boolean cachePrepStmts) {
|
||||
this.cachePrepStmts = cachePrepStmts;
|
||||
}
|
||||
|
||||
public int getPrepStmtCacheSize() {
|
||||
return prepStmtCacheSize;
|
||||
}
|
||||
|
||||
public void setPrepStmtCacheSize(int prepStmtCacheSize) {
|
||||
this.prepStmtCacheSize = prepStmtCacheSize;
|
||||
}
|
||||
|
||||
public int getPrepStmtCacheSqlLimit() {
|
||||
return prepStmtCacheSqlLimit;
|
||||
}
|
||||
|
||||
public void setPrepStmtCacheSqlLimit(int prepStmtCacheSqlLimit) {
|
||||
this.prepStmtCacheSqlLimit = prepStmtCacheSqlLimit;
|
||||
}
|
||||
|
||||
public boolean isUseServerPrepStmts() {
|
||||
return useServerPrepStmts;
|
||||
}
|
||||
|
||||
public void setUseServerPrepStmts(boolean useServerPrepStmts) {
|
||||
this.useServerPrepStmts = useServerPrepStmts;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Cache {
|
||||
|
||||
private int timeToLiveSeconds = 3600;
|
||||
|
@ -217,13 +166,13 @@ public class JHipsterProperties {
|
|||
|
||||
public static class Security {
|
||||
|
||||
private final Rememberme rememberme = new Rememberme();
|
||||
private final RememberMe rememberMe = new RememberMe();
|
||||
|
||||
public Rememberme getRememberme() {
|
||||
return rememberme;
|
||||
public RememberMe getRememberMe() {
|
||||
return rememberMe;
|
||||
}
|
||||
|
||||
public static class Rememberme {
|
||||
public static class RememberMe {
|
||||
|
||||
@NotNull
|
||||
private String key;
|
||||
|
@ -248,7 +197,11 @@ public class JHipsterProperties {
|
|||
|
||||
private String termsOfServiceUrl;
|
||||
|
||||
private String contact;
|
||||
private String contactName;
|
||||
|
||||
private String contactUrl;
|
||||
|
||||
private String contactEmail;
|
||||
|
||||
private String license;
|
||||
|
||||
|
@ -286,12 +239,28 @@ public class JHipsterProperties {
|
|||
this.termsOfServiceUrl = termsOfServiceUrl;
|
||||
}
|
||||
|
||||
public String getContact() {
|
||||
return contact;
|
||||
public String getContactName() {
|
||||
return contactName;
|
||||
}
|
||||
|
||||
public void setContact(String contact) {
|
||||
this.contact = contact;
|
||||
public void setContactName(String contactName) {
|
||||
this.contactName = contactName;
|
||||
}
|
||||
|
||||
public String getContactUrl() {
|
||||
return contactUrl;
|
||||
}
|
||||
|
||||
public void setContactUrl(String contactUrl) {
|
||||
this.contactUrl = contactUrl;
|
||||
}
|
||||
|
||||
public String getContactEmail() {
|
||||
return contactEmail;
|
||||
}
|
||||
|
||||
public void setContactEmail(String contactEmail) {
|
||||
this.contactEmail = contactEmail;
|
||||
}
|
||||
|
||||
public String getLicense() {
|
||||
|
@ -319,6 +288,8 @@ public class JHipsterProperties {
|
|||
|
||||
private final Graphite graphite = new Graphite();
|
||||
|
||||
private final Logs logs = new Logs();
|
||||
|
||||
public Jmx getJmx() {
|
||||
return jmx;
|
||||
}
|
||||
|
@ -331,6 +302,11 @@ public class JHipsterProperties {
|
|||
return graphite;
|
||||
}
|
||||
|
||||
public Logs getLogs() {
|
||||
return logs;
|
||||
}
|
||||
|
||||
|
||||
public static class Jmx {
|
||||
|
||||
private boolean enabled = true;
|
||||
|
@ -419,5 +395,67 @@ public class JHipsterProperties {
|
|||
this.prefix = prefix;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Logs {
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
private long reportFrequency = 60;
|
||||
|
||||
public long getReportFrequency() {
|
||||
return reportFrequency;
|
||||
}
|
||||
|
||||
public void setReportFrequency(int reportFrequency) {
|
||||
this.reportFrequency = reportFrequency;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private final Logging logging = new Logging();
|
||||
|
||||
public Logging getLogging() { return logging; }
|
||||
|
||||
public static class Logging {
|
||||
|
||||
private final Logstash logstash = new Logstash();
|
||||
|
||||
public Logstash getLogstash() { return logstash; }
|
||||
|
||||
public static class Logstash {
|
||||
|
||||
private boolean enabled = false;
|
||||
|
||||
private String host = "localhost";
|
||||
|
||||
private int port = 5000;
|
||||
|
||||
private int queueSize = 512;
|
||||
|
||||
public boolean isEnabled() { return enabled; }
|
||||
|
||||
public void setEnabled(boolean enabled) { this.enabled = enabled; }
|
||||
|
||||
public String getHost() { return host; }
|
||||
|
||||
public void setHost(String host) { this.host = host; }
|
||||
|
||||
public int getPort() { return port; }
|
||||
|
||||
public void setPort(int port) { this.port = port; }
|
||||
|
||||
public int getQueueSize() { return queueSize; }
|
||||
|
||||
public void setQueueSize(int queueSize) { this.queueSize = queueSize; }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -4,10 +4,8 @@ import com.mycompany.myapp.config.locale.AngularCookieLocaleResolver;
|
|||
|
||||
import org.springframework.boot.bind.RelaxedPropertyResolver;
|
||||
import org.springframework.context.EnvironmentAware;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.web.servlet.LocaleResolver;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
|
@ -31,15 +29,6 @@ public class LocaleConfiguration extends WebMvcConfigurerAdapter implements Envi
|
|||
return cookieLocaleResolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageSource messageSource() {
|
||||
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
|
||||
messageSource.setBasename("classpath:/i18n/messages");
|
||||
messageSource.setDefaultEncoding("UTF-8");
|
||||
messageSource.setCacheSeconds(propertyResolver.getProperty("cache-seconds", Integer.class, -1));
|
||||
return messageSource;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package com.mycompany.myapp.config;
|
||||
|
||||
import ch.qos.logback.classic.AsyncAppender;
|
||||
import ch.qos.logback.classic.LoggerContext;
|
||||
import net.logstash.logback.appender.LogstashSocketAppender;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
|
||||
@Configuration
|
||||
public class LoggingConfiguration {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
|
||||
|
||||
private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
|
||||
|
||||
@Value("${spring.application.name}")
|
||||
private String appName;
|
||||
|
||||
@Value("${server.port}")
|
||||
private String serverPort;
|
||||
|
||||
@Inject
|
||||
private JHipsterProperties jHipsterProperties;
|
||||
|
||||
@PostConstruct
|
||||
private void init() {
|
||||
if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
|
||||
addLogstashAppender();
|
||||
}
|
||||
}
|
||||
|
||||
public void addLogstashAppender() {
|
||||
log.info("Initializing Logstash logging");
|
||||
|
||||
LogstashSocketAppender logstashAppender = new LogstashSocketAppender();
|
||||
logstashAppender.setName("LOGSTASH");
|
||||
logstashAppender.setContext(context);
|
||||
|
||||
String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"}";
|
||||
|
||||
// Set the Logstash appender config from JHipster properties
|
||||
logstashAppender.setSyslogHost(jHipsterProperties.getLogging().getLogstash().getHost());
|
||||
logstashAppender.setPort(jHipsterProperties.getLogging().getLogstash().getPort());
|
||||
logstashAppender.setCustomFields(customFields);
|
||||
logstashAppender.start();
|
||||
|
||||
// Wrap the appender in an Async appender for performance
|
||||
AsyncAppender asyncLogstashAppender = new AsyncAppender();
|
||||
asyncLogstashAppender.setContext(context);
|
||||
asyncLogstashAppender.setName("ASYNC_LOGSTASH");
|
||||
asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
|
||||
asyncLogstashAppender.addAppender(logstashAppender);
|
||||
asyncLogstashAppender.start();
|
||||
|
||||
context.getLogger("ROOT").addAppender(asyncLogstashAppender);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ package com.mycompany.myapp.config;
|
|||
|
||||
import com.codahale.metrics.JmxReporter;
|
||||
import com.codahale.metrics.MetricRegistry;
|
||||
import com.codahale.metrics.Slf4jReporter;
|
||||
import com.codahale.metrics.graphite.Graphite;
|
||||
import com.codahale.metrics.graphite.GraphiteReporter;
|
||||
import com.codahale.metrics.health.HealthCheckRegistry;
|
||||
|
@ -22,7 +23,6 @@ import java.util.concurrent.TimeUnit;
|
|||
|
||||
@Configuration
|
||||
@EnableMetrics(proxyTargetClass = true)
|
||||
@Profile("!" + Constants.SPRING_PROFILE_FAST)
|
||||
public class MetricsConfiguration extends MetricsConfigurerAdapter {
|
||||
|
||||
private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
|
||||
|
@ -65,11 +65,20 @@ public class MetricsConfiguration extends MetricsConfigurerAdapter {
|
|||
JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
|
||||
jmxReporter.start();
|
||||
}
|
||||
|
||||
if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
|
||||
log.info("Initializing Metrics Log reporting");
|
||||
final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)
|
||||
.outputTo(LoggerFactory.getLogger("metrics"))
|
||||
.convertRatesTo(TimeUnit.SECONDS)
|
||||
.convertDurationsTo(TimeUnit.MILLISECONDS)
|
||||
.build();
|
||||
reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);
|
||||
}
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@ConditionalOnClass(Graphite.class)
|
||||
@Profile("!" + Constants.SPRING_PROFILE_FAST)
|
||||
public static class GraphiteRegistry {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(GraphiteRegistry.class);
|
||||
|
@ -100,7 +109,6 @@ public class MetricsConfiguration extends MetricsConfigurerAdapter {
|
|||
|
||||
@Configuration
|
||||
@ConditionalOnClass(SparkReporter.class)
|
||||
@Profile("!" + Constants.SPRING_PROFILE_FAST)
|
||||
public static class SparkRegistry {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(SparkRegistry.class);
|
||||
|
|
|
@ -2,9 +2,11 @@ package com.mycompany.myapp.config;
|
|||
|
||||
import com.mycompany.myapp.security.*;
|
||||
import com.mycompany.myapp.web.filter.CsrfCookieGeneratorFilter;
|
||||
import com.mycompany.myapp.config.JHipsterProperties;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.http.HttpMethod;
|
||||
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;
|
||||
|
@ -27,7 +29,7 @@ import javax.inject.Inject;
|
|||
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
||||
|
||||
@Inject
|
||||
private Environment env;
|
||||
private JHipsterProperties jHipsterProperties;
|
||||
|
||||
@Inject
|
||||
private AjaxAuthenticationSuccessHandler ajaxAuthenticationSuccessHandler;
|
||||
|
@ -62,10 +64,11 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
@Override
|
||||
public void configure(WebSecurity web) throws Exception {
|
||||
web.ignoring()
|
||||
.antMatchers("/scripts/**/*.{js,html}")
|
||||
.antMatchers(HttpMethod.OPTIONS, "/**")
|
||||
.antMatchers("/app/**/*.{js,html}")
|
||||
.antMatchers("/bower_components/**")
|
||||
.antMatchers("/i18n/**")
|
||||
.antMatchers("/assets/**")
|
||||
.antMatchers("/content/**")
|
||||
.antMatchers("/swagger-ui/index.html")
|
||||
.antMatchers("/test/**")
|
||||
.antMatchers("/h2-console/**");
|
||||
|
@ -84,7 +87,7 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
.rememberMe()
|
||||
.rememberMeServices(rememberMeServices)
|
||||
.rememberMeParameter("remember-me")
|
||||
.key(env.getProperty("jhipster.security.rememberme.key"))
|
||||
.key(jHipsterProperties.getSecurity().getRememberMe().getKey())
|
||||
.and()
|
||||
.formLogin()
|
||||
.loginProcessingUrl("/api/authentication")
|
||||
|
@ -123,7 +126,6 @@ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
|
|||
.antMatchers("/info/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/autoconfig/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/env/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/trace/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/mappings/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/liquibase/**").hasAuthority(AuthoritiesConstants.ADMIN)
|
||||
.antMatchers("/v2/api-docs/**").permitAll()
|
||||
|
|
|
@ -3,9 +3,7 @@ package com.mycompany.myapp.config;
|
|||
import org.apache.commons.lang.CharEncoding;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.context.MessageSource;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
|
||||
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
|
||||
|
||||
@Configuration
|
||||
|
@ -24,14 +22,4 @@ public class ThymeleafConfiguration {
|
|||
emailTemplateResolver.setOrder(1);
|
||||
return emailTemplateResolver;
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Description("Spring mail message resolver")
|
||||
public MessageSource emailMessageSource() {
|
||||
log.info("loading non-reloadable mail messages resources");
|
||||
ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
|
||||
messageSource.setBasename("classpath:/mails/messages/messages");
|
||||
messageSource.setDefaultEncoding(CharEncoding.UTF_8);
|
||||
return messageSource;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.codahale.metrics.MetricRegistry;
|
|||
import com.codahale.metrics.servlet.InstrumentedFilter;
|
||||
import com.codahale.metrics.servlets.MetricsServlet;
|
||||
import com.mycompany.myapp.web.filter.CachingHttpHeadersFilter;
|
||||
import com.mycompany.myapp.web.filter.StaticResourcesProductionFilter;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
@ -19,6 +18,7 @@ import org.springframework.web.cors.CorsConfiguration;
|
|||
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
|
||||
import org.springframework.web.filter.CorsFilter;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
import javax.inject.Inject;
|
||||
import javax.servlet.*;
|
||||
|
@ -35,7 +35,7 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
private Environment env;
|
||||
|
||||
@Inject
|
||||
private JHipsterProperties props;
|
||||
private JHipsterProperties jHipsterProperties;
|
||||
|
||||
@Autowired(required = false)
|
||||
private MetricRegistry metricRegistry;
|
||||
|
@ -44,12 +44,9 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
public void onStartup(ServletContext servletContext) throws ServletException {
|
||||
log.info("Web application configuration, using profiles: {}", Arrays.toString(env.getActiveProfiles()));
|
||||
EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
|
||||
if (!env.acceptsProfiles(Constants.SPRING_PROFILE_FAST)) {
|
||||
initMetrics(servletContext, disps);
|
||||
}
|
||||
initMetrics(servletContext, disps);
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
|
||||
initCachingHttpHeadersFilter(servletContext, disps);
|
||||
initStaticResourcesProductionFilter(servletContext, disps);
|
||||
}
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT)) {
|
||||
initH2Console(servletContext);
|
||||
|
@ -58,7 +55,7 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
}
|
||||
|
||||
/**
|
||||
* Set up Mime types.
|
||||
* Set up Mime types and, if needed, set the document root.
|
||||
*/
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer container) {
|
||||
|
@ -68,24 +65,17 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
// CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
|
||||
mappings.add("json", "text/html;charset=utf-8");
|
||||
container.setMimeMappings(mappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the static resources production Filter.
|
||||
*/
|
||||
private void initStaticResourcesProductionFilter(ServletContext servletContext,
|
||||
EnumSet<DispatcherType> disps) {
|
||||
|
||||
log.debug("Registering static resources production Filter");
|
||||
FilterRegistration.Dynamic staticResourcesProductionFilter =
|
||||
servletContext.addFilter("staticResourcesProductionFilter",
|
||||
new StaticResourcesProductionFilter());
|
||||
|
||||
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/");
|
||||
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/index.html");
|
||||
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/assets/*");
|
||||
staticResourcesProductionFilter.addMappingForUrlPatterns(disps, true, "/scripts/*");
|
||||
staticResourcesProductionFilter.setAsyncSupported(true);
|
||||
// When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets.
|
||||
File root;
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_PRODUCTION)) {
|
||||
root = new File("target/www/");
|
||||
} else {
|
||||
root = new File("src/main/webapp/");
|
||||
}
|
||||
if (root.exists() && root.isDirectory()) {
|
||||
container.setDocumentRoot(root);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -96,10 +86,10 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
log.debug("Registering Caching HTTP Headers Filter");
|
||||
FilterRegistration.Dynamic cachingHttpHeadersFilter =
|
||||
servletContext.addFilter("cachingHttpHeadersFilter",
|
||||
new CachingHttpHeadersFilter(env));
|
||||
new CachingHttpHeadersFilter(jHipsterProperties));
|
||||
|
||||
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/assets/*");
|
||||
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/dist/scripts/*");
|
||||
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*");
|
||||
cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*");
|
||||
cachingHttpHeadersFilter.setAsyncSupported(true);
|
||||
}
|
||||
|
||||
|
@ -132,7 +122,7 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
@Bean
|
||||
public CorsFilter corsFilter() {
|
||||
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
|
||||
CorsConfiguration config = props.getCors();
|
||||
CorsConfiguration config = jHipsterProperties.getCors();
|
||||
if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
|
||||
source.registerCorsConfiguration("/api/**", config);
|
||||
source.registerCorsConfiguration("/v2/api-docs", config);
|
||||
|
@ -148,7 +138,7 @@ public class WebConfigurer implements ServletContextInitializer, EmbeddedServlet
|
|||
log.debug("Initialize H2 console");
|
||||
ServletRegistration.Dynamic h2ConsoleServlet = servletContext.addServlet("H2Console", new org.h2.server.web.WebServlet());
|
||||
h2ConsoleServlet.addMapping("/h2-console/*");
|
||||
h2ConsoleServlet.setInitParameter("-properties", "src/main/resources");
|
||||
h2ConsoleServlet.setInitParameter("-properties", "src/main/resources/");
|
||||
h2ConsoleServlet.setLoadOnStartup(1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,13 @@ import com.mycompany.myapp.config.JHipsterProperties;
|
|||
import java.util.Date;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
|
||||
import org.springframework.context.annotation.*;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.util.StopWatch;
|
||||
import springfox.documentation.service.ApiInfo;
|
||||
import springfox.documentation.service.Contact;
|
||||
import springfox.documentation.spi.DocumentationType;
|
||||
import springfox.documentation.spring.web.plugins.Docket;
|
||||
import springfox.documentation.swagger2.annotations.EnableSwagger2;
|
||||
|
@ -26,7 +28,7 @@ import static springfox.documentation.builders.PathSelectors.regex;
|
|||
*/
|
||||
@Configuration
|
||||
@EnableSwagger2
|
||||
@Profile("!" + Constants.SPRING_PROFILE_PRODUCTION)
|
||||
@ConditionalOnExpression("#{!environment.acceptsProfiles('" + Constants.SPRING_PROFILE_NO_SWAGGER + "') && !environment.acceptsProfiles('" + Constants.SPRING_PROFILE_PRODUCTION + "')}")
|
||||
public class SwaggerConfiguration {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(SwaggerConfiguration.class);
|
||||
|
@ -35,29 +37,36 @@ public class SwaggerConfiguration {
|
|||
|
||||
/**
|
||||
* Swagger Springfox configuration.
|
||||
*
|
||||
* @param jHipsterProperties the properties of the application
|
||||
* @return the Swagger Springfox configuration
|
||||
*/
|
||||
@Bean
|
||||
@Profile("!" + Constants.SPRING_PROFILE_FAST)
|
||||
public Docket swaggerSpringfoxDocket(JHipsterProperties jHipsterProperties) {
|
||||
log.debug("Starting Swagger");
|
||||
StopWatch watch = new StopWatch();
|
||||
watch.start();
|
||||
Contact contact = new Contact(
|
||||
jHipsterProperties.getSwagger().getContactName(),
|
||||
jHipsterProperties.getSwagger().getContactUrl(),
|
||||
jHipsterProperties.getSwagger().getContactEmail());
|
||||
|
||||
ApiInfo apiInfo = new ApiInfo(
|
||||
jHipsterProperties.getSwagger().getTitle(),
|
||||
jHipsterProperties.getSwagger().getDescription(),
|
||||
jHipsterProperties.getSwagger().getVersion(),
|
||||
jHipsterProperties.getSwagger().getTermsOfServiceUrl(),
|
||||
jHipsterProperties.getSwagger().getContact(),
|
||||
contact,
|
||||
jHipsterProperties.getSwagger().getLicense(),
|
||||
jHipsterProperties.getSwagger().getLicenseUrl());
|
||||
|
||||
Docket docket = new Docket(DocumentationType.SWAGGER_2)
|
||||
.apiInfo(apiInfo)
|
||||
.genericModelSubstitutes(ResponseEntity.class)
|
||||
.forCodeGeneration(true)
|
||||
.genericModelSubstitutes(ResponseEntity.class)
|
||||
.ignoredParameterTypes(Pageable.class)
|
||||
.directModelSubstitute(java.time.LocalDate.class, String.class)
|
||||
.ignoredParameterTypes(java.sql.Date.class)
|
||||
.directModelSubstitute(java.time.LocalDate.class, java.sql.Date.class)
|
||||
.directModelSubstitute(java.time.ZonedDateTime.class, Date.class)
|
||||
.directModelSubstitute(java.time.LocalDateTime.class, Date.class)
|
||||
.select()
|
||||
|
|
|
@ -16,7 +16,7 @@ import liquibase.integration.spring.SpringLiquibase;
|
|||
/**
|
||||
* Specific liquibase.integration.spring.SpringLiquibase that will update the database asynchronously.
|
||||
* <p>
|
||||
* By default, this asynchronous version only works when using the "dev" profile.<br/>
|
||||
* By default, this asynchronous version only works when using the "dev" profile.<p>
|
||||
* The standard liquibase.integration.spring.SpringLiquibase starts Liquibase in the current thread:
|
||||
* <ul>
|
||||
* <li>This is needed if you want to do some database requests at startup</li>
|
||||
|
@ -27,7 +27,6 @@ import liquibase.integration.spring.SpringLiquibase;
|
|||
* <li>On a recent MacBook Pro, start-up time is down from 14 seconds to 8 seconds</li>
|
||||
* <li>In production, this can help your application run on platforms like Heroku, where it must start/restart very quickly</li>
|
||||
* </ul>
|
||||
* </p>
|
||||
*/
|
||||
public class AsyncSpringLiquibase extends SpringLiquibase {
|
||||
|
||||
|
@ -42,18 +41,22 @@ public class AsyncSpringLiquibase extends SpringLiquibase {
|
|||
|
||||
@Override
|
||||
public void afterPropertiesSet() throws LiquibaseException {
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT, Constants.SPRING_PROFILE_HEROKU)) {
|
||||
taskExecutor.execute(() -> {
|
||||
try {
|
||||
log.warn("Starting Liquibase asynchronously, your database might not be ready at startup!");
|
||||
initDb();
|
||||
} catch (LiquibaseException e) {
|
||||
log.error("Liquibase could not start correctly, your database is NOT ready: {}", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
if (!env.acceptsProfiles(Constants.SPRING_PROFILE_NO_LIQUIBASE)) {
|
||||
if (env.acceptsProfiles(Constants.SPRING_PROFILE_DEVELOPMENT, Constants.SPRING_PROFILE_HEROKU)) {
|
||||
taskExecutor.execute(() -> {
|
||||
try {
|
||||
log.warn("Starting Liquibase asynchronously, your database might not be ready at startup!");
|
||||
initDb();
|
||||
} catch (LiquibaseException e) {
|
||||
log.error("Liquibase could not start correctly, your database is NOT ready: {}", e.getMessage(), e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
log.debug("Starting Liquibase synchronously");
|
||||
initDb();
|
||||
}
|
||||
} else {
|
||||
log.debug("Starting Liquibase synchronously");
|
||||
initDb();
|
||||
log.debug("Liquibase is disabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,11 @@ public abstract class AbstractAuditingEntity implements Serializable {
|
|||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@CreatedBy
|
||||
@NotNull
|
||||
@Column(name = "created_by", nullable = false, length = 50, updatable = false)
|
||||
@JsonIgnore
|
||||
private String createdBy;
|
||||
|
||||
@CreatedDate
|
||||
@NotNull
|
||||
@Column(name = "created_date", nullable = false)
|
||||
@JsonIgnore
|
||||
private ZonedDateTime createdDate = ZonedDateTime.now();
|
||||
|
|
|
@ -18,6 +18,8 @@ import java.io.Serializable;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class Authority implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@NotNull
|
||||
@Size(min = 0, max = 50)
|
||||
@Id
|
||||
|
|
|
@ -20,6 +20,8 @@ import java.util.Objects;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class BankAccount implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
@ -27,13 +29,12 @@ public class BankAccount implements Serializable {
|
|||
@NotNull
|
||||
@Column(name = "name", nullable = false)
|
||||
private String name;
|
||||
|
||||
|
||||
@NotNull
|
||||
@Column(name = "balance", precision=10, scale=2, nullable = false)
|
||||
private BigDecimal balance;
|
||||
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "user_id")
|
||||
private User user;
|
||||
|
||||
@OneToMany(mappedBy = "bankAccount")
|
||||
|
@ -52,7 +53,7 @@ public class BankAccount implements Serializable {
|
|||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
@ -60,7 +61,7 @@ public class BankAccount implements Serializable {
|
|||
public BigDecimal getBalance() {
|
||||
return balance;
|
||||
}
|
||||
|
||||
|
||||
public void setBalance(BigDecimal balance) {
|
||||
this.balance = balance;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@ import java.util.Objects;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class Label implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
@ -27,7 +29,7 @@ public class Label implements Serializable {
|
|||
@Size(min = 3)
|
||||
@Column(name = "label", nullable = false)
|
||||
private String label;
|
||||
|
||||
|
||||
@ManyToMany(mappedBy = "labels")
|
||||
@JsonIgnore
|
||||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
|
@ -44,7 +46,7 @@ public class Label implements Serializable {
|
|||
public String getLabel() {
|
||||
return label;
|
||||
}
|
||||
|
||||
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
|
|
@ -2,12 +2,12 @@ package com.mycompany.myapp.domain;
|
|||
|
||||
import org.hibernate.annotations.Cache;
|
||||
import org.hibernate.annotations.CacheConcurrencyStrategy;
|
||||
import java.time.ZonedDateTime;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.*;
|
||||
import java.io.Serializable;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
|
@ -20,6 +20,8 @@ import java.util.Objects;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class Operation implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
@ -27,16 +29,15 @@ public class Operation implements Serializable {
|
|||
@NotNull
|
||||
@Column(name = "date", nullable = false)
|
||||
private ZonedDateTime date;
|
||||
|
||||
|
||||
@Column(name = "description")
|
||||
private String description;
|
||||
|
||||
|
||||
@NotNull
|
||||
@Column(name = "amount", precision=10, scale=2, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "bank_account_id")
|
||||
private BankAccount bankAccount;
|
||||
|
||||
@ManyToMany
|
||||
|
@ -57,7 +58,7 @@ public class Operation implements Serializable {
|
|||
public ZonedDateTime getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
|
||||
public void setDate(ZonedDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
@ -65,7 +66,7 @@ public class Operation implements Serializable {
|
|||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
|
||||
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
@ -73,7 +74,7 @@ public class Operation implements Serializable {
|
|||
public BigDecimal getAmount() {
|
||||
return amount;
|
||||
}
|
||||
|
||||
|
||||
public void setAmount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
}
|
||||
|
|
|
@ -22,10 +22,9 @@ import java.io.Serializable;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class PersistentToken implements Serializable {
|
||||
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("d MMMM yyyy");
|
||||
|
||||
|
||||
|
||||
private static final int MAX_USER_AGENT_LEN = 255;
|
||||
|
||||
|
|
|
@ -22,6 +22,8 @@ import java.time.ZonedDateTime;
|
|||
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
|
||||
public class User extends AbstractAuditingEntity implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.AUTO)
|
||||
private Long id;
|
||||
|
@ -46,11 +48,13 @@ public class User extends AbstractAuditingEntity implements Serializable {
|
|||
@Column(name = "last_name", length = 50)
|
||||
private String lastName;
|
||||
|
||||
@NotNull
|
||||
@Email
|
||||
@Size(max = 100)
|
||||
@Column(length = 100, unique = true)
|
||||
private String email;
|
||||
|
||||
@NotNull
|
||||
@Column(nullable = false)
|
||||
private boolean activated = false;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import com.fasterxml.jackson.databind.SerializerProvider;
|
|||
public final class JSR310DateTimeSerializer extends JsonSerializer<TemporalAccessor> {
|
||||
|
||||
private static final DateTimeFormatter ISOFormatter =
|
||||
DateTimeFormatter.ISO_OFFSET_DATE_TIME.withZone(ZoneId.of("Z"));
|
||||
DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZone(ZoneId.of("Z"));
|
||||
|
||||
public static final JSR310DateTimeSerializer INSTANCE = new JSR310DateTimeSerializer();
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@ import com.mycompany.myapp.domain.PersistentAuditEvent;
|
|||
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.boot.actuate.audit.AuditEventRepository;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
@ -18,54 +17,48 @@ import java.util.Date;
|
|||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Wraps an implementation of Spring Boot's AuditEventRepository.
|
||||
* An implementation of Spring Boot's AuditEventRepository.
|
||||
*/
|
||||
@Repository
|
||||
public class CustomAuditEventRepository {
|
||||
public class CustomAuditEventRepository implements AuditEventRepository {
|
||||
|
||||
private static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
|
||||
|
||||
private static final String ANONYMOUS_USER = "anonymousUser";
|
||||
|
||||
@Inject
|
||||
private PersistenceAuditEventRepository persistenceAuditEventRepository;
|
||||
|
||||
@Bean
|
||||
public AuditEventRepository auditEventRepository() {
|
||||
return new AuditEventRepository() {
|
||||
@Inject
|
||||
private AuditEventConverter auditEventConverter;
|
||||
|
||||
private static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
|
||||
@Override
|
||||
public List<AuditEvent> find(String principal, Date after) {
|
||||
Iterable<PersistentAuditEvent> persistentAuditEvents;
|
||||
if (principal == null && after == null) {
|
||||
persistentAuditEvents = persistenceAuditEventRepository.findAll();
|
||||
} else if (after == null) {
|
||||
persistentAuditEvents = persistenceAuditEventRepository.findByPrincipal(principal);
|
||||
} else {
|
||||
persistentAuditEvents =
|
||||
persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfter(principal, LocalDateTime.from(after.toInstant()));
|
||||
}
|
||||
return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
|
||||
}
|
||||
|
||||
private static final String ANONYMOUS_USER = "anonymousUser";
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void add(AuditEvent event) {
|
||||
if (!AUTHORIZATION_FAILURE.equals(event.getType()) &&
|
||||
!ANONYMOUS_USER.equals(event.getPrincipal().toString())) {
|
||||
|
||||
@Inject
|
||||
private AuditEventConverter auditEventConverter;
|
||||
|
||||
@Override
|
||||
public List<AuditEvent> find(String principal, Date after) {
|
||||
Iterable<PersistentAuditEvent> persistentAuditEvents;
|
||||
if (principal == null && after == null) {
|
||||
persistentAuditEvents = persistenceAuditEventRepository.findAll();
|
||||
} else if (after == null) {
|
||||
persistentAuditEvents = persistenceAuditEventRepository.findByPrincipal(principal);
|
||||
} else {
|
||||
persistentAuditEvents =
|
||||
persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfter(principal, LocalDateTime.from(after.toInstant()));
|
||||
}
|
||||
return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public void add(AuditEvent event) {
|
||||
if (!AUTHORIZATION_FAILURE.equals(event.getType()) &&
|
||||
!ANONYMOUS_USER.equals(event.getPrincipal().toString())) {
|
||||
|
||||
PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent();
|
||||
persistentAuditEvent.setPrincipal(event.getPrincipal());
|
||||
persistentAuditEvent.setAuditEventType(event.getType());
|
||||
Instant instant = Instant.ofEpochMilli(event.getTimestamp().getTime());
|
||||
persistentAuditEvent.setAuditEventDate(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));
|
||||
persistentAuditEvent.setData(auditEventConverter.convertDataToStrings(event.getData()));
|
||||
persistenceAuditEventRepository.save(persistentAuditEvent);
|
||||
}
|
||||
}
|
||||
};
|
||||
PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent();
|
||||
persistentAuditEvent.setPrincipal(event.getPrincipal());
|
||||
persistentAuditEvent.setAuditEventType(event.getType());
|
||||
Instant instant = Instant.ofEpochMilli(event.getTimestamp().getTime());
|
||||
persistentAuditEvent.setAuditEventDate(LocalDateTime.ofInstant(instant, ZoneId.systemDefault()));
|
||||
persistentAuditEvent.setData(auditEventConverter.convertDataToStrings(event.getData()));
|
||||
persistenceAuditEventRepository.save(persistentAuditEvent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ import com.mycompany.myapp.domain.PersistentAuditEvent;
|
|||
|
||||
import java.time.LocalDateTime;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
@ -16,5 +18,5 @@ public interface PersistenceAuditEventRepository extends JpaRepository<Persisten
|
|||
|
||||
List<PersistentAuditEvent> findByPrincipalAndAuditEventDateAfter(String principal, LocalDateTime after);
|
||||
|
||||
List<PersistentAuditEvent> findAllByAuditEventDateBetween(LocalDateTime fromDate, LocalDateTime toDate);
|
||||
Page<PersistentAuditEvent> findAllByAuditEventDateBetween(LocalDateTime fromDate, LocalDateTime toDate, Pageable pageable);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import com.mycompany.myapp.domain.PersistentToken;
|
|||
import com.mycompany.myapp.domain.User;
|
||||
import com.mycompany.myapp.repository.PersistentTokenRepository;
|
||||
import com.mycompany.myapp.repository.UserRepository;
|
||||
import com.mycompany.myapp.config.JHipsterProperties;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
@ -25,9 +26,9 @@ import java.util.Arrays;
|
|||
|
||||
/**
|
||||
* Custom implementation of Spring Security's RememberMeServices.
|
||||
* <p/>
|
||||
* <p>
|
||||
* Persistent tokens are used by Spring Security to automatically log in users.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This is a specific implementation of Spring Security's remember-me authentication, but it is much
|
||||
* more powerful than the standard implementations:
|
||||
* <ul>
|
||||
|
@ -35,17 +36,16 @@ import java.util.Arrays;
|
|||
* <li>It stores more information, such as the IP address and the user agent, for audit purposes<li>
|
||||
* <li>When a user logs out, only his current session is invalidated, and not all of his sessions</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p>
|
||||
* This is inspired by:
|
||||
* <ul>
|
||||
* <li><a href="http://jaspan.com/improved_persistent_login_cookie_best_practice">Improved Persistent Login Cookie
|
||||
* Best Practice</a></li>
|
||||
* <li><a href="https://github.com/blog/1661-modeling-your-app-s-user-session">Github's "Modeling your App's User Session"</a></li></li>
|
||||
* <li><a href="https://github.com/blog/1661-modeling-your-app-s-user-session">Github's "Modeling your App's User Session"</a></li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p>
|
||||
* The main algorithm comes from Spring Security's PersistentTokenBasedRememberMeServices, but this class
|
||||
* couldn't be cleanly extended.
|
||||
* <p/>
|
||||
*/
|
||||
@Service
|
||||
public class CustomPersistentRememberMeServices extends
|
||||
|
@ -71,15 +71,14 @@ public class CustomPersistentRememberMeServices extends
|
|||
private UserRepository userRepository;
|
||||
|
||||
@Inject
|
||||
public CustomPersistentRememberMeServices(Environment env, org.springframework.security.core.userdetails
|
||||
public CustomPersistentRememberMeServices(JHipsterProperties jHipsterProperties, org.springframework.security.core.userdetails
|
||||
.UserDetailsService userDetailsService) {
|
||||
|
||||
super(env.getProperty("jhipster.security.rememberme.key"), userDetailsService);
|
||||
super(jHipsterProperties.getSecurity().getRememberMe().getKey(), userDetailsService);
|
||||
random = new SecureRandom();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional
|
||||
protected UserDetails processAutoLoginCookie(String[] cookieTokens, HttpServletRequest request,
|
||||
HttpServletResponse response) {
|
||||
|
||||
|
@ -129,7 +128,7 @@ public class CustomPersistentRememberMeServices extends
|
|||
|
||||
/**
|
||||
* When logout occurs, only invalidate the current token, and not all user sessions.
|
||||
* <p/>
|
||||
* <p>
|
||||
* The standard Spring Security implementations are too basic: they invalidate all tokens for the
|
||||
* current user, so when he logs out from one browser, all his other sessions are destroyed.
|
||||
*/
|
||||
|
|
|
@ -5,7 +5,6 @@ import org.springframework.security.core.GrantedAuthority;
|
|||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
import java.util.Collection;
|
||||
|
@ -20,6 +19,8 @@ public final class SecurityUtils {
|
|||
|
||||
/**
|
||||
* Get the login of the current user.
|
||||
*
|
||||
* @return the login of the current user
|
||||
*/
|
||||
public static String getCurrentUserLogin() {
|
||||
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
|
@ -54,27 +55,13 @@ public final class SecurityUtils {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the current user, or throws an exception, if the user is not
|
||||
* authenticated yet.
|
||||
*
|
||||
* @return the current user
|
||||
*/
|
||||
public static User getCurrentUser() {
|
||||
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
Authentication authentication = securityContext.getAuthentication();
|
||||
if (authentication != null) {
|
||||
if (authentication.getPrincipal() instanceof User) {
|
||||
return (User) authentication.getPrincipal();
|
||||
}
|
||||
}
|
||||
throw new IllegalStateException("User not found!");
|
||||
}
|
||||
|
||||
/**
|
||||
* If the current user has a specific authority (security role).
|
||||
*
|
||||
* <p>The name of this method comes from the isUserInRole() method in the Servlet API</p>
|
||||
*
|
||||
* @param authority the authorithy to check
|
||||
* @return true if the current user has the authority, false otherwise
|
||||
*/
|
||||
public static boolean isCurrentUserInRole(String authority) {
|
||||
SecurityContext securityContext = SecurityContextHolder.getContext();
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
package com.mycompany.myapp.service;
|
||||
|
||||
import com.mycompany.myapp.config.audit.AuditEventConverter;
|
||||
import com.mycompany.myapp.domain.PersistentAuditEvent;
|
||||
import com.mycompany.myapp.repository.PersistenceAuditEventRepository;
|
||||
import java.time.LocalDateTime;
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
|
@ -14,7 +15,6 @@ import java.util.Optional;
|
|||
|
||||
/**
|
||||
* Service for managing audit events.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This is the default implementation to support SpringBoot Actuator AuditEventRepository
|
||||
* </p>
|
||||
|
@ -36,15 +36,14 @@ public class AuditEventService {
|
|||
this.auditEventConverter = auditEventConverter;
|
||||
}
|
||||
|
||||
public List<AuditEvent> findAll() {
|
||||
return auditEventConverter.convertToAuditEvent(persistenceAuditEventRepository.findAll());
|
||||
public Page<AuditEvent> findAll(Pageable pageable) {
|
||||
return persistenceAuditEventRepository.findAll(pageable)
|
||||
.map(persistentAuditEvents -> auditEventConverter.convertToAuditEvent(persistentAuditEvents));
|
||||
}
|
||||
|
||||
public List<AuditEvent> findByDates(LocalDateTime fromDate, LocalDateTime toDate) {
|
||||
List<PersistentAuditEvent> persistentAuditEvents =
|
||||
persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate);
|
||||
|
||||
return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
|
||||
public Page<AuditEvent> findByDates(LocalDateTime fromDate, LocalDateTime toDate, Pageable pageable) {
|
||||
return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable)
|
||||
.map(persistentAuditEvents -> auditEventConverter.convertToAuditEvent(persistentAuditEvents));
|
||||
}
|
||||
|
||||
public Optional<AuditEvent> find(Long id) {
|
||||
|
|
|
@ -22,7 +22,6 @@ import java.util.Locale;
|
|||
|
||||
/**
|
||||
* Service for sending e-mails.
|
||||
* <p/>
|
||||
* <p>
|
||||
* We use the @Async annotation to send e-mails asynchronously.
|
||||
* </p>
|
||||
|
|
|
@ -31,12 +31,14 @@ public class UserService {
|
|||
|
||||
private final Logger log = LoggerFactory.getLogger(UserService.class);
|
||||
|
||||
|
||||
@Inject
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Inject
|
||||
private UserRepository userRepository;
|
||||
|
||||
|
||||
@Inject
|
||||
private PersistentTokenRepository persistentTokenRepository;
|
||||
|
||||
|
@ -45,7 +47,7 @@ public class UserService {
|
|||
|
||||
public Optional<User> activateRegistration(String key) {
|
||||
log.debug("Activating user for activation key {}", key);
|
||||
userRepository.findOneByActivationKey(key)
|
||||
return userRepository.findOneByActivationKey(key)
|
||||
.map(user -> {
|
||||
// activate given user for the registration key.
|
||||
user.setActivated(true);
|
||||
|
@ -54,7 +56,6 @@ public class UserService {
|
|||
log.debug("Activated user: {}", user);
|
||||
return user;
|
||||
});
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
public Optional<User> completePasswordReset(String newPassword, String key) {
|
||||
|
@ -117,7 +118,7 @@ public class UserService {
|
|||
user.setLastName(managedUserDTO.getLastName());
|
||||
user.setEmail(managedUserDTO.getEmail());
|
||||
if (managedUserDTO.getLangKey() == null) {
|
||||
user.setLangKey("en"); // default language is English
|
||||
user.setLangKey("en"); // default language
|
||||
} else {
|
||||
user.setLangKey(managedUserDTO.getLangKey());
|
||||
}
|
||||
|
@ -139,7 +140,7 @@ public class UserService {
|
|||
}
|
||||
|
||||
public void updateUserInformation(String firstName, String lastName, String email, String langKey) {
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUser().getUsername()).ifPresent(u -> {
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).ifPresent(u -> {
|
||||
u.setFirstName(firstName);
|
||||
u.setLastName(lastName);
|
||||
u.setEmail(email);
|
||||
|
@ -157,7 +158,7 @@ public class UserService {
|
|||
}
|
||||
|
||||
public void changePassword(String password) {
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUser().getUsername()).ifPresent(u -> {
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).ifPresent(u -> {
|
||||
String encryptedPassword = passwordEncoder.encode(password);
|
||||
u.setPassword(encryptedPassword);
|
||||
userRepository.save(u);
|
||||
|
@ -182,7 +183,7 @@ public class UserService {
|
|||
|
||||
@Transactional(readOnly = true)
|
||||
public User getUserWithAuthorities() {
|
||||
User user = userRepository.findOneByLogin(SecurityUtils.getCurrentUser().getUsername()).get();
|
||||
User user = userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).get();
|
||||
user.getAuthorities().size(); // eagerly load the association
|
||||
return user;
|
||||
}
|
||||
|
@ -190,7 +191,6 @@ public class UserService {
|
|||
/**
|
||||
* Persistent Token are used for providing automatic authentication, they should be automatically deleted after
|
||||
* 30 days.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This is scheduled to get fired everyday, at midnight.
|
||||
* </p>
|
||||
|
@ -208,7 +208,6 @@ public class UserService {
|
|||
|
||||
/**
|
||||
* Not activated users should be automatically deleted after 3 days.
|
||||
* <p/>
|
||||
* <p>
|
||||
* This is scheduled to get fired everyday, at 01:00 (am).
|
||||
* </p>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package com.mycompany.myapp.web.filter;
|
||||
|
||||
import org.springframework.core.env.Environment;
|
||||
import com.mycompany.myapp.config.JHipsterProperties;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -15,18 +15,17 @@ public class CachingHttpHeadersFilter implements Filter {
|
|||
// We consider the last modified date is the start up time of the server
|
||||
private final static long LAST_MODIFIED = System.currentTimeMillis();
|
||||
|
||||
private long CACHE_TIME_TO_LIVE = TimeUnit.DAYS.toMillis(31L);
|
||||
private long CACHE_TIME_TO_LIVE = TimeUnit.DAYS.toMillis(1461L);
|
||||
|
||||
private Environment env;
|
||||
private JHipsterProperties jHipsterProperties;;
|
||||
|
||||
public CachingHttpHeadersFilter(Environment env) {
|
||||
this.env = env;
|
||||
public CachingHttpHeadersFilter(JHipsterProperties jHipsterProperties) {
|
||||
this.jHipsterProperties = jHipsterProperties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
CACHE_TIME_TO_LIVE = TimeUnit.DAYS.toMillis(env.getProperty("jhipster.http.cache.timeToLiveInDays",
|
||||
Long.class, 31L));
|
||||
CACHE_TIME_TO_LIVE = TimeUnit.DAYS.toMillis(jHipsterProperties.getHttp().getCache().getTimeToLiveInDays());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package com.mycompany.myapp.web.filter;
|
||||
|
||||
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* This filter is used in production, to serve static resources generated by "grunt build".
|
||||
* <p/>
|
||||
* <p>
|
||||
* It is configured to serve resources from the "dist" directory, which is the Grunt
|
||||
* destination directory.
|
||||
* </p>
|
||||
*/
|
||||
public class StaticResourcesProductionFilter implements Filter {
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
// Nothing to initialize
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
// Nothing to destroy
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
|
||||
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||
String contextPath = ((HttpServletRequest) request).getContextPath();
|
||||
String requestURI = httpRequest.getRequestURI();
|
||||
requestURI = StringUtils.substringAfter(requestURI, contextPath);
|
||||
if (StringUtils.equals("/", requestURI)) {
|
||||
requestURI = "/index.html";
|
||||
}
|
||||
String newURI = "/dist" + requestURI;
|
||||
request.getRequestDispatcher(newURI).forward(request, response);
|
||||
}
|
||||
}
|
|
@ -16,6 +16,7 @@ import com.mycompany.myapp.web.rest.util.HeaderUtil;
|
|||
import org.apache.commons.lang.StringUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
@ -50,17 +51,25 @@ public class AccountResource {
|
|||
private MailService mailService;
|
||||
|
||||
/**
|
||||
* POST /register -> register the user.
|
||||
* POST /register : register the user.
|
||||
*
|
||||
* @param userDTO the user DTO
|
||||
* @param request the HTTP request
|
||||
* @return the ResponseEntity with status 201 (Created) if the user is registred or 400 (Bad Request) if the login or e-mail is already in use
|
||||
*/
|
||||
@RequestMapping(value = "/register",
|
||||
method = RequestMethod.POST,
|
||||
produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
method = RequestMethod.POST,
|
||||
produces={MediaType.APPLICATION_JSON_VALUE, MediaType.TEXT_PLAIN_VALUE})
|
||||
@Timed
|
||||
public ResponseEntity<?> registerAccount(@Valid @RequestBody UserDTO userDTO, HttpServletRequest request) {
|
||||
|
||||
HttpHeaders textPlainHeaders = new HttpHeaders();
|
||||
textPlainHeaders.setContentType(MediaType.TEXT_PLAIN);
|
||||
|
||||
return userRepository.findOneByLogin(userDTO.getLogin())
|
||||
.map(user -> new ResponseEntity<>("login already in use", HttpStatus.BAD_REQUEST))
|
||||
.map(user -> new ResponseEntity<>("login already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
|
||||
.orElseGet(() -> userRepository.findOneByEmail(userDTO.getEmail())
|
||||
.map(user -> new ResponseEntity<>("e-mail address already in use", HttpStatus.BAD_REQUEST))
|
||||
.map(user -> new ResponseEntity<>("e-mail address already in use", textPlainHeaders, HttpStatus.BAD_REQUEST))
|
||||
.orElseGet(() -> {
|
||||
User user = userService.createUserInformation(userDTO.getLogin(), userDTO.getPassword(),
|
||||
userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail().toLowerCase(),
|
||||
|
@ -79,20 +88,26 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /activate -> activate the registered user.
|
||||
* GET /activate : activate the registered user.
|
||||
*
|
||||
* @param key the activation key
|
||||
* @return the ResponseEntity with status 200 (OK) and the activated user in body, or status 500 (Internal Server Error) if the user couldn't be activated
|
||||
*/
|
||||
@RequestMapping(value = "/activate",
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
public ResponseEntity<String> activateAccount(@RequestParam(value = "key") String key) {
|
||||
return Optional.ofNullable(userService.activateRegistration(key))
|
||||
return userService.activateRegistration(key)
|
||||
.map(user -> new ResponseEntity<String>(HttpStatus.OK))
|
||||
.orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /authenticate -> check if the user is authenticated, and return its login.
|
||||
* GET /authenticate : check if the user is authenticated, and return its login.
|
||||
*
|
||||
* @param request the HTTP request
|
||||
* @return the login if the user is authenticated
|
||||
*/
|
||||
@RequestMapping(value = "/authenticate",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -104,7 +119,9 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /account -> get the current user.
|
||||
* GET /account : get the current user.
|
||||
*
|
||||
* @return the ResponseEntity with status 200 (OK) and the current user in body, or status 500 (Internal Server Error) if the user couldn't be returned
|
||||
*/
|
||||
@RequestMapping(value = "/account",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -117,7 +134,10 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* POST /account -> update the current user information.
|
||||
* POST /account : update the current user information.
|
||||
*
|
||||
* @param userDTO the current user information
|
||||
* @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) or 500 (Internal Server Error) if the user couldn't be updated
|
||||
*/
|
||||
@RequestMapping(value = "/account",
|
||||
method = RequestMethod.POST,
|
||||
|
@ -129,7 +149,7 @@ public class AccountResource {
|
|||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("user-management", "emailexists", "Email already in use")).body(null);
|
||||
}
|
||||
return userRepository
|
||||
.findOneByLogin(SecurityUtils.getCurrentUser().getUsername())
|
||||
.findOneByLogin(SecurityUtils.getCurrentUserLogin())
|
||||
.map(u -> {
|
||||
userService.updateUserInformation(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(),
|
||||
userDTO.getLangKey());
|
||||
|
@ -139,11 +159,14 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* POST /change_password -> changes the current user's password
|
||||
* POST /account/change_password : changes the current user's password
|
||||
*
|
||||
* @param password the new password
|
||||
* @return the ResponseEntity with status 200 (OK), or status 400 (Bad Request) if the new password is not strong enough
|
||||
*/
|
||||
@RequestMapping(value = "/account/change_password",
|
||||
method = RequestMethod.POST,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@Timed
|
||||
public ResponseEntity<?> changePassword(@RequestBody String password) {
|
||||
if (!checkPasswordLength(password)) {
|
||||
|
@ -154,14 +177,17 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /account/sessions -> get the current open sessions.
|
||||
* GET /account/sessions : get the current open sessions.
|
||||
*
|
||||
* @return the ResponseEntity with status 200 (OK) and the current open sessions in body,
|
||||
* or status 500 (Internal Server Error) if the current open sessions couldn't be retrieved
|
||||
*/
|
||||
@RequestMapping(value = "/account/sessions",
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
public ResponseEntity<List<PersistentToken>> getCurrentSessions() {
|
||||
return userRepository.findOneByLogin(SecurityUtils.getCurrentUser().getUsername())
|
||||
return userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin())
|
||||
.map(user -> new ResponseEntity<>(
|
||||
persistentTokenRepository.findByUser(user),
|
||||
HttpStatus.OK))
|
||||
|
@ -169,7 +195,7 @@ public class AccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* DELETE /account/sessions?series={series} -> invalidate an existing session.
|
||||
* DELETE /account/sessions?series={series} : invalidate an existing session.
|
||||
*
|
||||
* - You can only delete your own sessions, not any other user's session
|
||||
* - If you delete one of your existing sessions, and that you are currently logged in on that session, you will
|
||||
|
@ -180,19 +206,29 @@ public class AccountResource {
|
|||
* anymore.
|
||||
* There is an API to invalidate the current session, but there is no API to check which session uses which
|
||||
* cookie.
|
||||
*
|
||||
* @param series the series of an existing session
|
||||
* @throws UnsupportedEncodingException if the series couldnt be URL decoded
|
||||
*/
|
||||
@RequestMapping(value = "/account/sessions/{series}",
|
||||
method = RequestMethod.DELETE)
|
||||
@Timed
|
||||
public void invalidateSession(@PathVariable String series) throws UnsupportedEncodingException {
|
||||
String decodedSeries = URLDecoder.decode(series, "UTF-8");
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUser().getUsername()).ifPresent(u -> {
|
||||
userRepository.findOneByLogin(SecurityUtils.getCurrentUserLogin()).ifPresent(u -> {
|
||||
persistentTokenRepository.findByUser(u).stream()
|
||||
.filter(persistentToken -> StringUtils.equals(persistentToken.getSeries(), decodedSeries))
|
||||
.findAny().ifPresent(t -> persistentTokenRepository.delete(decodedSeries));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /account/reset_password/init : Send an e-mail to reset the password of the user
|
||||
*
|
||||
* @param mail the mail of the user
|
||||
* @param request the HTTP request
|
||||
* @return the ResponseEntity with status 200 (OK) if the e-mail was sent, or status 400 (Bad Request) if the e-mail address is not registred
|
||||
*/
|
||||
@RequestMapping(value = "/account/reset_password/init",
|
||||
method = RequestMethod.POST,
|
||||
produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
|
@ -211,16 +247,24 @@ public class AccountResource {
|
|||
}).orElse(new ResponseEntity<>("e-mail address not registered", HttpStatus.BAD_REQUEST));
|
||||
}
|
||||
|
||||
/**
|
||||
* POST /account/reset_password/finish : Finish to reset the password of the user
|
||||
*
|
||||
* @param keyAndPassword the generated key and the new password
|
||||
* @return the ResponseEntity with status 200 (OK) if the password has been reset,
|
||||
* or status 400 (Bad Request) or 500 (Internal Server Error) if the password could not be reset
|
||||
*/
|
||||
@RequestMapping(value = "/account/reset_password/finish",
|
||||
method = RequestMethod.POST,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
produces = MediaType.TEXT_PLAIN_VALUE)
|
||||
@Timed
|
||||
public ResponseEntity<String> finishPasswordReset(@RequestBody KeyAndPasswordDTO keyAndPassword) {
|
||||
if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
|
||||
return new ResponseEntity<>("Incorrect password", HttpStatus.BAD_REQUEST);
|
||||
}
|
||||
return userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey())
|
||||
.map(user -> new ResponseEntity<String>(HttpStatus.OK)).orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
|
||||
.map(user -> new ResponseEntity<String>(HttpStatus.OK))
|
||||
.orElse(new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR));
|
||||
}
|
||||
|
||||
private boolean checkPasswordLength(String password) {
|
||||
|
|
|
@ -3,13 +3,18 @@ package com.mycompany.myapp.web.rest;
|
|||
import com.mycompany.myapp.service.AuditEventService;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import com.mycompany.myapp.web.rest.util.PaginationUtil;
|
||||
import org.springframework.boot.actuate.audit.AuditEvent;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.data.domain.Pageable;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
|
||||
import java.net.URISyntaxException;
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -27,20 +32,48 @@ public class AuditResource {
|
|||
this.auditEventService = auditEventService;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /audits : get a page of AuditEvents.
|
||||
*
|
||||
* @param pageable the pagination information
|
||||
* @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
|
||||
* @throws URISyntaxException if there is an error to generate the pagination HTTP headers
|
||||
*/
|
||||
@RequestMapping(method = RequestMethod.GET)
|
||||
public List<AuditEvent> getAll() {
|
||||
return auditEventService.findAll();
|
||||
public ResponseEntity<List<AuditEvent>> getAll(Pageable pageable) throws URISyntaxException {
|
||||
Page<AuditEvent> page = auditEventService.findAll(pageable);
|
||||
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/audits");
|
||||
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /audits : get a page of AuditEvents between the fromDate and toDate.
|
||||
*
|
||||
* @param fromDate the start of the time period of AuditEvents to get
|
||||
* @param toDate the end of the time period of AuditEvents to get
|
||||
* @param pageable the pagination information
|
||||
* @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
|
||||
* @throws URISyntaxException if there is an error to generate the pagination HTTP headers
|
||||
*/
|
||||
|
||||
@RequestMapping(method = RequestMethod.GET,
|
||||
params = {"fromDate", "toDate"})
|
||||
public List<AuditEvent> getByDates(
|
||||
public ResponseEntity<List<AuditEvent>> getByDates(
|
||||
@RequestParam(value = "fromDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate fromDate,
|
||||
@RequestParam(value = "toDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate toDate) {
|
||||
@RequestParam(value = "toDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) LocalDate toDate,
|
||||
Pageable pageable) throws URISyntaxException {
|
||||
|
||||
return auditEventService.findByDates(fromDate.atTime(0, 0), toDate.atTime(23, 59));
|
||||
Page<AuditEvent> page = auditEventService.findByDates(fromDate.atTime(0, 0), toDate.atTime(23, 59), pageable);
|
||||
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/audits");
|
||||
return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /audits/:id : get an AuditEvent by id.
|
||||
*
|
||||
* @param id the id of the entity to get
|
||||
* @return the ResponseEntity with status 200 (OK) and the AuditEvent in body, or status 404 (Not Found)
|
||||
*/
|
||||
@RequestMapping(value = "/{id:.+}",
|
||||
method = RequestMethod.GET)
|
||||
public ResponseEntity<AuditEvent> get(@PathVariable Long id) {
|
||||
|
|
|
@ -32,9 +32,13 @@ public class BankAccountResource {
|
|||
private BankAccountRepository bankAccountRepository;
|
||||
|
||||
/**
|
||||
* POST /bankAccounts -> Create a new bankAccount.
|
||||
* POST /bank-accounts : Create a new bankAccount.
|
||||
*
|
||||
* @param bankAccount the bankAccount to create
|
||||
* @return the ResponseEntity with status 201 (Created) and with body the new bankAccount, or with status 400 (Bad Request) if the bankAccount has already an ID
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/bankAccounts",
|
||||
@RequestMapping(value = "/bank-accounts",
|
||||
method = RequestMethod.POST,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
|
@ -44,15 +48,21 @@ public class BankAccountResource {
|
|||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("bankAccount", "idexists", "A new bankAccount cannot already have an ID")).body(null);
|
||||
}
|
||||
BankAccount result = bankAccountRepository.save(bankAccount);
|
||||
return ResponseEntity.created(new URI("/api/bankAccounts/" + result.getId()))
|
||||
return ResponseEntity.created(new URI("/api/bank-accounts/" + result.getId()))
|
||||
.headers(HeaderUtil.createEntityCreationAlert("bankAccount", result.getId().toString()))
|
||||
.body(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /bankAccounts -> Updates an existing bankAccount.
|
||||
* PUT /bank-accounts : Updates an existing bankAccount.
|
||||
*
|
||||
* @param bankAccount the bankAccount to update
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the updated bankAccount,
|
||||
* or with status 400 (Bad Request) if the bankAccount is not valid,
|
||||
* or with status 500 (Internal Server Error) if the bankAccount couldnt be updated
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/bankAccounts",
|
||||
@RequestMapping(value = "/bank-accounts",
|
||||
method = RequestMethod.PUT,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
|
@ -68,21 +78,27 @@ public class BankAccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /bankAccounts -> get all the bankAccounts.
|
||||
* GET /bank-accounts : get all the bankAccounts.
|
||||
*
|
||||
* @return the ResponseEntity with status 200 (OK) and the list of bankAccounts in body
|
||||
*/
|
||||
@RequestMapping(value = "/bankAccounts",
|
||||
@RequestMapping(value = "/bank-accounts",
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
public List<BankAccount> getAllBankAccounts() {
|
||||
log.debug("REST request to get all BankAccounts");
|
||||
return bankAccountRepository.findAll();
|
||||
}
|
||||
List<BankAccount> bankAccounts = bankAccountRepository.findAll();
|
||||
return bankAccounts;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /bankAccounts/:id -> get the "id" bankAccount.
|
||||
* GET /bank-accounts/:id : get the "id" bankAccount.
|
||||
*
|
||||
* @param id the id of the bankAccount to retrieve
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the bankAccount, or with status 404 (Not Found)
|
||||
*/
|
||||
@RequestMapping(value = "/bankAccounts/{id}",
|
||||
@RequestMapping(value = "/bank-accounts/{id}",
|
||||
method = RequestMethod.GET,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
|
@ -97,9 +113,12 @@ public class BankAccountResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* DELETE /bankAccounts/:id -> delete the "id" bankAccount.
|
||||
* DELETE /bank-accounts/:id : delete the "id" bankAccount.
|
||||
*
|
||||
* @param id the id of the bankAccount to delete
|
||||
* @return the ResponseEntity with status 200 (OK)
|
||||
*/
|
||||
@RequestMapping(value = "/bankAccounts/{id}",
|
||||
@RequestMapping(value = "/bank-accounts/{id}",
|
||||
method = RequestMethod.DELETE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
|
@ -108,4 +127,5 @@ public class BankAccountResource {
|
|||
bankAccountRepository.delete(id);
|
||||
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("bankAccount", id.toString())).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,7 +32,11 @@ public class LabelResource {
|
|||
private LabelRepository labelRepository;
|
||||
|
||||
/**
|
||||
* POST /labels -> Create a new label.
|
||||
* POST /labels : Create a new label.
|
||||
*
|
||||
* @param label the label to create
|
||||
* @return the ResponseEntity with status 201 (Created) and with body the new label, or with status 400 (Bad Request) if the label has already an ID
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/labels",
|
||||
method = RequestMethod.POST,
|
||||
|
@ -50,7 +54,13 @@ public class LabelResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* PUT /labels -> Updates an existing label.
|
||||
* PUT /labels : Updates an existing label.
|
||||
*
|
||||
* @param label the label to update
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the updated label,
|
||||
* or with status 400 (Bad Request) if the label is not valid,
|
||||
* or with status 500 (Internal Server Error) if the label couldnt be updated
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/labels",
|
||||
method = RequestMethod.PUT,
|
||||
|
@ -68,7 +78,9 @@ public class LabelResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /labels -> get all the labels.
|
||||
* GET /labels : get all the labels.
|
||||
*
|
||||
* @return the ResponseEntity with status 200 (OK) and the list of labels in body
|
||||
*/
|
||||
@RequestMapping(value = "/labels",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -76,11 +88,15 @@ public class LabelResource {
|
|||
@Timed
|
||||
public List<Label> getAllLabels() {
|
||||
log.debug("REST request to get all Labels");
|
||||
return labelRepository.findAll();
|
||||
}
|
||||
List<Label> labels = labelRepository.findAll();
|
||||
return labels;
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /labels/:id -> get the "id" label.
|
||||
* GET /labels/:id : get the "id" label.
|
||||
*
|
||||
* @param id the id of the label to retrieve
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the label, or with status 404 (Not Found)
|
||||
*/
|
||||
@RequestMapping(value = "/labels/{id}",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -97,7 +113,10 @@ public class LabelResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* DELETE /labels/:id -> delete the "id" label.
|
||||
* DELETE /labels/:id : delete the "id" label.
|
||||
*
|
||||
* @param id the id of the label to delete
|
||||
* @return the ResponseEntity with status 200 (OK)
|
||||
*/
|
||||
@RequestMapping(value = "/labels/{id}",
|
||||
method = RequestMethod.DELETE,
|
||||
|
@ -108,4 +127,5 @@ public class LabelResource {
|
|||
labelRepository.delete(id);
|
||||
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("label", id.toString())).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -35,7 +35,11 @@ public class OperationResource {
|
|||
private OperationRepository operationRepository;
|
||||
|
||||
/**
|
||||
* POST /operations -> Create a new operation.
|
||||
* POST /operations : Create a new operation.
|
||||
*
|
||||
* @param operation the operation to create
|
||||
* @return the ResponseEntity with status 201 (Created) and with body the new operation, or with status 400 (Bad Request) if the operation has already an ID
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/operations",
|
||||
method = RequestMethod.POST,
|
||||
|
@ -53,7 +57,13 @@ public class OperationResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* PUT /operations -> Updates an existing operation.
|
||||
* PUT /operations : Updates an existing operation.
|
||||
*
|
||||
* @param operation the operation to update
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the updated operation,
|
||||
* or with status 400 (Bad Request) if the operation is not valid,
|
||||
* or with status 500 (Internal Server Error) if the operation couldnt be updated
|
||||
* @throws URISyntaxException if the Location URI syntax is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/operations",
|
||||
method = RequestMethod.PUT,
|
||||
|
@ -71,7 +81,11 @@ public class OperationResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /operations -> get all the operations.
|
||||
* GET /operations : get all the operations.
|
||||
*
|
||||
* @param pageable the pagination information
|
||||
* @return the ResponseEntity with status 200 (OK) and the list of operations in body
|
||||
* @throws URISyntaxException if there is an error to generate the pagination HTTP headers
|
||||
*/
|
||||
@RequestMapping(value = "/operations",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -86,7 +100,10 @@ public class OperationResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /operations/:id -> get the "id" operation.
|
||||
* GET /operations/:id : get the "id" operation.
|
||||
*
|
||||
* @param id the id of the operation to retrieve
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the operation, or with status 404 (Not Found)
|
||||
*/
|
||||
@RequestMapping(value = "/operations/{id}",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -103,7 +120,10 @@ public class OperationResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* DELETE /operations/:id -> delete the "id" operation.
|
||||
* DELETE /operations/:id : delete the "id" operation.
|
||||
*
|
||||
* @param id the id of the operation to delete
|
||||
* @return the ResponseEntity with status 200 (OK)
|
||||
*/
|
||||
@RequestMapping(value = "/operations/{id}",
|
||||
method = RequestMethod.DELETE,
|
||||
|
@ -114,4 +134,5 @@ public class OperationResource {
|
|||
operationRepository.delete(id);
|
||||
return ResponseEntity.ok().headers(HeaderUtil.createEntityDeletionAlert("operation", id.toString())).build();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ import java.util.stream.Collectors;
|
|||
* but then all authorities come from the cache, so in fact it's much better than doing an outer join
|
||||
* (which will get lots of data from the database, for each HTTP call).</li>
|
||||
* <li> As this manages users, for security reasons, we'd rather have a DTO layer.</li>
|
||||
* </p>
|
||||
* </ul>
|
||||
* <p>Another option would be to have a specific JPA entity graph to handle this case.</p>
|
||||
*/
|
||||
@RestController
|
||||
|
@ -75,12 +75,17 @@ public class UserResource {
|
|||
private UserService userService;
|
||||
|
||||
/**
|
||||
* POST /users -> Creates a new user.
|
||||
* POST /users : Creates a new user.
|
||||
* <p>
|
||||
* Creates a new user if the login and email are not already used, and sends an
|
||||
* mail with an activation link.
|
||||
* The user needs to be activated on creation.
|
||||
* </p>
|
||||
*
|
||||
* @param managedUserDTO the user to create
|
||||
* @param request the HTTP request
|
||||
* @return the ResponseEntity with status 201 (Created) and with body the new user, or with status 400 (Bad Request) if the login or email is already in use
|
||||
* @throws URISyntaxException if the Location URI syntaxt is incorrect
|
||||
*/
|
||||
@RequestMapping(value = "/users",
|
||||
method = RequestMethod.POST,
|
||||
|
@ -91,11 +96,11 @@ public class UserResource {
|
|||
log.debug("REST request to save User : {}", managedUserDTO);
|
||||
if (userRepository.findOneByLogin(managedUserDTO.getLogin()).isPresent()) {
|
||||
return ResponseEntity.badRequest()
|
||||
.headers(HeaderUtil.createFailureAlert("user-management", "userexists", "Login already in use"))
|
||||
.headers(HeaderUtil.createFailureAlert("userManagement", "userexists", "Login already in use"))
|
||||
.body(null);
|
||||
} else if (userRepository.findOneByEmail(managedUserDTO.getEmail()).isPresent()) {
|
||||
return ResponseEntity.badRequest()
|
||||
.headers(HeaderUtil.createFailureAlert("user-management", "emailexists", "Email already in use"))
|
||||
.headers(HeaderUtil.createFailureAlert("userManagement", "emailexists", "Email already in use"))
|
||||
.body(null);
|
||||
} else {
|
||||
User newUser = userService.createUser(managedUserDTO);
|
||||
|
@ -107,13 +112,18 @@ public class UserResource {
|
|||
request.getContextPath(); // "/myContextPath" or "" if deployed in root context
|
||||
mailService.sendCreationEmail(newUser, baseUrl);
|
||||
return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin()))
|
||||
.headers(HeaderUtil.createAlert( "user-management.created", newUser.getLogin()))
|
||||
.headers(HeaderUtil.createAlert( "userManagement.created", newUser.getLogin()))
|
||||
.body(newUser);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* PUT /users -> Updates an existing User.
|
||||
* PUT /users : Updates an existing User.
|
||||
*
|
||||
* @param managedUserDTO the user to update
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the updated user,
|
||||
* or with status 400 (Bad Request) if the login or email is already in use,
|
||||
* or with status 500 (Internal Server Error) if the user couldnt be updated
|
||||
*/
|
||||
@RequestMapping(value = "/users",
|
||||
method = RequestMethod.PUT,
|
||||
|
@ -121,15 +131,15 @@ public class UserResource {
|
|||
@Timed
|
||||
@Transactional
|
||||
@Secured(AuthoritiesConstants.ADMIN)
|
||||
public ResponseEntity<ManagedUserDTO> updateUser(@RequestBody ManagedUserDTO managedUserDTO) throws URISyntaxException {
|
||||
public ResponseEntity<ManagedUserDTO> updateUser(@RequestBody ManagedUserDTO managedUserDTO) {
|
||||
log.debug("REST request to update User : {}", managedUserDTO);
|
||||
Optional<User> existingUser = userRepository.findOneByEmail(managedUserDTO.getEmail());
|
||||
if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserDTO.getId()))) {
|
||||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("user-management", "emailexists", "E-mail already in use")).body(null);
|
||||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("userManagement", "emailexists", "E-mail already in use")).body(null);
|
||||
}
|
||||
existingUser = userRepository.findOneByLogin(managedUserDTO.getLogin());
|
||||
if (existingUser.isPresent() && (!existingUser.get().getId().equals(managedUserDTO.getId()))) {
|
||||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("user-management", "userexists", "Login already in use")).body(null);
|
||||
return ResponseEntity.badRequest().headers(HeaderUtil.createFailureAlert("userManagement", "userexists", "Login already in use")).body(null);
|
||||
}
|
||||
return userRepository
|
||||
.findOneById(managedUserDTO.getId())
|
||||
|
@ -146,7 +156,7 @@ public class UserResource {
|
|||
authority -> authorities.add(authorityRepository.findOne(authority))
|
||||
);
|
||||
return ResponseEntity.ok()
|
||||
.headers(HeaderUtil.createAlert("user-management.updated", managedUserDTO.getLogin()))
|
||||
.headers(HeaderUtil.createAlert("userManagement.updated", managedUserDTO.getLogin()))
|
||||
.body(new ManagedUserDTO(userRepository
|
||||
.findOne(managedUserDTO.getId())));
|
||||
})
|
||||
|
@ -155,7 +165,11 @@ public class UserResource {
|
|||
}
|
||||
|
||||
/**
|
||||
* GET /users -> get all users.
|
||||
* GET /users : get all users.
|
||||
*
|
||||
* @param pageable the pagination information
|
||||
* @return the ResponseEntity with status 200 (OK) and with body all users
|
||||
* @throws URISyntaxException if the pagination headers couldnt be generated
|
||||
*/
|
||||
@RequestMapping(value = "/users",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -166,14 +180,17 @@ public class UserResource {
|
|||
throws URISyntaxException {
|
||||
Page<User> page = userRepository.findAll(pageable);
|
||||
List<ManagedUserDTO> managedUserDTOs = page.getContent().stream()
|
||||
.map(user -> new ManagedUserDTO(user))
|
||||
.map(ManagedUserDTO::new)
|
||||
.collect(Collectors.toList());
|
||||
HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users");
|
||||
return new ResponseEntity<>(managedUserDTOs, headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /users/:login -> get the "login" user.
|
||||
* GET /users/:login : get the "login" user.
|
||||
*
|
||||
* @param login the login of the user to find
|
||||
* @return the ResponseEntity with status 200 (OK) and with body the "login" user, or with status 404 (Not Found)
|
||||
*/
|
||||
@RequestMapping(value = "/users/{login:[_'.@a-z0-9-]+}",
|
||||
method = RequestMethod.GET,
|
||||
|
@ -187,9 +204,12 @@ public class UserResource {
|
|||
.orElse(new ResponseEntity<>(HttpStatus.NOT_FOUND));
|
||||
}
|
||||
/**
|
||||
* DELETE USER :login -> delete the "login" User.
|
||||
* DELETE USER :login : delete the "login" User.
|
||||
*
|
||||
* @param login the login of the user to delete
|
||||
* @return the ResponseEntity with status 200 (OK)
|
||||
*/
|
||||
@RequestMapping(value = "/users/{login}",
|
||||
@RequestMapping(value = "/users/{login:[_'.@a-z0-9-]+}",
|
||||
method = RequestMethod.DELETE,
|
||||
produces = MediaType.APPLICATION_JSON_VALUE)
|
||||
@Timed
|
||||
|
@ -197,6 +217,6 @@ public class UserResource {
|
|||
public ResponseEntity<Void> deleteUser(@PathVariable String login) {
|
||||
log.debug("REST request to delete User: {}", login);
|
||||
userService.deleteUserInformation(login);
|
||||
return ResponseEntity.ok().headers(HeaderUtil.createAlert( "user-management.deleted", login)).build();
|
||||
return ResponseEntity.ok().headers(HeaderUtil.createAlert( "userManagement.deleted", login)).build();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ import java.util.stream.Collectors;
|
|||
*/
|
||||
public class UserDTO {
|
||||
|
||||
public static final int PASSWORD_MIN_LENGTH = 5;
|
||||
public static final int PASSWORD_MIN_LENGTH = 4;
|
||||
public static final int PASSWORD_MAX_LENGTH = 100;
|
||||
|
||||
@Pattern(regexp = "^[a-z0-9]*$")
|
||||
|
|
|
@ -6,6 +6,7 @@ public final class ErrorConstants {
|
|||
public static final String ERR_ACCESS_DENIED = "error.accessDenied";
|
||||
public static final String ERR_VALIDATION = "error.validation";
|
||||
public static final String ERR_METHOD_NOT_SUPPORTED = "error.methodNotSupported";
|
||||
public static final String ERR_INTERNAL_SERVER_ERROR = "error.internalServerError";
|
||||
|
||||
private ErrorConstants() {
|
||||
}
|
||||
|
|
|
@ -16,16 +16,16 @@ public class ErrorDTO implements Serializable {
|
|||
|
||||
private List<FieldErrorDTO> fieldErrors;
|
||||
|
||||
ErrorDTO(String message) {
|
||||
public ErrorDTO(String message) {
|
||||
this(message, null);
|
||||
}
|
||||
|
||||
ErrorDTO(String message, String description) {
|
||||
public ErrorDTO(String message, String description) {
|
||||
this.message = message;
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
ErrorDTO(String message, String description, List<FieldErrorDTO> fieldErrors) {
|
||||
public ErrorDTO(String message, String description, List<FieldErrorDTO> fieldErrors) {
|
||||
this.message = message;
|
||||
this.description = description;
|
||||
this.fieldErrors = fieldErrors;
|
||||
|
|
|
@ -2,8 +2,11 @@ package com.mycompany.myapp.web.rest.errors;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.ResponseEntity.BodyBuilder;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.validation.FieldError;
|
||||
|
@ -64,4 +67,19 @@ public class ExceptionTranslator {
|
|||
public ErrorDTO processMethodNotSupportedException(HttpRequestMethodNotSupportedException exception) {
|
||||
return new ErrorDTO(ErrorConstants.ERR_METHOD_NOT_SUPPORTED, exception.getMessage());
|
||||
}
|
||||
|
||||
@ExceptionHandler(Exception.class)
|
||||
public ResponseEntity<ErrorDTO> processRuntimeException(Exception ex) throws Exception {
|
||||
BodyBuilder builder;
|
||||
ErrorDTO errorDTO;
|
||||
ResponseStatus responseStatus = AnnotationUtils.findAnnotation(ex.getClass(), ResponseStatus.class);
|
||||
if (responseStatus != null) {
|
||||
builder = ResponseEntity.status(responseStatus.value());
|
||||
errorDTO = new ErrorDTO("error." + responseStatus.value().value(), responseStatus.reason());
|
||||
} else {
|
||||
builder = ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
errorDTO = new ErrorDTO(ErrorConstants.ERR_INTERNAL_SERVER_ERROR, "Internal server error");
|
||||
}
|
||||
return builder.body(errorDTO);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ public class FieldErrorDTO implements Serializable {
|
|||
|
||||
private final String message;
|
||||
|
||||
FieldErrorDTO(String dto, String field, String message) {
|
||||
public FieldErrorDTO(String dto, String field, String message) {
|
||||
this.objectName = dto;
|
||||
this.field = field;
|
||||
this.message = message;
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
package com.mycompany.myapp.web.rest.mapper;
|
||||
|
||||
import com.mycompany.myapp.domain.Authority;
|
||||
import com.mycompany.myapp.domain.User;
|
||||
import com.mycompany.myapp.web.rest.dto.UserDTO;
|
||||
import org.mapstruct.*;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Mapper for the entity User and its DTO UserDTO.
|
||||
*/
|
||||
@Mapper(componentModel = "spring", uses = {})
|
||||
public interface UserMapper {
|
||||
|
||||
UserDTO userToUserDTO(User user);
|
||||
|
||||
List<UserDTO> usersToUserDTOs(List<User> users);
|
||||
|
||||
@Mapping(target = "createdBy", ignore = true)
|
||||
@Mapping(target = "createdDate", ignore = true)
|
||||
@Mapping(target = "lastModifiedBy", ignore = true)
|
||||
@Mapping(target = "lastModifiedDate", ignore = true)
|
||||
@Mapping(target = "persistentTokens", ignore = true)
|
||||
@Mapping(target = "id", ignore = true)
|
||||
@Mapping(target = "activationKey", ignore = true)
|
||||
@Mapping(target = "resetKey", ignore = true)
|
||||
@Mapping(target = "resetDate", ignore = true)
|
||||
User userDTOToUser(UserDTO userDTO);
|
||||
|
||||
List<User> userDTOsToUsers(List<UserDTO> userDTOs);
|
||||
|
||||
default User userFromId(Long id) {
|
||||
if (id == null) {
|
||||
return null;
|
||||
}
|
||||
User user = new User();
|
||||
user.setId(id);
|
||||
return user;
|
||||
}
|
||||
|
||||
default Set<String> stringsFromAuthorities (Set < Authority > authorities) {
|
||||
return authorities.stream().map(Authority::getName)
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
default Set<Authority> authoritiesFromStrings(Set<String> strings) {
|
||||
return strings.stream().map(string -> {
|
||||
Authority auth = new Authority();
|
||||
auth.setName(string);
|
||||
return auth;
|
||||
}).collect(Collectors.toSet());
|
||||
}
|
||||
}
|
|
@ -3,34 +3,34 @@ package com.mycompany.myapp.web.rest.util;
|
|||
import org.springframework.http.HttpHeaders;
|
||||
|
||||
/**
|
||||
* Utility class for http header creation.
|
||||
* Utility class for HTTP headers creation.
|
||||
*
|
||||
*/
|
||||
public class HeaderUtil {
|
||||
|
||||
public static HttpHeaders createAlert(String message, String param) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("X-sampleapplicationApp-alert", message);
|
||||
headers.add("X-sampleapplicationApp-params", param);
|
||||
headers.add("X-sampleApplicationApp-alert", message);
|
||||
headers.add("X-sampleApplicationApp-params", param);
|
||||
return headers;
|
||||
}
|
||||
|
||||
public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
|
||||
return createAlert("sampleapplicationApp." + entityName + ".created", param);
|
||||
return createAlert("sampleApplicationApp." + entityName + ".created", param);
|
||||
}
|
||||
|
||||
public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
|
||||
return createAlert("sampleapplicationApp." + entityName + ".updated", param);
|
||||
return createAlert("sampleApplicationApp." + entityName + ".updated", param);
|
||||
}
|
||||
|
||||
public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
|
||||
return createAlert("sampleapplicationApp." + entityName + ".deleted", param);
|
||||
return createAlert("sampleApplicationApp." + entityName + ".deleted", param);
|
||||
}
|
||||
|
||||
public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("X-sampleapplicationApp-error", "error." + errorKey);
|
||||
headers.add("X-sampleapplicationApp-params", entityName);
|
||||
headers.add("X-sampleApplicationApp-error", "error." + errorKey);
|
||||
headers.add("X-sampleApplicationApp-params", entityName);
|
||||
return headers;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ import java.net.URISyntaxException;
|
|||
* Utility class for handling pagination.
|
||||
*
|
||||
* <p>
|
||||
* Pagination uses the same principles as the <a href="https://developer.github.com/v3/#pagination">Github API</api>,
|
||||
* Pagination uses the same principles as the <a href="https://developer.github.com/v3/#pagination">Github API</a>,
|
||||
* and follow <a href="http://tools.ietf.org/html/rfc5988">RFC 5988 (Link header)</a>.
|
||||
* </p>
|
||||
*/
|
||||
public class PaginationUtil {
|
||||
|
||||
|
@ -23,19 +22,19 @@ public class PaginationUtil {
|
|||
headers.add("X-Total-Count", "" + page.getTotalElements());
|
||||
String link = "";
|
||||
if ((page.getNumber() + 1) < page.getTotalPages()) {
|
||||
link = "<" + (new URI(baseUrl +"?page=" + (page.getNumber() + 1) + "&size=" + page.getSize())).toString() + ">; rel=\"next\",";
|
||||
link = "<" + (new URI(baseUrl + "?page=" + (page.getNumber() + 1) + "&size=" + page.getSize())).toString() + ">; rel=\"next\",";
|
||||
}
|
||||
// prev link
|
||||
if ((page.getNumber()) > 0) {
|
||||
link += "<" + (new URI(baseUrl +"?page=" + (page.getNumber() - 1) + "&size=" + page.getSize())).toString() + ">; rel=\"prev\",";
|
||||
link += "<" + (new URI(baseUrl + "?page=" + (page.getNumber() - 1) + "&size=" + page.getSize())).toString() + ">; rel=\"prev\",";
|
||||
}
|
||||
// last and first link
|
||||
int lastPage = 0;
|
||||
if (page.getTotalPages() > 0) {
|
||||
lastPage = page.getTotalPages() - 1;
|
||||
}
|
||||
link += "<" + (new URI(baseUrl +"?page=" + lastPage + "&size=" + page.getSize())).toString() + ">; rel=\"last\",";
|
||||
link += "<" + (new URI(baseUrl +"?page=" + 0 + "&size=" + page.getSize())).toString() + ">; rel=\"first\"";
|
||||
link += "<" + (new URI(baseUrl + "?page=" + lastPage + "&size=" + page.getSize())).toString() + ">; rel=\"last\",";
|
||||
link += "<" + (new URI(baseUrl + "?page=" + 0 + "&size=" + page.getSize())).toString() + ">; rel=\"first\"";
|
||||
headers.add(HttpHeaders.LINK, link);
|
||||
return headers;
|
||||
}
|
||||
|
|
|
@ -10,16 +10,14 @@
|
|||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: dev
|
||||
devtools:
|
||||
restart:
|
||||
enabled: true
|
||||
livereload:
|
||||
enabled: false # we use Grunt + BrowserSync for livereload
|
||||
enabled: false # we use gulp + BrowserSync for livereload
|
||||
datasource:
|
||||
driver-class-name: org.h2.jdbcx.JdbcDataSource
|
||||
url: jdbc:h2:mem:sampleapplication;DB_CLOSE_DELAY=-1
|
||||
name:
|
||||
username: sampleApplication
|
||||
|
@ -71,3 +69,12 @@ jhipster:
|
|||
host: localhost
|
||||
port: 2003
|
||||
prefix: sampleApplication
|
||||
logs: # report metrics in the logs
|
||||
enabled: false
|
||||
reportFrequency: 60 # in seconds
|
||||
logging:
|
||||
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 5000
|
||||
queueSize: 512
|
||||
|
|
|
@ -10,20 +10,24 @@
|
|||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
|
||||
spring:
|
||||
profiles:
|
||||
active: prod
|
||||
devtools:
|
||||
restart:
|
||||
enabled: false
|
||||
livereload:
|
||||
enabled: false
|
||||
datasource:
|
||||
driver-class-name: com.mysql.jdbc.jdbc2.optional.MysqlDataSource
|
||||
url: jdbc:mysql://localhost:3306/sampleApplication?useUnicode=true&characterEncoding=utf8
|
||||
url: jdbc:mysql://localhost:3306/sampleApplication?useUnicode=true&characterEncoding=utf8&useSSL=false
|
||||
name:
|
||||
username: root
|
||||
password:
|
||||
hikari:
|
||||
data-source-properties:
|
||||
cachePrepStmts: true
|
||||
prepStmtCacheSize: 250
|
||||
prepStmtCacheSqlLimit: 2048
|
||||
useServerPrepStmts: true
|
||||
jpa:
|
||||
database-platform: org.hibernate.dialect.MySQLInnoDBDialect
|
||||
database: MYSQL
|
||||
|
@ -57,7 +61,7 @@ server:
|
|||
jhipster:
|
||||
http:
|
||||
cache: # Used by the CachingHttpHeadersFilter
|
||||
timeToLiveInDays: 31
|
||||
timeToLiveInDays: 1461
|
||||
cache: # Hibernate 2nd level cache, used by CacheConfiguration
|
||||
timeToLiveSeconds: 3600
|
||||
ehcache:
|
||||
|
@ -75,3 +79,12 @@ jhipster:
|
|||
host: localhost
|
||||
port: 2003
|
||||
prefix: sampleApplication
|
||||
logs: # report metrics in the logs
|
||||
enabled: false
|
||||
reportFrequency: 60 # in seconds
|
||||
logging:
|
||||
logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 5000
|
||||
queueSize: 512
|
||||
|
|
|
@ -11,14 +11,17 @@
|
|||
# http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html
|
||||
# ===================================================================
|
||||
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: sampleApplication
|
||||
jpa:
|
||||
open-in-view: false
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
naming-strategy: org.springframework.boot.orm.jpa.hibernate.SpringNamingStrategy
|
||||
messages:
|
||||
basename: classpath:/i18n/messages
|
||||
basename: i18n/messages
|
||||
mvc:
|
||||
favicon:
|
||||
enabled: false
|
||||
|
@ -48,7 +51,7 @@ jhipster:
|
|||
mail:
|
||||
from: sampleApplication@localhost
|
||||
security:
|
||||
rememberme:
|
||||
rememberMe:
|
||||
# security key (this key should be unique for your application, and kept secret)
|
||||
key: 5c37379956bd1242f5636c8cb322c2966ad81277
|
||||
swagger:
|
||||
|
@ -56,6 +59,8 @@ jhipster:
|
|||
description: sampleApplication API documentation
|
||||
version: 0.0.1
|
||||
termsOfServiceUrl:
|
||||
contact:
|
||||
contactName:
|
||||
contactUrl:
|
||||
contactEmail:
|
||||
license:
|
||||
licenseUrl:
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
The initial schema has the '00000000000001' id, so that it is over-written if we re-generate it.
|
||||
-->
|
||||
<changeSet id="00000000000001" author="jhipster">
|
||||
|
||||
<createTable tableName="jhi_user">
|
||||
<column name="id" type="bigint" autoIncrement="${autoIncrement}">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
|
@ -30,7 +31,7 @@
|
|||
<column name="first_name" type="varchar(50)"/>
|
||||
<column name="last_name" type="varchar(50)"/>
|
||||
<column name="email" type="varchar(100)">
|
||||
<constraints unique="true"/>
|
||||
<constraints unique="true" nullable="false"/>
|
||||
</column>
|
||||
<column name="activated" type="boolean" valueBoolean="false">
|
||||
<constraints nullable="false" />
|
||||
|
@ -110,7 +111,6 @@
|
|||
constraintName="fk_user_persistent_token"
|
||||
referencedColumnNames="id"
|
||||
referencedTableName="jhi_user"/>
|
||||
|
||||
<loadData encoding="UTF-8"
|
||||
file="config/liquibase/users.csv"
|
||||
separator=";"
|
||||
|
@ -129,7 +129,7 @@
|
|||
file="config/liquibase/users_authorities.csv"
|
||||
separator=";"
|
||||
tableName="jhi_user_authority"/>
|
||||
|
||||
|
||||
<createTable tableName="jhi_persistent_audit_event">
|
||||
<column name="event_id" type="bigint" autoIncrement="${autoIncrement}">
|
||||
<constraints primaryKey="true" nullable="false"/>
|
||||
|
|
|
@ -25,7 +25,9 @@
|
|||
<constraints nullable="false" />
|
||||
</column>
|
||||
|
||||
<column name="description" type="varchar(255)"/>
|
||||
<column name="description" type="varchar(255)">
|
||||
<constraints nullable="true" />
|
||||
</column>
|
||||
|
||||
<column name="amount" type="decimal(10,2)">
|
||||
<constraints nullable="false" />
|
||||
|
@ -35,14 +37,12 @@
|
|||
<!-- jhipster-needle-liquibase-add-column - Jhipster will add columns here, do not remove-->
|
||||
</createTable>
|
||||
<dropDefaultValue tableName="operation" columnName="date" columnDataType="datetime"/>
|
||||
|
||||
|
||||
<addForeignKeyConstraint baseColumnNames="bank_account_id"
|
||||
baseTableName="operation"
|
||||
constraintName="fk_operation_bankaccount_id"
|
||||
referencedColumnNames="id"
|
||||
referencedTableName="bank_account"/>
|
||||
|
||||
<createTable tableName="operation_label">
|
||||
<column name="labels_id" type="bigint">
|
||||
<constraints nullable="false"/>
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
# Error page
|
||||
error.title=Your request cannot be processed
|
||||
error.subtitle=Sorry, an error has occurred.
|
||||
error.status=Status:
|
||||
error.message=Message:
|
||||
|
||||
# Activation e-mail
|
||||
email.activation.title=sampleApplication account activation
|
||||
email.activation.greeting=Dear {0}
|
||||
email.activation.text1=Your sampleApplication account has been created, please click on the URL below to activate it:
|
||||
email.activation.text2=Regards,
|
||||
email.signature=sampleApplication Team.
|
||||
|
||||
# Creation email
|
||||
email.creation.text1=Your sampleApplication account has been created, please click on the URL below to access it:
|
||||
|
||||
# Reset e-mail
|
||||
email.reset.title=sampleApplication password reset
|
||||
email.reset.greeting=Dear {0}
|
||||
email.reset.text1=For your sampleApplication account a password reset was requested, please click on the URL below to reset it:
|
||||
email.reset.text2=Regards,
|
||||
|
|
@ -11,6 +11,9 @@ email.activation.text1=Your sampleApplication account has been created, please c
|
|||
email.activation.text2=Regards,
|
||||
email.signature=sampleApplication Team.
|
||||
|
||||
# Creation email
|
||||
email.creation.text1=Your sampleApplication account has been created, please click on the URL below to access it:
|
||||
|
||||
# Reset e-mail
|
||||
email.reset.title=sampleApplication password reset
|
||||
email.reset.greeting=Dear {0}
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
# Error page
|
||||
error.title=Votre demande ne peut être traitée
|
||||
error.subtitle=Désolé, une erreur s'est produite.
|
||||
error.status=Status:
|
||||
error.message=Message:
|
||||
|
||||
# Activation e-mail
|
||||
email.activation.title=Activation de votre compte sampleApplication
|
||||
email.activation.greeting=Cher {0}
|
||||
email.activation.text1=Votre compte sampleApplication a été créé, pour l'activer merci de cliquer sur le lien ci-dessous:
|
||||
email.activation.text2=Cordialement,
|
||||
email.signature=sampleApplication.
|
||||
|
||||
# Reset e-mail
|
||||
email.reset.title=sampleApplication Réinitialisation de mot de passe
|
||||
email.reset.greeting=Cher {0}
|
||||
email.reset.text1=Un nouveau mot de passe pour votre compte sampleApplication a été demandé, veuillez cliquer sur le lien ci-dessous pour le réinitialiser:
|
||||
email.reset.text2=Cordialement,
|
||||
|
|
@ -30,9 +30,8 @@
|
|||
<logger name="ch.qos.logback" level="WARN"/>
|
||||
<logger name="com.codahale.metrics" level="WARN"/>
|
||||
<logger name="com.ryantenney" level="WARN"/>
|
||||
<logger name="com.sun.xml.internal.bind" level="WARN"/>
|
||||
<logger name="com.sun" level="WARN"/>
|
||||
<logger name="com.zaxxer" level="WARN"/>
|
||||
<logger name="io.undertow" level="WARN"/>
|
||||
<logger name="net.sf.ehcache" level="WARN"/>
|
||||
<logger name="org.apache" level="WARN"/>
|
||||
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
<p th:text="#{email.activation.greeting(${user.login})}">
|
||||
Dear
|
||||
</p>
|
||||
<p th:text="#{email.activation.text1}">
|
||||
Your JHipster account has been created, please click on the URL below to activate it:
|
||||
<p th:text="#{email.creation.text1}">
|
||||
Your JHipster account has been created, please click on the URL below to access it:
|
||||
</p>
|
||||
<p>
|
||||
<a th:href="@{|${baseUrl}/#/reset/finish?key=${user.resetKey}|}"
|
||||
|
|
|
@ -1,543 +0,0 @@
|
|||
# Apache Configuration File
|
||||
|
||||
# (!) Using `.htaccess` files slows down Apache, therefore, if you have access
|
||||
# to the main server config file (usually called `httpd.conf`), you should add
|
||||
# this logic there: http://httpd.apache.org/docs/current/howto/htaccess.html.
|
||||
|
||||
# ##############################################################################
|
||||
# # CROSS-ORIGIN RESOURCE SHARING (CORS) #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Cross-domain AJAX requests |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Enable cross-origin AJAX requests.
|
||||
# http://code.google.com/p/html5security/wiki/CrossOriginRequestSecurity
|
||||
# http://enable-cors.org/
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set Access-Control-Allow-Origin "*"
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | CORS-enabled images |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Send the CORS header for images when browsers request it.
|
||||
# https://developer.mozilla.org/en/CORS_Enabled_Image
|
||||
# http://blog.chromium.org/2011/07/using-cross-domain-images-in-webgl-and.html
|
||||
# http://hacks.mozilla.org/2011/11/using-cors-to-load-webgl-textures-from-cross-domain-images/
|
||||
|
||||
<IfModule mod_setenvif.c>
|
||||
<IfModule mod_headers.c>
|
||||
<FilesMatch "\.(gif|ico|jpe?g|png|svg|svgz|webp)$">
|
||||
SetEnvIf Origin ":" IS_CORS
|
||||
Header set Access-Control-Allow-Origin "*" env=IS_CORS
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Web fonts access |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Allow access from all domains for web fonts
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
<FilesMatch "\.(eot|font.css|otf|ttc|ttf|woff)$">
|
||||
Header set Access-Control-Allow-Origin "*"
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # ERRORS #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | 404 error prevention for non-existing redirected folders |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Prevent Apache from returning a 404 error for a rewrite if a directory
|
||||
# with the same name does not exist.
|
||||
# http://httpd.apache.org/docs/current/content-negotiation.html#multiviews
|
||||
# http://www.webmasterworld.com/apache/3808792.htm
|
||||
|
||||
Options -MultiViews
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Custom error messages / pages |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# You can customize what Apache returns to the client in case of an error (see
|
||||
# http://httpd.apache.org/docs/current/mod/core.html#errordocument), e.g.:
|
||||
|
||||
ErrorDocument 404 /404.html
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # INTERNET EXPLORER #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Better website experience |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Force IE to render pages in the highest available mode in the various
|
||||
# cases when it may not: http://hsivonen.iki.fi/doctype/ie-mode.pdf.
|
||||
|
||||
<IfModule mod_headers.c>
|
||||
Header set X-UA-Compatible "IE=edge"
|
||||
# `mod_headers` can't match based on the content-type, however, we only
|
||||
# want to send this header for HTML pages and not for the other resources
|
||||
<FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$">
|
||||
Header unset X-UA-Compatible
|
||||
</FilesMatch>
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Cookie setting from iframes |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Allow cookies to be set from iframes in IE.
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set P3P "policyref=\"/w3c/p3p.xml\", CP=\"IDC DSP COR ADM DEVi TAIi PSA PSD IVAi IVDi CONi HIS OUR IND CNT\""
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Screen flicker |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Stop screen flicker in IE on CSS rollovers (this only works in
|
||||
# combination with the `ExpiresByType` directives for images from below).
|
||||
|
||||
# BrowserMatch "MSIE" brokenvary=1
|
||||
# BrowserMatch "Mozilla/4.[0-9]{2}" brokenvary=1
|
||||
# BrowserMatch "Opera" !brokenvary
|
||||
# SetEnvIf brokenvary 1 force-no-vary
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # MIME TYPES AND ENCODING #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Proper MIME types for all files |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
<IfModule mod_mime.c>
|
||||
|
||||
# Audio
|
||||
AddType audio/mp4 m4a f4a f4b
|
||||
AddType audio/ogg oga ogg
|
||||
|
||||
# JavaScript
|
||||
# Normalize to standard type (it's sniffed in IE anyways):
|
||||
# http://tools.ietf.org/html/rfc4329#section-7.2
|
||||
AddType application/javascript js jsonp
|
||||
AddType application/json json
|
||||
|
||||
# Video
|
||||
AddType video/mp4 mp4 m4v f4v f4p
|
||||
AddType video/ogg ogv
|
||||
AddType video/webm webm
|
||||
AddType video/x-flv flv
|
||||
|
||||
# Web fonts
|
||||
AddType application/font-woff woff
|
||||
AddType application/vnd.ms-fontobject eot
|
||||
|
||||
# Browsers usually ignore the font MIME types and sniff the content,
|
||||
# however, Chrome shows a warning if other MIME types are used for the
|
||||
# following fonts.
|
||||
AddType application/x-font-ttf ttc ttf
|
||||
AddType font/opentype otf
|
||||
|
||||
# Make SVGZ fonts work on iPad:
|
||||
# https://twitter.com/FontSquirrel/status/14855840545
|
||||
AddType image/svg+xml svg svgz
|
||||
AddEncoding gzip svgz
|
||||
|
||||
# Other
|
||||
AddType application/octet-stream safariextz
|
||||
AddType application/x-chrome-extension crx
|
||||
AddType application/x-opera-extension oex
|
||||
AddType application/x-shockwave-flash swf
|
||||
AddType application/x-web-app-manifest+json webapp
|
||||
AddType application/x-xpinstall xpi
|
||||
AddType application/xml atom rdf rss xml
|
||||
AddType image/webp webp
|
||||
AddType image/x-icon ico
|
||||
AddType text/cache-manifest appcache manifest
|
||||
AddType text/vtt vtt
|
||||
AddType text/x-component htc
|
||||
AddType text/x-vcard vcf
|
||||
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | UTF-8 encoding |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Use UTF-8 encoding for anything served as `text/html` or `text/plain`.
|
||||
AddDefaultCharset utf-8
|
||||
|
||||
# Force UTF-8 for certain file formats.
|
||||
<IfModule mod_mime.c>
|
||||
AddCharset utf-8 .atom .css .js .json .rss .vtt .webapp .xml
|
||||
</IfModule>
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # URL REWRITES #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Rewrite engine |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Turning on the rewrite engine and enabling the `FollowSymLinks` option is
|
||||
# necessary for the following directives to work.
|
||||
|
||||
# If your web host doesn't allow the `FollowSymlinks` option, you may need to
|
||||
# comment it out and use `Options +SymLinksIfOwnerMatch` but, be aware of the
|
||||
# performance impact: http://httpd.apache.org/docs/current/misc/perf-tuning.html#symlinks
|
||||
|
||||
# Also, some cloud hosting services require `RewriteBase` to be set:
|
||||
# http://www.rackspace.com/knowledge_center/frequently-asked-question/why-is-mod-rewrite-not-working-on-my-site
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
Options +FollowSymlinks
|
||||
# Options +SymLinksIfOwnerMatch
|
||||
RewriteEngine On
|
||||
# RewriteBase /
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Suppressing / Forcing the "www." at the beginning of URLs |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# The same content should never be available under two different URLs especially
|
||||
# not with and without "www." at the beginning. This can cause SEO problems
|
||||
# (duplicate content), therefore, you should choose one of the alternatives and
|
||||
# redirect the other one.
|
||||
|
||||
# By default option 1 (no "www.") is activated:
|
||||
# http://no-www.org/faq.php?q=class_b
|
||||
|
||||
# If you'd prefer to use option 2, just comment out all the lines from option 1
|
||||
# and uncomment the ones from option 2.
|
||||
|
||||
# IMPORTANT: NEVER USE BOTH RULES AT THE SAME TIME!
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Option 1: rewrite www.example.com → example.com
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteCond %{HTTPS} !=on
|
||||
RewriteCond %{HTTP_HOST} ^www\.(.+)$ [NC]
|
||||
RewriteRule ^ http://%1%{REQUEST_URI} [R=301,L]
|
||||
</IfModule>
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Option 2: rewrite example.com → www.example.com
|
||||
|
||||
# Be aware that the following might not be a good idea if you use "real"
|
||||
# subdomains for certain parts of your website.
|
||||
|
||||
# <IfModule mod_rewrite.c>
|
||||
# RewriteCond %{HTTPS} !=on
|
||||
# RewriteCond %{HTTP_HOST} !^www\..+$ [NC]
|
||||
# RewriteRule ^ http://www.%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
|
||||
# </IfModule>
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # SECURITY #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Content Security Policy (CSP) |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# You can mitigate the risk of cross-site scripting and other content-injection
|
||||
# attacks by setting a Content Security Policy which whitelists trusted sources
|
||||
# of content for your site.
|
||||
|
||||
# The example header below allows ONLY scripts that are loaded from the current
|
||||
# site's origin (no inline scripts, no CDN, etc). This almost certainly won't
|
||||
# work as-is for your site!
|
||||
|
||||
# To get all the details you'll need to craft a reasonable policy for your site,
|
||||
# read: http://html5rocks.com/en/tutorials/security/content-security-policy (or
|
||||
# see the specification: http://w3.org/TR/CSP).
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set Content-Security-Policy "script-src 'self'; object-src 'self'"
|
||||
# <FilesMatch "\.(appcache|crx|css|eot|gif|htc|ico|jpe?g|js|m4a|m4v|manifest|mp4|oex|oga|ogg|ogv|otf|pdf|png|safariextz|svg|svgz|ttf|vcf|webapp|webm|webp|woff|xml|xpi)$">
|
||||
# Header unset Content-Security-Policy
|
||||
# </FilesMatch>
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | File access |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Block access to directories without a default document.
|
||||
# Usually you should leave this uncommented because you shouldn't allow anyone
|
||||
# to surf through every directory on your server (which may includes rather
|
||||
# private places like the CMS's directories).
|
||||
|
||||
<IfModule mod_autoindex.c>
|
||||
Options -Indexes
|
||||
</IfModule>
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Block access to hidden files and directories.
|
||||
# This includes directories used by version control systems such as Git and SVN.
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteCond %{SCRIPT_FILENAME} -d [OR]
|
||||
RewriteCond %{SCRIPT_FILENAME} -f
|
||||
RewriteRule "(^|/)\." - [F]
|
||||
</IfModule>
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Block access to backup and source files.
|
||||
# These files may be left by some text editors and can pose a great security
|
||||
# danger when anyone has access to them.
|
||||
|
||||
<FilesMatch "(^#.*#|\.(bak|config|dist|fla|inc|ini|log|psd|sh|sql|sw[op])|~)$">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
Satisfy All
|
||||
</FilesMatch>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Secure Sockets Layer (SSL) |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Rewrite secure requests properly to prevent SSL certificate warnings, e.g.:
|
||||
# prevent `https://www.example.com` when your certificate only allows
|
||||
# `https://secure.example.com`.
|
||||
|
||||
# <IfModule mod_rewrite.c>
|
||||
# RewriteCond %{SERVER_PORT} !^443
|
||||
# RewriteRule ^ https://example-domain-please-change-me.com%{REQUEST_URI} [R=301,L]
|
||||
# </IfModule>
|
||||
|
||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||
|
||||
# Force client-side SSL redirection.
|
||||
|
||||
# If a user types "example.com" in his browser, the above rule will redirect him
|
||||
# to the secure version of the site. That still leaves a window of opportunity
|
||||
# (the initial HTTP connection) for an attacker to downgrade or redirect the
|
||||
# request. The following header ensures that browser will ONLY connect to your
|
||||
# server via HTTPS, regardless of what the users type in the address bar.
|
||||
# http://www.html5rocks.com/en/tutorials/security/transport-layer-security/
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set Strict-Transport-Security max-age=16070400;
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Server software information |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Avoid displaying the exact Apache version number, the description of the
|
||||
# generic OS-type and the information about Apache's compiled-in modules.
|
||||
|
||||
# ADD THIS DIRECTIVE IN THE `httpd.conf` AS IT WILL NOT WORK IN THE `.htaccess`!
|
||||
|
||||
# ServerTokens Prod
|
||||
|
||||
|
||||
# ##############################################################################
|
||||
# # WEB PERFORMANCE #
|
||||
# ##############################################################################
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Compression |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
<IfModule mod_deflate.c>
|
||||
|
||||
# Force compression for mangled headers.
|
||||
# http://developer.yahoo.com/blogs/ydn/posts/2010/12/pushing-beyond-gzipping
|
||||
<IfModule mod_setenvif.c>
|
||||
<IfModule mod_headers.c>
|
||||
SetEnvIfNoCase ^(Accept-EncodXng|X-cept-Encoding|X{15}|~{15}|-{15})$ ^((gzip|deflate)\s*,?\s*)+|[X~-]{4,13}$ HAVE_Accept-Encoding
|
||||
RequestHeader append Accept-Encoding "gzip,deflate" env=HAVE_Accept-Encoding
|
||||
</IfModule>
|
||||
</IfModule>
|
||||
|
||||
# Compress all output labeled with one of the following MIME-types
|
||||
# (for Apache versions below 2.3.7, you don't need to enable `mod_filter`
|
||||
# and can remove the `<IfModule mod_filter.c>` and `</IfModule>` lines
|
||||
# as `AddOutputFilterByType` is still in the core directives).
|
||||
<IfModule mod_filter.c>
|
||||
AddOutputFilterByType DEFLATE application/atom+xml \
|
||||
application/javascript \
|
||||
application/json \
|
||||
application/rss+xml \
|
||||
application/vnd.ms-fontobject \
|
||||
application/x-font-ttf \
|
||||
application/x-web-app-manifest+json \
|
||||
application/xhtml+xml \
|
||||
application/xml \
|
||||
font/opentype \
|
||||
image/svg+xml \
|
||||
image/x-icon \
|
||||
text/css \
|
||||
text/html \
|
||||
text/plain \
|
||||
text/x-component \
|
||||
text/xml
|
||||
</IfModule>
|
||||
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Content transformations |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Prevent some of the mobile network providers from modifying the content of
|
||||
# your site: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9.5.
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set Cache-Control "no-transform"
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | ETag removal |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Since we're sending far-future expires headers (see below), ETags can
|
||||
# be removed: http://developer.yahoo.com/performance/rules.html#etags.
|
||||
|
||||
# `FileETag None` is not enough for every server.
|
||||
<IfModule mod_headers.c>
|
||||
Header unset ETag
|
||||
</IfModule>
|
||||
|
||||
FileETag None
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Expires headers (for better cache control) |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# The following expires headers are set pretty far in the future. If you don't
|
||||
# control versioning with filename-based cache busting, consider lowering the
|
||||
# cache time for resources like CSS and JS to something like 1 week.
|
||||
|
||||
<IfModule mod_expires.c>
|
||||
|
||||
ExpiresActive on
|
||||
ExpiresDefault "access plus 1 month"
|
||||
|
||||
# CSS
|
||||
ExpiresByType text/css "access plus 1 year"
|
||||
|
||||
# Data interchange
|
||||
ExpiresByType application/json "access plus 0 seconds"
|
||||
ExpiresByType application/xml "access plus 0 seconds"
|
||||
ExpiresByType text/xml "access plus 0 seconds"
|
||||
|
||||
# Favicon (cannot be renamed!)
|
||||
ExpiresByType image/x-icon "access plus 1 week"
|
||||
|
||||
# HTML components (HTCs)
|
||||
ExpiresByType text/x-component "access plus 1 month"
|
||||
|
||||
# HTML
|
||||
ExpiresByType text/html "access plus 0 seconds"
|
||||
|
||||
# JavaScript
|
||||
ExpiresByType application/javascript "access plus 1 year"
|
||||
|
||||
# Manifest files
|
||||
ExpiresByType application/x-web-app-manifest+json "access plus 0 seconds"
|
||||
ExpiresByType text/cache-manifest "access plus 0 seconds"
|
||||
|
||||
# Media
|
||||
ExpiresByType audio/ogg "access plus 1 month"
|
||||
ExpiresByType image/gif "access plus 1 month"
|
||||
ExpiresByType image/jpeg "access plus 1 month"
|
||||
ExpiresByType image/png "access plus 1 month"
|
||||
ExpiresByType video/mp4 "access plus 1 month"
|
||||
ExpiresByType video/ogg "access plus 1 month"
|
||||
ExpiresByType video/webm "access plus 1 month"
|
||||
|
||||
# Web feeds
|
||||
ExpiresByType application/atom+xml "access plus 1 hour"
|
||||
ExpiresByType application/rss+xml "access plus 1 hour"
|
||||
|
||||
# Web fonts
|
||||
ExpiresByType application/font-woff "access plus 1 month"
|
||||
ExpiresByType application/vnd.ms-fontobject "access plus 1 month"
|
||||
ExpiresByType application/x-font-ttf "access plus 1 month"
|
||||
ExpiresByType font/opentype "access plus 1 month"
|
||||
ExpiresByType image/svg+xml "access plus 1 month"
|
||||
|
||||
</IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Filename-based cache busting |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# If you're not using a build process to manage your filename version revving,
|
||||
# you might want to consider enabling the following directives to route all
|
||||
# requests such as `/css/style.12345.css` to `/css/style.css`.
|
||||
|
||||
# To understand why this is important and a better idea than `*.css?v231`, read:
|
||||
# http://stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring
|
||||
|
||||
# <IfModule mod_rewrite.c>
|
||||
# RewriteCond %{REQUEST_FILENAME} !-f
|
||||
# RewriteCond %{REQUEST_FILENAME} !-d
|
||||
# RewriteRule ^(.+)\.(\d+)\.(js|css|png|jpg|gif)$ $1.$3 [L]
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | File concatenation |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Allow concatenation from within specific CSS and JS files, e.g.:
|
||||
# Inside of `script.combined.js` you could have
|
||||
# <!--#include file="libs/jquery.js" -->
|
||||
# <!--#include file="plugins/jquery.idletimer.js" -->
|
||||
# and they would be included into this single file.
|
||||
|
||||
# <IfModule mod_include.c>
|
||||
# <FilesMatch "\.combined\.js$">
|
||||
# Options +Includes
|
||||
# AddOutputFilterByType INCLUDES application/javascript application/json
|
||||
# SetOutputFilter INCLUDES
|
||||
# </FilesMatch>
|
||||
# <FilesMatch "\.combined\.css$">
|
||||
# Options +Includes
|
||||
# AddOutputFilterByType INCLUDES text/css
|
||||
# SetOutputFilter INCLUDES
|
||||
# </FilesMatch>
|
||||
# </IfModule>
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# | Persistent connections |
|
||||
# ------------------------------------------------------------------------------
|
||||
|
||||
# Allow multiple requests to be sent over the same TCP connection:
|
||||
# http://httpd.apache.org/docs/current/en/mod/core.html#keepalive.
|
||||
|
||||
# Enable if you serve a lot of static content but, be aware of the
|
||||
# possible disadvantages!
|
||||
|
||||
# <IfModule mod_headers.c>
|
||||
# Header set Connection Keep-Alive
|
||||
# </IfModule>
|
|
@ -0,0 +1,16 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('account', {
|
||||
abstract: true,
|
||||
parent: 'app'
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,23 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('ActivationController', ActivationController);
|
||||
|
||||
ActivationController.$inject = ['$stateParams', 'Auth', 'LoginService'];
|
||||
|
||||
function ActivationController ($stateParams, Auth, LoginService) {
|
||||
var vm = this;
|
||||
|
||||
Auth.activateAccount({key: $stateParams.key}).then(function () {
|
||||
vm.error = null;
|
||||
vm.success = 'OK';
|
||||
}).catch(function () {
|
||||
vm.success = null;
|
||||
vm.error = 'ERROR';
|
||||
});
|
||||
|
||||
vm.login = LoginService.open;
|
||||
}
|
||||
})();
|
|
@ -3,11 +3,11 @@
|
|||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1 translate="activate.title">Activation</h1>
|
||||
|
||||
<div class="alert alert-success" ng-show="success" translate="activate.messages.success">
|
||||
<strong>Your user has been activated.</strong> Please <a class="alert-link" href="#/login">sign in</a>.
|
||||
<div class="alert alert-success" ng-show="vm.success" translate="activate.messages.success" translate-compile>
|
||||
<strong>Your user has been activated.</strong> Please <a class="alert-link" href="" ng-click="vm.login">sign in</a>.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="error" translate="activate.messages.error">
|
||||
<div class="alert alert-danger" ng-show="vm.error" translate="activate.messages.error">
|
||||
<strong>Your user could not be activated.</strong> Please use the registration form to sign up.
|
||||
</div>
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('activate', {
|
||||
parent: 'account',
|
||||
url: '/activate?key',
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'activate.title'
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/activate/activate.html',
|
||||
controller: 'ActivationController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('activate');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,95 @@
|
|||
/* globals $ */
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.directive('passwordStrengthBar', passwordStrengthBar);
|
||||
|
||||
function passwordStrengthBar () {
|
||||
var directive = {
|
||||
replace: true,
|
||||
restrict: 'E',
|
||||
template: '<div id="strength">' +
|
||||
'<small translate="global.messages.validate.newpassword.strength">Password strength:</small>' +
|
||||
'<ul id="strengthBar">' +
|
||||
'<li class="point"></li><li class="point"></li><li class="point"></li><li class="point"></li><li class="point"></li>' +
|
||||
'</ul>' +
|
||||
'</div>',
|
||||
scope: {
|
||||
passwordToCheck: '='
|
||||
},
|
||||
link: linkFunc
|
||||
};
|
||||
|
||||
return directive;
|
||||
|
||||
/* private helper methods*/
|
||||
|
||||
function linkFunc(scope, iElement) {
|
||||
var strength = {
|
||||
colors: ['#F00', '#F90', '#FF0', '#9F0', '#0F0'],
|
||||
mesureStrength: function (p) {
|
||||
|
||||
var _force = 0;
|
||||
var _regex = /[$-/:-?{-~!"^_`\[\]]/g; // "
|
||||
|
||||
var _lowerLetters = /[a-z]+/.test(p);
|
||||
var _upperLetters = /[A-Z]+/.test(p);
|
||||
var _numbers = /[0-9]+/.test(p);
|
||||
var _symbols = _regex.test(p);
|
||||
|
||||
var _flags = [_lowerLetters, _upperLetters, _numbers, _symbols];
|
||||
var _passedMatches = $.grep(_flags, function (el) {
|
||||
return el === true;
|
||||
}).length;
|
||||
|
||||
_force += 2 * p.length + ((p.length >= 10) ? 1 : 0);
|
||||
_force += _passedMatches * 10;
|
||||
|
||||
// penality (short password)
|
||||
_force = (p.length <= 6) ? Math.min(_force, 10) : _force;
|
||||
|
||||
// penality (poor variety of characters)
|
||||
_force = (_passedMatches === 1) ? Math.min(_force, 10) : _force;
|
||||
_force = (_passedMatches === 2) ? Math.min(_force, 20) : _force;
|
||||
_force = (_passedMatches === 3) ? Math.min(_force, 40) : _force;
|
||||
|
||||
return _force;
|
||||
|
||||
},
|
||||
getColor: function (s) {
|
||||
|
||||
var idx = 0;
|
||||
if (s <= 10) {
|
||||
idx = 0;
|
||||
}
|
||||
else if (s <= 20) {
|
||||
idx = 1;
|
||||
}
|
||||
else if (s <= 30) {
|
||||
idx = 2;
|
||||
}
|
||||
else if (s <= 40) {
|
||||
idx = 3;
|
||||
}
|
||||
else {
|
||||
idx = 4;
|
||||
}
|
||||
|
||||
return { idx: idx + 1, col: this.colors[idx] };
|
||||
}
|
||||
};
|
||||
scope.$watch('passwordToCheck', function (password) {
|
||||
if (password) {
|
||||
var c = strength.getColor(strength.mesureStrength(password));
|
||||
iElement.removeClass('ng-hide');
|
||||
iElement.find('ul').children('li')
|
||||
.css({ 'background-color': '#DDD' })
|
||||
.slice(0, c.idx)
|
||||
.css({ 'background-color': c.col });
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,39 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('PasswordController', PasswordController);
|
||||
|
||||
PasswordController.$inject = ['Auth', 'Principal'];
|
||||
|
||||
function PasswordController (Auth, Principal) {
|
||||
var vm = this;
|
||||
|
||||
vm.changePassword = changePassword;
|
||||
vm.doNotMatch = null;
|
||||
vm.error = null;
|
||||
vm.success = null;
|
||||
|
||||
Principal.identity().then(function(account) {
|
||||
vm.account = account;
|
||||
});
|
||||
|
||||
function changePassword () {
|
||||
if (vm.password !== vm.confirmPassword) {
|
||||
vm.error = null;
|
||||
vm.success = null;
|
||||
vm.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
vm.doNotMatch = null;
|
||||
Auth.changePassword(vm.password).then(function () {
|
||||
vm.error = null;
|
||||
vm.success = 'OK';
|
||||
}).catch(function () {
|
||||
vm.success = null;
|
||||
vm.error = 'ERROR';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -1,25 +1,25 @@
|
|||
<div>
|
||||
<div class="row">
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<h2 translate="password.title" translate-values="{username: '{{account.login}}'}">Password for [<b>{{account.login}}</b>]</h2>
|
||||
<h2 translate="password.title" translate-values="{username: '{{vm.account.login}}'}">Password for [<b>{{vm.account.login}}</b>]</h2>
|
||||
|
||||
<div class="alert alert-success" ng-show="success" translate="password.messages.success">
|
||||
<div class="alert alert-success" ng-show="vm.success" translate="password.messages.success">
|
||||
<strong>Password changed!</strong>
|
||||
</div>
|
||||
<div class="alert alert-danger" ng-show="error" translate="password.messages.error">
|
||||
<div class="alert alert-danger" ng-show="vm.error" translate="password.messages.error">
|
||||
<strong>An error has occurred!</strong> The password could not be changed.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="doNotMatch" translate="global.messages.error.dontmatch">
|
||||
<div class="alert alert-danger" ng-show="vm.doNotMatch" translate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
|
||||
<form name="form" role="form" novalidate ng-submit="changePassword()" show-validation>
|
||||
<form name="form" role="form" novalidate ng-submit="vm.changePassword()" show-validation>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="password" translate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
ng-model="password" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.password" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.password.$dirty && form.password.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.password.$error.required" translate="global.messages.validate.newpassword.required">
|
||||
|
@ -34,12 +34,12 @@
|
|||
Your password cannot be longer than 50 characters.
|
||||
</p>
|
||||
</div>
|
||||
<password-strength-bar password-to-check="password"></password-strength-bar>
|
||||
<password-strength-bar password-to-check="vm.password"></password-strength-bar>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="confirmPassword" translate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
ng-model="confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.confirmPassword.$dirty && form.confirmPassword.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.confirmPassword.$error.required" translate="global.messages.validate.confirmpassword.required">
|
|
@ -0,0 +1,33 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('password', {
|
||||
parent: 'account',
|
||||
url: '/password',
|
||||
data: {
|
||||
authorities: ['ROLE_USER'],
|
||||
pageTitle: 'global.menu.account.password'
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/password/password.html',
|
||||
controller: 'PasswordController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('password');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,49 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('RegisterController', RegisterController);
|
||||
|
||||
|
||||
RegisterController.$inject = ['$translate', '$timeout', 'Auth', 'LoginService'];
|
||||
|
||||
function RegisterController ($translate, $timeout, Auth, LoginService) {
|
||||
var vm = this;
|
||||
|
||||
vm.doNotMatch = null;
|
||||
vm.error = null;
|
||||
vm.errorUserExists = null;
|
||||
vm.login = LoginService.open;
|
||||
vm.register = register;
|
||||
vm.registerAccount = {};
|
||||
vm.success = null;
|
||||
|
||||
$timeout(function (){angular.element('[ng-model="vm.registerAccount.login"]').focus();});
|
||||
|
||||
function register () {
|
||||
if (vm.registerAccount.password !== vm.confirmPassword) {
|
||||
vm.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
vm.registerAccount.langKey = $translate.use();
|
||||
vm.doNotMatch = null;
|
||||
vm.error = null;
|
||||
vm.errorUserExists = null;
|
||||
vm.errorEmailExists = null;
|
||||
|
||||
Auth.createAccount(vm.registerAccount).then(function () {
|
||||
vm.success = 'OK';
|
||||
}).catch(function (response) {
|
||||
vm.success = null;
|
||||
if (response.status === 400 && response.data === 'login already in use') {
|
||||
vm.errorUserExists = 'ERROR';
|
||||
} else if (response.status === 400 && response.data === 'e-mail address already in use') {
|
||||
vm.errorEmailExists = 'ERROR';
|
||||
} else {
|
||||
vm.error = 'ERROR';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -3,33 +3,33 @@
|
|||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1 translate="register.title">Registration</h1>
|
||||
|
||||
<div class="alert alert-success" ng-show="success" translate="register.messages.success">
|
||||
<div class="alert alert-success" ng-show="vm.success" translate="register.messages.success">
|
||||
<strong>Registration saved!</strong> Please check your email for confirmation.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="error" translate="register.messages.error.fail">
|
||||
<div class="alert alert-danger" ng-show="vm.error" translate="register.messages.error.fail">
|
||||
<strong>Registration failed!</strong> Please try again later.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="errorUserExists" translate="register.messages.error.userexists">
|
||||
<div class="alert alert-danger" ng-show="vm.errorUserExists" translate="register.messages.error.userexists">
|
||||
<strong>Login name already registered!</strong> Please choose another one.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="errorEmailExists" translate="register.messages.error.emailexists">
|
||||
<div class="alert alert-danger" ng-show="vm.errorEmailExists" translate="register.messages.error.emailexists">
|
||||
<strong>E-mail is already in use!</strong> Please choose another one.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="doNotMatch" translate="global.messages.error.dontmatch">
|
||||
<div class="alert alert-danger" ng-show="vm.doNotMatch" translate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-2">
|
||||
<form ng-show="!success" name="form" role="form" novalidate ng-submit="register()" show-validation>
|
||||
<form ng-show="!vm.success" name="form" role="form" novalidate ng-submit="vm.register()" show-validation>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="login" translate="global.form.username">Username</label>
|
||||
<input type="text" class="form-control" id="login" name="login" placeholder="{{'global.form.username.placeholder' | translate}}"
|
||||
ng-model="registerAccount.login" ng-minlength=1 ng-maxlength=50 ng-pattern="/^[a-z0-9]*$/" required>
|
||||
ng-model="vm.registerAccount.login" ng-minlength=1 ng-maxlength=50 ng-pattern="/^[a-z0-9]*$/" required>
|
||||
<div ng-show="form.login.$dirty && form.login.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.login.$error.required" translate="register.messages.validate.login.required">
|
||||
|
@ -52,7 +52,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label" for="email" translate="global.form.email">E-mail</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="{{'global.form.email.placeholder' | translate}}"
|
||||
ng-model="registerAccount.email" ng-minlength=5 ng-maxlength=100 required>
|
||||
ng-model="vm.registerAccount.email" ng-minlength=5 ng-maxlength=100 required>
|
||||
<div ng-show="form.email.$dirty && form.email.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.email.$error.required" translate="global.messages.validate.email.required">
|
||||
|
@ -75,7 +75,7 @@
|
|||
<div class="form-group">
|
||||
<label class="control-label" for="password" translate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
ng-model="registerAccount.password" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.registerAccount.password" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.password.$dirty && form.password.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.password.$error.required" translate="global.messages.validate.newpassword.required">
|
||||
|
@ -90,12 +90,12 @@
|
|||
Your password cannot be longer than 50 characters.
|
||||
</p>
|
||||
</div>
|
||||
<password-strength-bar password-to-check="registerAccount.password"></password-strength-bar>
|
||||
<password-strength-bar password-to-check="vm.registerAccount.password"></password-strength-bar>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="confirmPassword" translate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
ng-model="confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.confirmPassword.$dirty && form.confirmPassword.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.confirmPassword.$error.required" translate="global.messages.validate.confirmpassword.required">
|
||||
|
@ -115,8 +115,8 @@
|
|||
<button type="submit" ng-disabled="form.$invalid" class="btn btn-primary" translate="register.form.button">Register</button>
|
||||
</form>
|
||||
<p></p>
|
||||
<div class="alert alert-warning" translate="global.messages.info.authenticated">
|
||||
If you want to <a class="alert-link" href="#/login">sign in</a>, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").
|
||||
<div class="alert alert-warning" translate="global.messages.info.authenticated" translate-compile>
|
||||
If you want to <a class="alert-link" href="" ng-click="login()">sign in</a>, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,33 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('register', {
|
||||
parent: 'account',
|
||||
url: '/register',
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'register.title'
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/register/register.html',
|
||||
controller: 'RegisterController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('register');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,37 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('ResetFinishController', ResetFinishController);
|
||||
|
||||
ResetFinishController.$inject = ['$stateParams', '$timeout', 'Auth', 'LoginService'];
|
||||
|
||||
function ResetFinishController ($stateParams, $timeout, Auth, LoginService) {
|
||||
var vm = this;
|
||||
|
||||
vm.keyMissing = angular.isUndefined($stateParams.key);
|
||||
vm.confirmPassword = null;
|
||||
vm.doNotMatch = null;
|
||||
vm.error = null;
|
||||
vm.finishReset = finishReset;
|
||||
vm.login = LoginService.open;
|
||||
vm.resetAccount = {};
|
||||
vm.success = null;
|
||||
|
||||
$timeout(function (){angular.element('[ng-model="vm.resetAccount.password"]').focus();});
|
||||
|
||||
function finishReset() {
|
||||
if (vm.resetAccount.password !== vm.confirmPassword) {
|
||||
vm.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
Auth.resetPasswordFinish({key: $stateParams.key, newPassword: vm.resetAccount.password}).then(function () {
|
||||
vm.success = 'OK';
|
||||
}).catch(function () {
|
||||
vm.success = null;
|
||||
vm.error = 'ERROR';
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -3,32 +3,32 @@
|
|||
<div class="col-md-4 col-md-offset-4">
|
||||
<h1 translate="reset.finish.title">Reset password</h1>
|
||||
|
||||
<div class="alert alert-danger" translate="reset.finish.messages.keymissing" ng-show="keyMissing">
|
||||
<div class="alert alert-danger" translate="reset.finish.messages.keymissing" ng-show="vm.keyMissing">
|
||||
<strong>The password reset key is missing.</strong>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" ng-hide="success || keyMissing">
|
||||
<div class="alert alert-warning" ng-hide="vm.success || vm.keyMissing">
|
||||
<p translate="reset.finish.messages.info">Choose a new password</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="error">
|
||||
<div class="alert alert-danger" ng-show="vm.error">
|
||||
<p translate="reset.finish.messages.error">Your password couldn't be reset. Remember a password request is only valid for 24 hours.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" ng-show="success">
|
||||
<p translate="reset.finish.messages.success"><strong>Your password has been reset.</strong> Please <a class="alert-link" href="#/login">sign in</a>.</p>
|
||||
<div class="alert alert-success" ng-show="vm.success">
|
||||
<p translate="reset.finish.messages.success" translate-compile><strong>Your password has been reset.</strong> Please <a class="alert-link" href="" ng-click="login">sign in</a>.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" ng-show="doNotMatch" translate="global.messages.error.dontmatch">
|
||||
<div class="alert alert-danger" ng-show="vm.doNotMatch" translate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
|
||||
<div ng-hide="keyMissing">
|
||||
<form ng-show="!success" name="form" role="form" novalidate ng-submit="finishReset()" show-validation>
|
||||
<div ng-hide="vm.keyMissing">
|
||||
<form ng-show="!vm.success" name="form" role="form" novalidate ng-submit="vm.finishReset()" show-validation>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="password" translate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
ng-model="resetAccount.password" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.resetAccount.password" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.password.$dirty && form.password.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.password.$error.required" translate="global.messages.validate.newpassword.required">
|
||||
|
@ -43,13 +43,13 @@
|
|||
Your password cannot be longer than 50 characters.
|
||||
</p>
|
||||
</div>
|
||||
<password-strength-bar password-to-check="resetAccount.password"></password-strength-bar>
|
||||
<password-strength-bar password-to-check="vm.resetAccount.password"></password-strength-bar>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="confirmPassword" translate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
ng-model="confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
ng-model="vm.confirmPassword" ng-minlength=5 ng-maxlength=50 required>
|
||||
<div ng-show="form.confirmPassword.$dirty && form.confirmPassword.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.confirmPassword.$error.required" translate="global.messages.validate.confirmpassword.required">
|
|
@ -0,0 +1,32 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('finishReset', {
|
||||
parent: 'account',
|
||||
url: '/reset/finish?key',
|
||||
data: {
|
||||
authorities: []
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/reset/finish/reset.finish.html',
|
||||
controller: 'ResetFinishController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('reset');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,38 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('RequestResetController', RequestResetController);
|
||||
|
||||
RequestResetController.$inject = ['$timeout', 'Auth'];
|
||||
|
||||
function RequestResetController ($timeout, Auth) {
|
||||
var vm = this;
|
||||
|
||||
vm.error = null;
|
||||
vm.errorEmailNotExists = null;
|
||||
vm.requestReset = requestReset;
|
||||
vm.resetAccount = {};
|
||||
vm.success = null;
|
||||
|
||||
$timeout(function (){angular.element('[ng-model="resetAccount.email"]').focus();});
|
||||
|
||||
function requestReset () {
|
||||
|
||||
vm.error = null;
|
||||
vm.errorEmailNotExists = null;
|
||||
|
||||
Auth.resetPasswordInit(vm.resetAccount.email).then(function () {
|
||||
vm.success = 'OK';
|
||||
}).catch(function (response) {
|
||||
vm.success = null;
|
||||
if (response.status === 400 && response.data === 'e-mail address not registered') {
|
||||
vm.errorEmailNotExists = 'ERROR';
|
||||
} else {
|
||||
vm.error = 'ERROR';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -3,23 +3,23 @@
|
|||
<div class="col-md-8 col-md-offset-2">
|
||||
<h1 translate="reset.request.title">Reset your password</h1>
|
||||
|
||||
<div class="alert alert-danger" translate="reset.request.messages.notfound" ng-show="errorEmailNotExists">
|
||||
<div class="alert alert-danger" translate="reset.request.messages.notfound" ng-show="vm.errorEmailNotExists">
|
||||
<strong>E-Mail address isn't registered!</strong> Please check and try again.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" ng-hide="success">
|
||||
<div class="alert alert-warning" ng-hide="vm.success">
|
||||
<p translate="reset.request.messages.info">Enter the e-mail address you used to register.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" ng-show="success == 'OK'">
|
||||
<div class="alert alert-success" ng-show="vm.success == 'OK'">
|
||||
<p translate="reset.request.messages.success">Check your e-mails for details on how to reset your password.</p>
|
||||
</div>
|
||||
|
||||
<form ng-show="!success" name="form" role="form" novalidate ng-submit="requestReset()" show-validation>
|
||||
<form ng-show="!vm.success" name="form" role="form" novalidate ng-submit="vm.requestReset()" show-validation>
|
||||
<div class="form-group">
|
||||
<label class="control-label" for="email" translate="global.form.email">E-mail</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="{{'global.form.email.placeholder' | translate}}"
|
||||
ng-model="resetAccount.email" ng-minlength=5 ng-maxlength=100 required>
|
||||
ng-model="vm.resetAccount.email" ng-minlength=5 ng-maxlength=100 required>
|
||||
<div ng-show="form.email.$dirty && form.email.$invalid">
|
||||
<p class="help-block"
|
||||
ng-show="form.email.$error.required" translate="global.messages.validate.email.required">
|
|
@ -0,0 +1,32 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('requestReset', {
|
||||
parent: 'account',
|
||||
url: '/reset/request',
|
||||
data: {
|
||||
authorities: []
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/reset/request/reset.request.html',
|
||||
controller: 'RequestResetController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('reset');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
|
@ -0,0 +1,37 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.controller('SessionsController', SessionsController);
|
||||
|
||||
SessionsController.$inject = ['Sessions', 'Principal'];
|
||||
|
||||
function SessionsController (Sessions, Principal) {
|
||||
var vm = this;
|
||||
|
||||
vm.account = null;
|
||||
vm.error = null;
|
||||
vm.invalidate = invalidate;
|
||||
vm.sessions = Sessions.getAll();
|
||||
vm.success = null;
|
||||
|
||||
|
||||
Principal.identity().then(function(account) {
|
||||
vm.account = account;
|
||||
});
|
||||
|
||||
function invalidate (series) {
|
||||
Sessions.delete({series: encodeURIComponent(series)},
|
||||
function () {
|
||||
vm.error = null;
|
||||
vm.success = 'OK';
|
||||
vm.sessions = Sessions.getAll();
|
||||
},
|
||||
function () {
|
||||
vm.success = null;
|
||||
vm.error = 'ERROR';
|
||||
});
|
||||
}
|
||||
}
|
||||
})();
|
|
@ -1,11 +1,11 @@
|
|||
<div>
|
||||
|
||||
<h2 translate="sessions.title" translate-values="{username: '{{account.login}}'}">Active sessions for [<b>{{account.login}}</b>]</h2>
|
||||
<h2 translate="sessions.title" translate-values="{username: '{{vm.account.login}}'}">Active sessions for [<b>{{vm.account.login}}</b>]</h2>
|
||||
|
||||
<div class="alert alert-success" ng-show="success" translate="sessions.messages.success">
|
||||
<div class="alert alert-success" ng-show="vm.success" translate="sessions.messages.success">
|
||||
<strong>Session invalidated!</strong>
|
||||
</div>
|
||||
<div class="alert alert-danger" ng-show="error" translate="sessions.messages.error">
|
||||
<div class="alert alert-danger" ng-show="vm.error" translate="sessions.messages.error">
|
||||
<strong>An error has occured!</strong> The session could not be invalidated.
|
||||
</div>
|
||||
|
||||
|
@ -20,14 +20,14 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-repeat="session in sessions">
|
||||
<tr ng-repeat="session in vm.sessions">
|
||||
<td>{{session.ipAddress}}</td>
|
||||
<td>{{session.userAgent}}</td>
|
||||
<td>{{session.formattedTokenDate}}</td>
|
||||
<td>
|
||||
<button type="submit"
|
||||
class="btn btn-primary"
|
||||
ng-click="invalidate(session.series)" translate="sessions.table.button">
|
||||
ng-click="vm.invalidate(session.series)" translate="sessions.table.button">
|
||||
Invalidate
|
||||
</button>
|
||||
</td>
|
|
@ -0,0 +1,33 @@
|
|||
(function() {
|
||||
'use strict';
|
||||
|
||||
angular
|
||||
.module('sampleApplicationApp')
|
||||
.config(stateConfig);
|
||||
|
||||
stateConfig.$inject = ['$stateProvider'];
|
||||
|
||||
function stateConfig($stateProvider) {
|
||||
$stateProvider.state('sessions', {
|
||||
parent: 'account',
|
||||
url: '/sessions',
|
||||
data: {
|
||||
authorities: ['ROLE_USER'],
|
||||
pageTitle: 'global.menu.account.sessions'
|
||||
},
|
||||
views: {
|
||||
'content@': {
|
||||
templateUrl: 'app/account/sessions/sessions.html',
|
||||
controller: 'SessionsController',
|
||||
controllerAs: 'vm'
|
||||
}
|
||||
},
|
||||
resolve: {
|
||||
translatePartialLoader: ['$translate', '$translatePartialLoader', function ($translate, $translatePartialLoader) {
|
||||
$translatePartialLoader.addPart('sessions');
|
||||
return $translate.refresh();
|
||||
}]
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue