Procházet zdrojové kódy

Initial application generated by JHipster-5.7.0

Lauren Green před 5 roky
rodič
revize
cead2f089a
100 změnil soubory, kde provedl 26491 přidání a 1 odebrání
  1. 24
    0
      .editorconfig
  2. 149
    0
      .gitattributes
  3. 144
    1
      .gitignore
  4. 5
    0
      .huskyrc
  5. 110
    0
      .mvn/wrapper/MavenWrapperDownloader.java
  6. binární
      .mvn/wrapper/maven-wrapper.jar
  7. 1
    0
      .mvn/wrapper/maven-wrapper.properties
  8. 2
    0
      .prettierignore
  9. 12
    0
      .prettierrc
  10. 41
    0
      .yo-rc.json
  11. 100
    0
      README.md
  12. 39
    0
      angular.json
  13. 286
    0
      mvnw
  14. 161
    0
      mvnw.cmd
  15. 19707
    0
      package-lock.json
  16. 139
    0
      package.json
  17. 1126
    0
      pom.xml
  18. 5
    0
      postcss.config.js
  19. 7
    0
      proxy.conf.json
  20. 14
    0
      src/main/docker/.dockerignore
  21. 20
    0
      src/main/docker/Dockerfile
  22. 24
    0
      src/main/docker/app.yml
  23. 7
    0
      src/main/docker/central-server-config/README.md
  24. 15
    0
      src/main/docker/central-server-config/docker-config/application.yml
  25. 15
    0
      src/main/docker/central-server-config/localhost-config/application.yml
  26. 4
    0
      src/main/docker/entrypoint.sh
  27. 6
    0
      src/main/docker/hazelcast-management-center.yml
  28. 22
    0
      src/main/docker/jhipster-registry.yml
  29. 13
    0
      src/main/docker/mysql.yml
  30. 7
    0
      src/main/docker/sonar.yml
  31. 21
    0
      src/main/java/rocks/zipcode/io/ApplicationWebXml.java
  32. 100
    0
      src/main/java/rocks/zipcode/io/ZipConnectApp.java
  33. 98
    0
      src/main/java/rocks/zipcode/io/aop/logging/LoggingAspect.java
  34. 14
    0
      src/main/java/rocks/zipcode/io/config/ApplicationProperties.java
  35. 59
    0
      src/main/java/rocks/zipcode/io/config/AsyncConfiguration.java
  36. 155
    0
      src/main/java/rocks/zipcode/io/config/CacheConfiguration.java
  37. 29
    0
      src/main/java/rocks/zipcode/io/config/CloudDatabaseConfiguration.java
  38. 17
    0
      src/main/java/rocks/zipcode/io/config/Constants.java
  39. 60
    0
      src/main/java/rocks/zipcode/io/config/DatabaseConfiguration.java
  40. 20
    0
      src/main/java/rocks/zipcode/io/config/DateTimeFormatConfiguration.java
  41. 51
    0
      src/main/java/rocks/zipcode/io/config/DefaultProfileUtil.java
  42. 63
    0
      src/main/java/rocks/zipcode/io/config/JacksonConfiguration.java
  43. 53
    0
      src/main/java/rocks/zipcode/io/config/LiquibaseConfiguration.java
  44. 27
    0
      src/main/java/rocks/zipcode/io/config/LocaleConfiguration.java
  45. 19
    0
      src/main/java/rocks/zipcode/io/config/LoggingAspectConfiguration.java
  46. 158
    0
      src/main/java/rocks/zipcode/io/config/LoggingConfiguration.java
  47. 119
    0
      src/main/java/rocks/zipcode/io/config/MetricsConfiguration.java
  48. 121
    0
      src/main/java/rocks/zipcode/io/config/SecurityConfiguration.java
  49. 206
    0
      src/main/java/rocks/zipcode/io/config/WebConfigurer.java
  50. 86
    0
      src/main/java/rocks/zipcode/io/config/audit/AuditEventConverter.java
  51. 4
    0
      src/main/java/rocks/zipcode/io/config/audit/package-info.java
  52. 4
    0
      src/main/java/rocks/zipcode/io/config/package-info.java
  53. 79
    0
      src/main/java/rocks/zipcode/io/domain/AbstractAuditingEntity.java
  54. 62
    0
      src/main/java/rocks/zipcode/io/domain/Authority.java
  55. 109
    0
      src/main/java/rocks/zipcode/io/domain/PersistentAuditEvent.java
  56. 233
    0
      src/main/java/rocks/zipcode/io/domain/User.java
  57. 4
    0
      src/main/java/rocks/zipcode/io/domain/package-info.java
  58. 11
    0
      src/main/java/rocks/zipcode/io/repository/AuthorityRepository.java
  59. 89
    0
      src/main/java/rocks/zipcode/io/repository/CustomAuditEventRepository.java
  60. 25
    0
      src/main/java/rocks/zipcode/io/repository/PersistenceAuditEventRepository.java
  61. 47
    0
      src/main/java/rocks/zipcode/io/repository/UserRepository.java
  62. 4
    0
      src/main/java/rocks/zipcode/io/repository/package-info.java
  63. 16
    0
      src/main/java/rocks/zipcode/io/security/AuthoritiesConstants.java
  64. 62
    0
      src/main/java/rocks/zipcode/io/security/DomainUserDetailsService.java
  65. 76
    0
      src/main/java/rocks/zipcode/io/security/SecurityUtils.java
  66. 20
    0
      src/main/java/rocks/zipcode/io/security/SpringSecurityAuditorAware.java
  67. 19
    0
      src/main/java/rocks/zipcode/io/security/UserNotActivatedException.java
  68. 21
    0
      src/main/java/rocks/zipcode/io/security/jwt/JWTConfigurer.java
  69. 48
    0
      src/main/java/rocks/zipcode/io/security/jwt/JWTFilter.java
  70. 119
    0
      src/main/java/rocks/zipcode/io/security/jwt/TokenProvider.java
  71. 4
    0
      src/main/java/rocks/zipcode/io/security/package-info.java
  72. 51
    0
      src/main/java/rocks/zipcode/io/service/AuditEventService.java
  73. 105
    0
      src/main/java/rocks/zipcode/io/service/MailService.java
  74. 293
    0
      src/main/java/rocks/zipcode/io/service/UserService.java
  75. 35
    0
      src/main/java/rocks/zipcode/io/service/dto/PasswordChangeDTO.java
  76. 199
    0
      src/main/java/rocks/zipcode/io/service/dto/UserDTO.java
  77. 4
    0
      src/main/java/rocks/zipcode/io/service/dto/package-info.java
  78. 76
    0
      src/main/java/rocks/zipcode/io/service/mapper/UserMapper.java
  79. 4
    0
      src/main/java/rocks/zipcode/io/service/mapper/package-info.java
  80. 4
    0
      src/main/java/rocks/zipcode/io/service/package-info.java
  81. 41
    0
      src/main/java/rocks/zipcode/io/service/util/RandomUtil.java
  82. 189
    0
      src/main/java/rocks/zipcode/io/web/rest/AccountResource.java
  83. 77
    0
      src/main/java/rocks/zipcode/io/web/rest/AuditResource.java
  84. 39
    0
      src/main/java/rocks/zipcode/io/web/rest/LogsResource.java
  85. 73
    0
      src/main/java/rocks/zipcode/io/web/rest/UserJWTController.java
  86. 190
    0
      src/main/java/rocks/zipcode/io/web/rest/UserResource.java
  87. 42
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/BadRequestAlertException.java
  88. 54
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/CustomParameterizedException.java
  89. 10
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/EmailAlreadyUsedException.java
  90. 13
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/EmailNotFoundException.java
  91. 21
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/ErrorConstants.java
  92. 107
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/ExceptionTranslator.java
  93. 33
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/FieldErrorVM.java
  94. 16
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/InternalServerErrorException.java
  95. 13
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/InvalidPasswordException.java
  96. 10
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/LoginAlreadyUsedException.java
  97. 6
    0
      src/main/java/rocks/zipcode/io/web/rest/errors/package-info.java
  98. 4
    0
      src/main/java/rocks/zipcode/io/web/rest/package-info.java
  99. 45
    0
      src/main/java/rocks/zipcode/io/web/rest/util/HeaderUtil.java
  100. 0
    0
      src/main/java/rocks/zipcode/io/web/rest/util/PaginationUtil.java

+ 24
- 0
.editorconfig Zobrazit soubor

@@ -0,0 +1,24 @@
1
+# EditorConfig helps developers define and maintain consistent
2
+# coding styles between different editors and IDEs
3
+# editorconfig.org
4
+
5
+root = true
6
+
7
+[*]
8
+
9
+# Change these settings to your own preference
10
+indent_style = space
11
+indent_size = 4
12
+
13
+# We recommend you to keep these unchanged
14
+end_of_line = lf
15
+charset = utf-8
16
+trim_trailing_whitespace = true
17
+insert_final_newline = true
18
+
19
+[*.md]
20
+trim_trailing_whitespace = false
21
+
22
+[{package,bower}.json]
23
+indent_style = space
24
+indent_size = 2

+ 149
- 0
.gitattributes Zobrazit soubor

@@ -0,0 +1,149 @@
1
+# This file is inspired by https://github.com/alexkaratarakis/gitattributes
2
+#
3
+# Auto detect text files and perform LF normalization
4
+# http://davidlaing.com/2012/09/19/customise-your-gitattributes-to-become-a-git-ninja/
5
+* text=auto
6
+
7
+# The above will handle all files NOT found below
8
+# These files are text and should be normalized (Convert crlf => lf)
9
+
10
+*.bat           text eol=crlf
11
+*.coffee        text
12
+*.css           text
13
+*.cql           text
14
+*.df            text
15
+*.ejs           text
16
+*.html          text
17
+*.java          text
18
+*.js            text
19
+*.json          text
20
+*.less          text
21
+*.properties    text
22
+*.sass          text
23
+*.scss          text
24
+*.sh            text eol=lf
25
+*.sql           text
26
+*.txt           text
27
+*.ts            text
28
+*.xml           text
29
+*.yaml          text
30
+*.yml           text
31
+
32
+# Documents
33
+*.doc           diff=astextplain
34
+*.DOC           diff=astextplain
35
+*.docx          diff=astextplain
36
+*.DOCX          diff=astextplain
37
+*.dot           diff=astextplain
38
+*.DOT           diff=astextplain
39
+*.pdf           diff=astextplain
40
+*.PDF           diff=astextplain
41
+*.rtf           diff=astextplain
42
+*.RTF           diff=astextplain
43
+*.markdown      text
44
+*.md            text
45
+*.adoc          text
46
+*.textile       text
47
+*.mustache      text
48
+*.csv           text
49
+*.tab           text
50
+*.tsv           text
51
+*.txt           text
52
+AUTHORS         text
53
+CHANGELOG       text
54
+CHANGES         text
55
+CONTRIBUTING    text
56
+COPYING         text
57
+copyright       text
58
+*COPYRIGHT*     text
59
+INSTALL         text
60
+license         text
61
+LICENSE         text
62
+NEWS            text
63
+readme          text
64
+*README*        text
65
+TODO            text
66
+
67
+# Graphics
68
+*.png           binary
69
+*.jpg           binary
70
+*.jpeg          binary
71
+*.gif           binary
72
+*.tif           binary
73
+*.tiff          binary
74
+*.ico           binary
75
+# SVG treated as an asset (binary) by default. If you want to treat it as text,
76
+# comment-out the following line and uncomment the line after.
77
+*.svg           binary
78
+#*.svg          text
79
+*.eps           binary
80
+
81
+# These files are binary and should be left untouched
82
+# (binary is a macro for -text -diff)
83
+*.class         binary
84
+*.jar           binary
85
+*.war           binary
86
+
87
+## LINTERS
88
+.csslintrc      text
89
+.eslintrc       text
90
+.jscsrc         text
91
+.jshintrc       text
92
+.jshintignore   text
93
+.stylelintrc    text
94
+
95
+## CONFIGS
96
+*.bowerrc       text
97
+*.conf          text
98
+*.config        text
99
+.editorconfig   text
100
+.gitattributes  text
101
+.gitconfig      text
102
+.gitignore      text
103
+.htaccess       text
104
+*.npmignore     text
105
+
106
+## HEROKU
107
+Procfile        text
108
+.slugignore     text
109
+
110
+## AUDIO
111
+*.kar           binary
112
+*.m4a           binary
113
+*.mid           binary
114
+*.midi          binary
115
+*.mp3           binary
116
+*.ogg           binary
117
+*.ra            binary
118
+
119
+## VIDEO
120
+*.3gpp          binary
121
+*.3gp           binary
122
+*.as            binary
123
+*.asf           binary
124
+*.asx           binary
125
+*.fla           binary
126
+*.flv           binary
127
+*.m4v           binary
128
+*.mng           binary
129
+*.mov           binary
130
+*.mp4           binary
131
+*.mpeg          binary
132
+*.mpg           binary
133
+*.swc           binary
134
+*.swf           binary
135
+*.webm          binary
136
+
137
+## ARCHIVES
138
+*.7z            binary
139
+*.gz            binary
140
+*.rar           binary
141
+*.tar           binary
142
+*.zip           binary
143
+
144
+## FONTS
145
+*.ttf           binary
146
+*.eot           binary
147
+*.otf           binary
148
+*.woff          binary
149
+*.woff2         binary

+ 144
- 1
.gitignore Zobrazit soubor

@@ -1 +1,144 @@
1
-.idea
1
+######################
2
+# Project Specific
3
+######################
4
+/build/www/**
5
+/src/test/javascript/coverage/
6
+
7
+######################
8
+# Node
9
+######################
10
+/node/
11
+node_tmp/
12
+node_modules/
13
+npm-debug.log.*
14
+/.awcache/*
15
+/.cache-loader/*
16
+
17
+######################
18
+# SASS
19
+######################
20
+.sass-cache/
21
+
22
+######################
23
+# Eclipse
24
+######################
25
+*.pydevproject
26
+.project
27
+.metadata
28
+tmp/
29
+tmp/**/*
30
+*.tmp
31
+*.bak
32
+*.swp
33
+*~.nib
34
+local.properties
35
+.classpath
36
+.settings/
37
+.loadpath
38
+.factorypath
39
+/src/main/resources/rebel.xml
40
+
41
+# External tool builders
42
+.externalToolBuilders/**
43
+
44
+# Locally stored "Eclipse launch configurations"
45
+*.launch
46
+
47
+# CDT-specific
48
+.cproject
49
+
50
+# PDT-specific
51
+.buildpath
52
+
53
+######################
54
+# Intellij
55
+######################
56
+.idea/
57
+*.iml
58
+*.iws
59
+*.ipr
60
+*.ids
61
+*.orig
62
+classes/
63
+out/
64
+
65
+######################
66
+# Visual Studio Code
67
+######################
68
+.vscode/
69
+
70
+######################
71
+# Maven
72
+######################
73
+/log/
74
+/target/
75
+
76
+######################
77
+# Gradle
78
+######################
79
+.gradle/
80
+/build/
81
+
82
+######################
83
+# Package Files
84
+######################
85
+*.jar
86
+*.war
87
+*.ear
88
+*.db
89
+
90
+######################
91
+# Windows
92
+######################
93
+# Windows image file caches
94
+Thumbs.db
95
+
96
+# Folder config file
97
+Desktop.ini
98
+
99
+######################
100
+# Mac OSX
101
+######################
102
+.DS_Store
103
+.svn
104
+
105
+# Thumbnails
106
+._*
107
+
108
+# Files that might appear on external disk
109
+.Spotlight-V100
110
+.Trashes
111
+
112
+######################
113
+# Directories
114
+######################
115
+/bin/
116
+/deploy/
117
+
118
+######################
119
+# Logs
120
+######################
121
+*.log*
122
+
123
+######################
124
+# Others
125
+######################
126
+*.class
127
+*.*~
128
+*~
129
+.merge_file*
130
+
131
+######################
132
+# Gradle Wrapper
133
+######################
134
+!gradle/wrapper/gradle-wrapper.jar
135
+
136
+######################
137
+# Maven Wrapper
138
+######################
139
+!.mvn/wrapper/maven-wrapper.jar
140
+
141
+######################
142
+# ESLint
143
+######################
144
+.eslintcache

+ 5
- 0
.huskyrc Zobrazit soubor

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

+ 110
- 0
.mvn/wrapper/MavenWrapperDownloader.java Zobrazit soubor

@@ -0,0 +1,110 @@
1
+/*
2
+Licensed to the Apache Software Foundation (ASF) under one
3
+or more contributor license agreements.  See the NOTICE file
4
+distributed with this work for additional information
5
+regarding copyright ownership.  The ASF licenses this file
6
+to you under the Apache License, Version 2.0 (the
7
+"License"); you may not use this file except in compliance
8
+with the License.  You may obtain a copy of the License at
9
+
10
+  http://www.apache.org/licenses/LICENSE-2.0
11
+
12
+Unless required by applicable law or agreed to in writing,
13
+software distributed under the License is distributed on an
14
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+KIND, either express or implied.  See the License for the
16
+specific language governing permissions and limitations
17
+under the License.
18
+*/
19
+
20
+import java.net.*;
21
+import java.io.*;
22
+import java.nio.channels.*;
23
+import java.util.Properties;
24
+
25
+public class MavenWrapperDownloader {
26
+
27
+    /**
28
+     * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
29
+     */
30
+    private static final String DEFAULT_DOWNLOAD_URL =
31
+            "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
32
+
33
+    /**
34
+     * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
35
+     * use instead of the default one.
36
+     */
37
+    private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
38
+            ".mvn/wrapper/maven-wrapper.properties";
39
+
40
+    /**
41
+     * Path where the maven-wrapper.jar will be saved to.
42
+     */
43
+    private static final String MAVEN_WRAPPER_JAR_PATH =
44
+            ".mvn/wrapper/maven-wrapper.jar";
45
+
46
+    /**
47
+     * Name of the property which should be used to override the default download url for the wrapper.
48
+     */
49
+    private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
50
+
51
+    public static void main(String args[]) {
52
+        System.out.println("- Downloader started");
53
+        File baseDirectory = new File(args[0]);
54
+        System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
55
+
56
+        // If the maven-wrapper.properties exists, read it and check if it contains a custom
57
+        // wrapperUrl parameter.
58
+        File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
59
+        String url = DEFAULT_DOWNLOAD_URL;
60
+        if (mavenWrapperPropertyFile.exists()) {
61
+            FileInputStream mavenWrapperPropertyFileInputStream = null;
62
+            try {
63
+                mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
64
+                Properties mavenWrapperProperties = new Properties();
65
+                mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
66
+                url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
67
+            } catch (IOException e) {
68
+                System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
69
+            } finally {
70
+                try {
71
+                    if (mavenWrapperPropertyFileInputStream != null) {
72
+                        mavenWrapperPropertyFileInputStream.close();
73
+                    }
74
+                } catch (IOException e) {
75
+                    // Ignore ...
76
+                }
77
+            }
78
+        }
79
+        System.out.println("- Downloading from: : " + url);
80
+
81
+        File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
82
+        if (!outputFile.getParentFile().exists()) {
83
+            if (!outputFile.getParentFile().mkdirs()) {
84
+                System.out.println(
85
+                        "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
86
+            }
87
+        }
88
+        System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
89
+        try {
90
+            downloadFileFromURL(url, outputFile);
91
+            System.out.println("Done");
92
+            System.exit(0);
93
+        } catch (Throwable e) {
94
+            System.out.println("- Error downloading");
95
+            e.printStackTrace();
96
+            System.exit(1);
97
+        }
98
+    }
99
+
100
+    private static void downloadFileFromURL(String urlString, File destination) throws Exception {
101
+        URL website = new URL(urlString);
102
+        ReadableByteChannel rbc;
103
+        rbc = Channels.newChannel(website.openStream());
104
+        FileOutputStream fos = new FileOutputStream(destination);
105
+        fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
106
+        fos.close();
107
+        rbc.close();
108
+    }
109
+
110
+}

binární
.mvn/wrapper/maven-wrapper.jar Zobrazit soubor


+ 1
- 0
.mvn/wrapper/maven-wrapper.properties Zobrazit soubor

@@ -0,0 +1 @@
1
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.0/apache-maven-3.6.0-bin.zip

+ 2
- 0
.prettierignore Zobrazit soubor

@@ -0,0 +1,2 @@
1
+node_modules
2
+target

+ 12
- 0
.prettierrc Zobrazit soubor

@@ -0,0 +1,12 @@
1
+# Prettier configuration
2
+
3
+printWidth: 140
4
+singleQuote: true
5
+tabWidth: 4
6
+useTabs: false
7
+
8
+# js and ts rules:
9
+arrowParens: avoid
10
+
11
+# jsx and tsx rules:
12
+jsxBracketSameLine: false

+ 41
- 0
.yo-rc.json Zobrazit soubor

@@ -0,0 +1,41 @@
1
+{
2
+  "generator-jhipster": {
3
+    "promptValues": {
4
+      "packageName": "rocks.zipcode.io",
5
+      "nativeLanguage": "en"
6
+    },
7
+    "jhipsterVersion": "5.7.0",
8
+    "applicationType": "monolith",
9
+    "baseName": "ZipConnect",
10
+    "packageName": "rocks.zipcode.io",
11
+    "packageFolder": "rocks/zipcode/io",
12
+    "serverPort": "8080",
13
+    "authenticationType": "jwt",
14
+    "cacheProvider": "hazelcast",
15
+    "enableHibernateCache": true,
16
+    "websocket": false,
17
+    "databaseType": "sql",
18
+    "devDatabaseType": "h2Memory",
19
+    "prodDatabaseType": "mysql",
20
+    "searchEngine": false,
21
+    "messageBroker": false,
22
+    "serviceDiscoveryType": "eureka",
23
+    "buildTool": "maven",
24
+    "enableSwaggerCodegen": false,
25
+    "jwtSecretKey": "ZTM5ZmZjYTczMmM4NmFhYzI4MDg0OGUyNzljOGRjOWM0MDQwYTgyOTJlODRjNTYwNTE5ZjI0NDE1ZTQzMzRiODZkNmUzMmM5ZjVjZDQ1MWM0NjRlZWRlZTllOTgzMjIxYTBhNDk0MTY2NjRjNTRhMTVjMzNjMTI3OTQzNjI3N2U=",
26
+    "clientFramework": "angularX",
27
+    "useSass": true,
28
+    "clientPackageManager": "npm",
29
+    "testFrameworks": [
30
+      "protractor"
31
+    ],
32
+    "jhiPrefix": "jhi",
33
+    "otherModules": [],
34
+    "enableTranslation": true,
35
+    "nativeLanguage": "en",
36
+    "languages": [
37
+      "en",
38
+      "es"
39
+    ]
40
+  }
41
+}

+ 100
- 0
README.md Zobrazit soubor

@@ -0,0 +1,100 @@
1
+# ZipConnect
2
+This application was generated using JHipster 5.7.0, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v5.7.0](https://www.jhipster.tech/documentation-archive/v5.7.0).
3
+
4
+## Development
5
+
6
+To start your application in the dev profile, simply run:
7
+
8
+    
9
+
10
+
11
+For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][].
12
+
13
+### Using angular-cli
14
+
15
+You can also use [Angular CLI][] to generate some custom client code.
16
+
17
+For example, the following command:
18
+
19
+    ng generate component my-component
20
+
21
+will generate few files:
22
+
23
+    create src/main/webapp/app/my-component/my-component.component.html
24
+    create src/main/webapp/app/my-component/my-component.component.ts
25
+    update src/main/webapp/app/app.module.ts
26
+
27
+
28
+## Building for production
29
+
30
+To optimize the ZipConnect application for production, run:
31
+
32
+
33
+To ensure everything worked, run:
34
+
35
+
36
+
37
+Refer to [Using JHipster in production][] for more details.
38
+
39
+## Testing
40
+
41
+To launch your application's tests, run:
42
+
43
+    ./gradlew test
44
+
45
+For more information, refer to the [Running tests page][].
46
+
47
+### Code quality
48
+
49
+Sonar is used to analyse code quality. You can start a local Sonar server (accessible on http://localhost:9001) with:
50
+
51
+```
52
+docker-compose -f src/main/docker/sonar.yml up -d
53
+```
54
+
55
+Then, run a Sonar analysis:
56
+
57
+```
58
+./gradlew -Pprod clean test sonarqube
59
+```
60
+
61
+For more information, refer to the [Code quality page][].
62
+
63
+## Using Docker to simplify development (optional)
64
+
65
+You can use Docker to improve your JHipster development experience. A number of docker-compose configuration are available in the [src/main/docker](src/main/docker) folder to launch required third party services.
66
+
67
+For example, to start a  database in a docker container, run:
68
+
69
+    docker-compose -f src/main/docker/.yml up -d
70
+
71
+To stop it and remove the container, run:
72
+
73
+    docker-compose -f src/main/docker/.yml down
74
+
75
+You can also fully dockerize your application and all the services that it depends on.
76
+To achieve this, first build a docker image of your app by running:
77
+
78
+    
79
+
80
+Then run:
81
+
82
+    docker-compose -f src/main/docker/app.yml up -d
83
+
84
+For more information refer to [Using Docker and Docker-Compose][], this page also contains information on the docker-compose sub-generator (`jhipster docker-compose`), which is able to generate docker configurations for one or several JHipster applications.
85
+
86
+## Continuous Integration (optional)
87
+
88
+To configure CI for your project, run the ci-cd sub-generator (`jhipster ci-cd`), this will let you generate configuration files for a number of Continuous Integration systems. Consult the [Setting up Continuous Integration][] page for more information.
89
+
90
+[JHipster Homepage and latest documentation]: https://www.jhipster.tech
91
+[JHipster 5.7.0 archive]: https://www.jhipster.tech/documentation-archive/v5.7.0
92
+
93
+[Using JHipster in development]: https://www.jhipster.tech/documentation-archive/v5.7.0/development/
94
+[Using Docker and Docker-Compose]: https://www.jhipster.tech/documentation-archive/v5.7.0/docker-compose
95
+[Using JHipster in production]: https://www.jhipster.tech/documentation-archive/v5.7.0/production/
96
+[Running tests page]: https://www.jhipster.tech/documentation-archive/v5.7.0/running-tests/
97
+[Code quality page]: https://www.jhipster.tech/documentation-archive/v5.7.0/code-quality/
98
+[Setting up Continuous Integration]: https://www.jhipster.tech/documentation-archive/v5.7.0/setting-up-ci/
99
+
100
+

+ 39
- 0
angular.json Zobrazit soubor

@@ -0,0 +1,39 @@
1
+{
2
+  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3
+  "version": 1,
4
+  "newProjectRoot": "projects",
5
+  "projects": {
6
+    "zip-connect": {
7
+      "root": "",
8
+      "sourceRoot": "src/main/webapp",
9
+      "projectType": "application",
10
+      "architect": {}
11
+    }
12
+  },
13
+  "defaultProject": "zip-connect",
14
+  "cli": {
15
+    "packageManager": "npm"
16
+  },
17
+  "schematics": {
18
+    "@schematics/angular:component": {
19
+      "inlineStyle": true,
20
+      "inlineTemplate": false,
21
+      "spec": false,
22
+      "prefix": "jhi",
23
+      "styleExt": "scss"
24
+    },
25
+    "@schematics/angular:directive": {
26
+      "spec": false,
27
+      "prefix": "jhi"
28
+    },
29
+    "@schematics/angular:guard": {
30
+      "spec": false
31
+    },
32
+    "@schematics/angular:pipe": {
33
+      "spec": false
34
+    },
35
+    "@schematics/angular:service": {
36
+      "spec": false
37
+    }
38
+  }
39
+}

+ 286
- 0
mvnw Zobrazit soubor

@@ -0,0 +1,286 @@
1
+#!/bin/sh
2
+# ----------------------------------------------------------------------------
3
+# Licensed to the Apache Software Foundation (ASF) under one
4
+# or more contributor license agreements.  See the NOTICE file
5
+# distributed with this work for additional information
6
+# regarding copyright ownership.  The ASF licenses this file
7
+# to you under the Apache License, Version 2.0 (the
8
+# "License"); you may not use this file except in compliance
9
+# with the License.  You may obtain a copy of the License at
10
+#
11
+#    http://www.apache.org/licenses/LICENSE-2.0
12
+#
13
+# Unless required by applicable law or agreed to in writing,
14
+# software distributed under the License is distributed on an
15
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+# KIND, either express or implied.  See the License for the
17
+# specific language governing permissions and limitations
18
+# under the License.
19
+# ----------------------------------------------------------------------------
20
+
21
+# ----------------------------------------------------------------------------
22
+# Maven2 Start Up Batch script
23
+#
24
+# Required ENV vars:
25
+# ------------------
26
+#   JAVA_HOME - location of a JDK home dir
27
+#
28
+# Optional ENV vars
29
+# -----------------
30
+#   M2_HOME - location of maven2's installed home dir
31
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
32
+#     e.g. to debug Maven itself, use
33
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
34
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
35
+# ----------------------------------------------------------------------------
36
+
37
+if [ -z "$MAVEN_SKIP_RC" ] ; then
38
+
39
+  if [ -f /etc/mavenrc ] ; then
40
+    . /etc/mavenrc
41
+  fi
42
+
43
+  if [ -f "$HOME/.mavenrc" ] ; then
44
+    . "$HOME/.mavenrc"
45
+  fi
46
+
47
+fi
48
+
49
+# OS specific support.  $var _must_ be set to either true or false.
50
+cygwin=false;
51
+darwin=false;
52
+mingw=false
53
+case "`uname`" in
54
+  CYGWIN*) cygwin=true ;;
55
+  MINGW*) mingw=true;;
56
+  Darwin*) darwin=true
57
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
58
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
59
+    if [ -z "$JAVA_HOME" ]; then
60
+      if [ -x "/usr/libexec/java_home" ]; then
61
+        export JAVA_HOME="`/usr/libexec/java_home`"
62
+      else
63
+        export JAVA_HOME="/Library/Java/Home"
64
+      fi
65
+    fi
66
+    ;;
67
+esac
68
+
69
+if [ -z "$JAVA_HOME" ] ; then
70
+  if [ -r /etc/gentoo-release ] ; then
71
+    JAVA_HOME=`java-config --jre-home`
72
+  fi
73
+fi
74
+
75
+if [ -z "$M2_HOME" ] ; then
76
+  ## resolve links - $0 may be a link to maven's home
77
+  PRG="$0"
78
+
79
+  # need this for relative symlinks
80
+  while [ -h "$PRG" ] ; do
81
+    ls=`ls -ld "$PRG"`
82
+    link=`expr "$ls" : '.*-> \(.*\)$'`
83
+    if expr "$link" : '/.*' > /dev/null; then
84
+      PRG="$link"
85
+    else
86
+      PRG="`dirname "$PRG"`/$link"
87
+    fi
88
+  done
89
+
90
+  saveddir=`pwd`
91
+
92
+  M2_HOME=`dirname "$PRG"`/..
93
+
94
+  # make it fully qualified
95
+  M2_HOME=`cd "$M2_HOME" && pwd`
96
+
97
+  cd "$saveddir"
98
+  # echo Using m2 at $M2_HOME
99
+fi
100
+
101
+# For Cygwin, ensure paths are in UNIX format before anything is touched
102
+if $cygwin ; then
103
+  [ -n "$M2_HOME" ] &&
104
+    M2_HOME=`cygpath --unix "$M2_HOME"`
105
+  [ -n "$JAVA_HOME" ] &&
106
+    JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
107
+  [ -n "$CLASSPATH" ] &&
108
+    CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
109
+fi
110
+
111
+# For Mingw, ensure paths are in UNIX format before anything is touched
112
+if $mingw ; then
113
+  [ -n "$M2_HOME" ] &&
114
+    M2_HOME="`(cd "$M2_HOME"; pwd)`"
115
+  [ -n "$JAVA_HOME" ] &&
116
+    JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
117
+  # TODO classpath?
118
+fi
119
+
120
+if [ -z "$JAVA_HOME" ]; then
121
+  javaExecutable="`which javac`"
122
+  if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
123
+    # readlink(1) is not available as standard on Solaris 10.
124
+    readLink=`which readlink`
125
+    if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
126
+      if $darwin ; then
127
+        javaHome="`dirname \"$javaExecutable\"`"
128
+        javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
129
+      else
130
+        javaExecutable="`readlink -f \"$javaExecutable\"`"
131
+      fi
132
+      javaHome="`dirname \"$javaExecutable\"`"
133
+      javaHome=`expr "$javaHome" : '\(.*\)/bin'`
134
+      JAVA_HOME="$javaHome"
135
+      export JAVA_HOME
136
+    fi
137
+  fi
138
+fi
139
+
140
+if [ -z "$JAVACMD" ] ; then
141
+  if [ -n "$JAVA_HOME"  ] ; then
142
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
143
+      # IBM's JDK on AIX uses strange locations for the executables
144
+      JAVACMD="$JAVA_HOME/jre/sh/java"
145
+    else
146
+      JAVACMD="$JAVA_HOME/bin/java"
147
+    fi
148
+  else
149
+    JAVACMD="`which java`"
150
+  fi
151
+fi
152
+
153
+if [ ! -x "$JAVACMD" ] ; then
154
+  echo "Error: JAVA_HOME is not defined correctly." >&2
155
+  echo "  We cannot execute $JAVACMD" >&2
156
+  exit 1
157
+fi
158
+
159
+if [ -z "$JAVA_HOME" ] ; then
160
+  echo "Warning: JAVA_HOME environment variable is not set."
161
+fi
162
+
163
+CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
164
+
165
+# traverses directory structure from process work directory to filesystem root
166
+# first directory with .mvn subdirectory is considered project base directory
167
+find_maven_basedir() {
168
+
169
+  if [ -z "$1" ]
170
+  then
171
+    echo "Path not specified to find_maven_basedir"
172
+    return 1
173
+  fi
174
+
175
+  basedir="$1"
176
+  wdir="$1"
177
+  while [ "$wdir" != '/' ] ; do
178
+    if [ -d "$wdir"/.mvn ] ; then
179
+      basedir=$wdir
180
+      break
181
+    fi
182
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
183
+    if [ -d "${wdir}" ]; then
184
+      wdir=`cd "$wdir/.."; pwd`
185
+    fi
186
+    # end of workaround
187
+  done
188
+  echo "${basedir}"
189
+}
190
+
191
+# concatenates all lines of a file
192
+concat_lines() {
193
+  if [ -f "$1" ]; then
194
+    echo "$(tr -s '\n' ' ' < "$1")"
195
+  fi
196
+}
197
+
198
+BASE_DIR=`find_maven_basedir "$(pwd)"`
199
+if [ -z "$BASE_DIR" ]; then
200
+  exit 1;
201
+fi
202
+
203
+##########################################################################################
204
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
205
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
206
+##########################################################################################
207
+if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
208
+    if [ "$MVNW_VERBOSE" = true ]; then
209
+      echo "Found .mvn/wrapper/maven-wrapper.jar"
210
+    fi
211
+else
212
+    if [ "$MVNW_VERBOSE" = true ]; then
213
+      echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
214
+    fi
215
+    jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
216
+    while IFS="=" read key value; do
217
+      case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
218
+      esac
219
+    done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
220
+    if [ "$MVNW_VERBOSE" = true ]; then
221
+      echo "Downloading from: $jarUrl"
222
+    fi
223
+    wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
224
+
225
+    if command -v wget > /dev/null; then
226
+        if [ "$MVNW_VERBOSE" = true ]; then
227
+          echo "Found wget ... using wget"
228
+        fi
229
+        wget "$jarUrl" -O "$wrapperJarPath"
230
+    elif command -v curl > /dev/null; then
231
+        if [ "$MVNW_VERBOSE" = true ]; then
232
+          echo "Found curl ... using curl"
233
+        fi
234
+        curl -o "$wrapperJarPath" "$jarUrl"
235
+    else
236
+        if [ "$MVNW_VERBOSE" = true ]; then
237
+          echo "Falling back to using Java to download"
238
+        fi
239
+        javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
240
+        if [ -e "$javaClass" ]; then
241
+            if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
242
+                if [ "$MVNW_VERBOSE" = true ]; then
243
+                  echo " - Compiling MavenWrapperDownloader.java ..."
244
+                fi
245
+                # Compiling the Java class
246
+                ("$JAVA_HOME/bin/javac" "$javaClass")
247
+            fi
248
+            if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
249
+                # Running the downloader
250
+                if [ "$MVNW_VERBOSE" = true ]; then
251
+                  echo " - Running MavenWrapperDownloader.java ..."
252
+                fi
253
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
254
+            fi
255
+        fi
256
+    fi
257
+fi
258
+##########################################################################################
259
+# End of extension
260
+##########################################################################################
261
+
262
+export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
263
+if [ "$MVNW_VERBOSE" = true ]; then
264
+  echo $MAVEN_PROJECTBASEDIR
265
+fi
266
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
267
+
268
+# For Cygwin, switch paths to Windows format before running java
269
+if $cygwin; then
270
+  [ -n "$M2_HOME" ] &&
271
+    M2_HOME=`cygpath --path --windows "$M2_HOME"`
272
+  [ -n "$JAVA_HOME" ] &&
273
+    JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
274
+  [ -n "$CLASSPATH" ] &&
275
+    CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
276
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
277
+    MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
278
+fi
279
+
280
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
281
+
282
+exec "$JAVACMD" \
283
+  $MAVEN_OPTS \
284
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
285
+  "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
286
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"

+ 161
- 0
mvnw.cmd Zobrazit soubor

@@ -0,0 +1,161 @@
1
+@REM ----------------------------------------------------------------------------
2
+@REM Licensed to the Apache Software Foundation (ASF) under one
3
+@REM or more contributor license agreements.  See the NOTICE file
4
+@REM distributed with this work for additional information
5
+@REM regarding copyright ownership.  The ASF licenses this file
6
+@REM to you under the Apache License, Version 2.0 (the
7
+@REM "License"); you may not use this file except in compliance
8
+@REM with the License.  You may obtain a copy of the License at
9
+@REM
10
+@REM    http://www.apache.org/licenses/LICENSE-2.0
11
+@REM
12
+@REM Unless required by applicable law or agreed to in writing,
13
+@REM software distributed under the License is distributed on an
14
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+@REM KIND, either express or implied.  See the License for the
16
+@REM specific language governing permissions and limitations
17
+@REM under the License.
18
+@REM ----------------------------------------------------------------------------
19
+
20
+@REM ----------------------------------------------------------------------------
21
+@REM Maven2 Start Up Batch script
22
+@REM
23
+@REM Required ENV vars:
24
+@REM JAVA_HOME - location of a JDK home dir
25
+@REM
26
+@REM Optional ENV vars
27
+@REM M2_HOME - location of maven2's installed home dir
28
+@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
29
+@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a key stroke before ending
30
+@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
31
+@REM     e.g. to debug Maven itself, use
32
+@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
33
+@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
34
+@REM ----------------------------------------------------------------------------
35
+
36
+@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
37
+@echo off
38
+@REM set title of command window
39
+title %0
40
+@REM enable echoing my setting MAVEN_BATCH_ECHO to 'on'
41
+@if "%MAVEN_BATCH_ECHO%" == "on"  echo %MAVEN_BATCH_ECHO%
42
+
43
+@REM set %HOME% to equivalent of $HOME
44
+if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
45
+
46
+@REM Execute a user defined script before this one
47
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
48
+@REM check for pre script, once with legacy .bat ending and once with .cmd ending
49
+if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
50
+if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
51
+:skipRcPre
52
+
53
+@setlocal
54
+
55
+set ERROR_CODE=0
56
+
57
+@REM To isolate internal variables from possible post scripts, we use another setlocal
58
+@setlocal
59
+
60
+@REM ==== START VALIDATION ====
61
+if not "%JAVA_HOME%" == "" goto OkJHome
62
+
63
+echo.
64
+echo Error: JAVA_HOME not found in your environment. >&2
65
+echo Please set the JAVA_HOME variable in your environment to match the >&2
66
+echo location of your Java installation. >&2
67
+echo.
68
+goto error
69
+
70
+:OkJHome
71
+if exist "%JAVA_HOME%\bin\java.exe" goto init
72
+
73
+echo.
74
+echo Error: JAVA_HOME is set to an invalid directory. >&2
75
+echo JAVA_HOME = "%JAVA_HOME%" >&2
76
+echo Please set the JAVA_HOME variable in your environment to match the >&2
77
+echo location of your Java installation. >&2
78
+echo.
79
+goto error
80
+
81
+@REM ==== END VALIDATION ====
82
+
83
+:init
84
+
85
+@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
86
+@REM Fallback to current working directory if not found.
87
+
88
+set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
89
+IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
90
+
91
+set EXEC_DIR=%CD%
92
+set WDIR=%EXEC_DIR%
93
+:findBaseDir
94
+IF EXIST "%WDIR%"\.mvn goto baseDirFound
95
+cd ..
96
+IF "%WDIR%"=="%CD%" goto baseDirNotFound
97
+set WDIR=%CD%
98
+goto findBaseDir
99
+
100
+:baseDirFound
101
+set MAVEN_PROJECTBASEDIR=%WDIR%
102
+cd "%EXEC_DIR%"
103
+goto endDetectBaseDir
104
+
105
+:baseDirNotFound
106
+set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
107
+cd "%EXEC_DIR%"
108
+
109
+:endDetectBaseDir
110
+
111
+IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
112
+
113
+@setlocal EnableExtensions EnableDelayedExpansion
114
+for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
115
+@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
116
+
117
+:endReadAdditionalConfig
118
+
119
+SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
120
+set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
121
+set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
122
+
123
+set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar"
124
+FOR /F "tokens=1,2 delims==" %%A IN (%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties) DO (
125
+	IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B 
126
+)
127
+
128
+@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
129
+@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
130
+if exist %WRAPPER_JAR% (
131
+    echo Found %WRAPPER_JAR%
132
+) else (
133
+    echo Couldn't find %WRAPPER_JAR%, downloading it ...
134
+	echo Downloading from: %DOWNLOAD_URL%
135
+    powershell -Command "(New-Object Net.WebClient).DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"
136
+    echo Finished downloading %WRAPPER_JAR%
137
+)
138
+@REM End of extension
139
+
140
+%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
141
+if ERRORLEVEL 1 goto error
142
+goto end
143
+
144
+:error
145
+set ERROR_CODE=1
146
+
147
+:end
148
+@endlocal & set ERROR_CODE=%ERROR_CODE%
149
+
150
+if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
151
+@REM check for post script, once with legacy .bat ending and once with .cmd ending
152
+if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
153
+if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
154
+:skipRcPost
155
+
156
+@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
157
+if "%MAVEN_BATCH_PAUSE%" == "on" pause
158
+
159
+if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
160
+
161
+exit /B %ERROR_CODE%

+ 19707
- 0
package-lock.json
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 139
- 0
package.json Zobrazit soubor

@@ -0,0 +1,139 @@
1
+{
2
+  "name": "zip-connect",
3
+  "version": "0.0.0",
4
+  "description": "Description for ZipConnect",
5
+  "private": true,
6
+  "license": "UNLICENSED",
7
+  "cacheDirectories": [
8
+    "node_modules"
9
+  ],
10
+  "dependencies": {
11
+    "@angular/common": "7.0.0",
12
+    "@angular/compiler": "7.0.0",
13
+    "@angular/core": "7.0.0",
14
+    "@angular/forms": "7.0.0",
15
+    "@angular/platform-browser": "7.0.0",
16
+    "@angular/platform-browser-dynamic": "7.0.0",
17
+    "@angular/router": "7.0.0",
18
+    "@fortawesome/angular-fontawesome": "0.3.0",
19
+    "@fortawesome/fontawesome-svg-core": "1.2.8",
20
+    "@fortawesome/free-solid-svg-icons": "5.5.0",
21
+    "@ng-bootstrap/ng-bootstrap": "4.0.0",
22
+    "bootstrap": "4.1.3",
23
+    "core-js": "2.5.7",
24
+    "moment": "2.22.2",
25
+    "ng-jhipster": "0.5.6",
26
+    "ngx-cookie": "2.0.1",
27
+    "ngx-infinite-scroll": "6.0.1",
28
+    "ngx-webstorage": "2.0.1",
29
+    "reflect-metadata": "0.1.12",
30
+    "rxjs": "6.3.3",
31
+    "swagger-ui": "2.2.10",
32
+    "tslib": "1.9.3",
33
+    "zone.js": "0.8.26"
34
+  },
35
+  "devDependencies": {
36
+    "@angular/cli": "7.0.2",
37
+    "@angular/compiler-cli": "7.0.0",
38
+    "@ngtools/webpack": "7.0.2",
39
+    "@types/chai": "4.1.4",
40
+    "@types/chai-string": "1.4.1",
41
+    "@types/jest": "23.3.5",
42
+    "@types/mocha": "5.2.5",
43
+    "@types/node": "9.4.7",
44
+    "@types/selenium-webdriver": "3.0.8",
45
+    "angular-router-loader": "0.8.5",
46
+    "angular2-template-loader": "0.6.2",
47
+    "autoprefixer": "9.2.0",
48
+    "browser-sync": "2.26.3",
49
+    "browser-sync-webpack-plugin": "2.2.2",
50
+    "cache-loader": "1.2.2",
51
+    "chai": "4.1.2",
52
+    "chai-as-promised": "7.1.1",
53
+    "chai-string": "1.5.0",
54
+    "codelyzer": "4.5.0",
55
+    "copy-webpack-plugin": "4.5.1",
56
+    "css-loader": "0.28.10",
57
+    "file-loader": "1.1.11",
58
+    "fork-ts-checker-webpack-plugin": "0.4.10",
59
+    "friendly-errors-webpack-plugin": "1.7.0",
60
+    "generator-jhipster": "5.7.0",
61
+    "html-loader": "0.5.5",
62
+    "html-webpack-plugin": "3.2.0",
63
+    "husky": "1.1.0",
64
+    "jest": "23.6.0",
65
+    "jest-junit": "5.1.0",
66
+    "jest-preset-angular": "6.0.1",
67
+    "jest-sonar-reporter": "2.0.0",
68
+    "lint-staged": "7.3.0",
69
+    "merge-jsons-webpack-plugin": "1.0.14",
70
+    "mocha": "5.2.0",
71
+    "mini-css-extract-plugin": "0.4.2",
72
+    "moment-locales-webpack-plugin": "1.0.5",
73
+    "optimize-css-assets-webpack-plugin": "5.0.1",
74
+    "prettier": "1.14.3",
75
+    "protractor": "5.4.0",
76
+    "rimraf": "2.6.1",
77
+    "simple-progress-webpack-plugin": "1.1.2",
78
+    "style-loader": "0.20.3",
79
+    "terser-webpack-plugin": "1.0.0",
80
+    "thread-loader": "1.1.5",
81
+    "to-string-loader": "1.1.5",
82
+    "ts-node": "5.0.1",
83
+    "ts-loader": "4.5.0",
84
+    "tslint": "5.11.0",
85
+    "tslint-config-prettier": "1.15.0",
86
+    "tslint-loader": "3.6.0",
87
+    "typescript": "3.1.3",
88
+    "sass": "1.13.0",
89
+    "sass-loader": "7.1.0",
90
+    "postcss-loader": "2.1.6",
91
+    "xml2js": "0.4.19",
92
+    "webpack": "4.25.1",
93
+    "webpack-cli": "3.1.2",
94
+    "webpack-dev-server": "3.1.10",
95
+    "webpack-merge": "4.1.4",
96
+    "webpack-notifier": "1.7.0",
97
+    "webpack-visualizer-plugin": "0.1.11",
98
+    "workbox-webpack-plugin": "3.6.3",
99
+    "write-file-webpack-plugin": "4.4.1"
100
+  },
101
+  "engines": {
102
+    "node": ">=8.9.0"
103
+  },
104
+  "lint-staged": {
105
+    "src/**/*.{json,ts,css,scss}": [
106
+      "prettier --write",
107
+      "git add"
108
+    ]
109
+  },
110
+  "scripts": {
111
+    "prettier:format": "prettier --write \"src/**/*.{json,ts,css,scss}\"",
112
+    "lint": "tslint --project tsconfig.json -e 'node_modules/**'",
113
+    "lint:fix": "npm run lint -- --fix",
114
+    "ngc": "ngc -p tsconfig-aot.json",
115
+    "cleanup": "rimraf target/{aot,www}",
116
+    "clean-www": "rimraf target//www/app/{src,target/}",
117
+    "e2e": "protractor src/test/javascript/protractor.conf.js",
118
+    "postinstall": "webdriver-manager update --gecko false",
119
+    "start": "npm run webpack:dev",
120
+    "start-tls": "npm run webpack:dev -- --env.tls",
121
+    "serve": "npm run start",
122
+    "build": "npm run webpack:prod",
123
+    "test": "npm run lint && jest --coverage --logHeapUsage -w=2 --config src/test/javascript/jest.conf.js",
124
+    "test:watch": "npm run test -- --watch",
125
+    "webpack:dev": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --env.stats=minimal",
126
+    "webpack:dev-verbose": "npm run webpack-dev-server -- --config webpack/webpack.dev.js --inline --hot --port=9060 --watch-content-base --profile --progress --env.stats=normal",
127
+    "webpack:build:main": "npm run webpack -- --config webpack/webpack.dev.js --env.stats=minimal",
128
+    "webpack:build": "npm run cleanup && npm run webpack:build:main",
129
+    "webpack:prod:main": "npm run webpack -- --config webpack/webpack.prod.js --profile",
130
+    "webpack:prod": "npm run cleanup && npm run webpack:prod:main && npm run clean-www",
131
+    "webpack:test": "npm run test",
132
+    "webpack-dev-server": "node --max_old_space_size=4096 node_modules/webpack-dev-server/bin/webpack-dev-server.js",
133
+    "webpack": "node --max_old_space_size=4096 node_modules/webpack/bin/webpack.js"
134
+  },
135
+  "jestSonar": {
136
+    "reportPath": "target/test-results/jest",
137
+    "reportFile": "TESTS-results-sonar.xml"
138
+  }
139
+}

+ 1126
- 0
pom.xml
Diff nebyl zobrazen, protože je příliš veliký
Zobrazit soubor


+ 5
- 0
postcss.config.js Zobrazit soubor

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

+ 7
- 0
proxy.conf.json Zobrazit soubor

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

+ 14
- 0
src/main/docker/.dockerignore Zobrazit soubor

@@ -0,0 +1,14 @@
1
+# https://docs.docker.com/engine/reference/builder/#dockerignore-file
2
+classes/
3
+generated-sources/
4
+generated-test-sources/
5
+h2db/
6
+maven-archiver/
7
+maven-status/
8
+reports/
9
+surefire-reports/
10
+test-classes/
11
+test-results/
12
+www/
13
+!*.jar
14
+!*.war

+ 20
- 0
src/main/docker/Dockerfile Zobrazit soubor

@@ -0,0 +1,20 @@
1
+FROM openjdk:8-jre-alpine
2
+
3
+ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS \
4
+    JHIPSTER_SLEEP=0 \
5
+    JAVA_OPTS=""
6
+
7
+# Add a jhipster user to run our application so that it doesn't need to run as root
8
+RUN adduser -D -s /bin/sh jhipster
9
+WORKDIR /home/jhipster
10
+
11
+ADD entrypoint.sh entrypoint.sh
12
+RUN chmod 755 entrypoint.sh && chown jhipster:jhipster entrypoint.sh
13
+USER jhipster
14
+
15
+ENTRYPOINT ["./entrypoint.sh"]
16
+
17
+EXPOSE 8080 5701/udp
18
+
19
+ADD *.war app.war
20
+

+ 24
- 0
src/main/docker/app.yml Zobrazit soubor

@@ -0,0 +1,24 @@
1
+version: '2'
2
+services:
3
+    zipconnect-app:
4
+        image: zipconnect
5
+        environment:
6
+            - _JAVA_OPTIONS=-Xmx512m -Xms256m
7
+            - SPRING_PROFILES_ACTIVE=prod,swagger
8
+            - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka
9
+            - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
10
+            - SPRING_DATASOURCE_URL=jdbc:mysql://zipconnect-mysql:3306/zipconnect?useUnicode=true&characterEncoding=utf8&useSSL=false
11
+            - JHIPSTER_SLEEP=30 # gives time for the JHipster Registry to boot before the application
12
+        ports:
13
+            - 8080:8080
14
+    zipconnect-mysql:
15
+        extends:
16
+            file: mysql.yml
17
+            service: zipconnect-mysql
18
+    jhipster-registry:
19
+        extends:
20
+            file: jhipster-registry.yml
21
+            service: jhipster-registry
22
+        environment:
23
+            - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native
24
+            - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config/docker-config/

+ 7
- 0
src/main/docker/central-server-config/README.md Zobrazit soubor

@@ -0,0 +1,7 @@
1
+# Central configuration sources details
2
+
3
+The JHipster-Registry will use the following directories as its configuration source :
4
+- localhost-config : when running the registry in docker with the jhipster-registry.yml docker-compose file
5
+- docker-config : when running the registry and the app both in docker with the app.yml docker-compose file
6
+
7
+For more info, refer to https://www.jhipster.tech/microservices-architecture/#registry_app_configuration

+ 15
- 0
src/main/docker/central-server-config/docker-config/application.yml Zobrazit soubor

@@ -0,0 +1,15 @@
1
+# Common configuration shared between all applications
2
+configserver:
3
+    name: Docker JHipster Registry
4
+    status: Connected to the JHipster Registry running in Docker
5
+
6
+jhipster:
7
+    security:
8
+        authentication:
9
+            jwt:
10
+                secret: my-secret-key-which-should-be-changed-in-production-and-be-base64-encoded
11
+
12
+eureka:
13
+    client:
14
+        service-url:
15
+            defaultZone: http://admin:${jhipster.registry.password}@jhipster-registry:8761/eureka/

+ 15
- 0
src/main/docker/central-server-config/localhost-config/application.yml Zobrazit soubor

@@ -0,0 +1,15 @@
1
+# Common configuration shared between all applications
2
+configserver:
3
+    name: Docker JHipster Registry
4
+    status: Connected to the JHipster Registry running in Docker
5
+
6
+jhipster:
7
+    security:
8
+        authentication:
9
+            jwt:
10
+                secret: my-secret-key-which-should-be-changed-in-production-and-be-base64-encoded
11
+
12
+eureka:
13
+    client:
14
+        service-url:
15
+            defaultZone: http://admin:${jhipster.registry.password}@localhost:8761/eureka/

+ 4
- 0
src/main/docker/entrypoint.sh Zobrazit soubor

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

+ 6
- 0
src/main/docker/hazelcast-management-center.yml Zobrazit soubor

@@ -0,0 +1,6 @@
1
+version: '2'
2
+services:
3
+    zipconnect-hazelcast-management-center:
4
+        image: hazelcast/management-center:3.9.3
5
+        ports:
6
+            - 8180:8080

+ 22
- 0
src/main/docker/jhipster-registry.yml Zobrazit soubor

@@ -0,0 +1,22 @@
1
+version: '2'
2
+services:
3
+    jhipster-registry:
4
+        image: jhipster/jhipster-registry:v4.0.6
5
+        volumes:
6
+            - ./central-server-config:/central-config
7
+        # When run with the "dev" Spring profile, the JHipster Registry will
8
+        # read the config from the local filesystem (central-server-config directory)
9
+        # When run with the "prod" Spring profile, it will read the configuration from a Git repository
10
+        # See https://www.jhipster.tech/microservices-architecture/#registry_app_configuration
11
+        environment:
12
+            - _JAVA_OPTIONS=-Xmx512m -Xms256m
13
+            - SPRING_PROFILES_ACTIVE=dev,swagger
14
+            - SPRING_SECURITY_USER_PASSWORD=admin
15
+            - JHIPSTER_REGISTRY_PASSWORD=admin
16
+            - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=native
17
+            - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_LOCATIONS=file:./central-config/localhost-config/
18
+            # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_TYPE=git
19
+            # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_URI=https://github.com/jhipster/jhipster-registry/
20
+            # - SPRING_CLOUD_CONFIG_SERVER_COMPOSITE_0_SEARCH_PATHS=central-config
21
+        ports:
22
+            - 8761:8761

+ 13
- 0
src/main/docker/mysql.yml Zobrazit soubor

@@ -0,0 +1,13 @@
1
+version: '2'
2
+services:
3
+    zipconnect-mysql:
4
+        image: mysql:5.7.20
5
+        # volumes:
6
+        #     - ~/volumes/jhipster/ZipConnect/mysql/:/var/lib/mysql/
7
+        environment:
8
+            - MYSQL_USER=root
9
+            - MYSQL_ALLOW_EMPTY_PASSWORD=yes
10
+            - MYSQL_DATABASE=zipconnect
11
+        ports:
12
+            - 3306:3306
13
+        command: mysqld --lower_case_table_names=1 --skip-ssl --character_set_server=utf8mb4 --explicit_defaults_for_timestamp

+ 7
- 0
src/main/docker/sonar.yml Zobrazit soubor

@@ -0,0 +1,7 @@
1
+version: '2'
2
+services:
3
+    zipconnect-sonar:
4
+        image: sonarqube:7.1
5
+        ports:
6
+            - 9001:9000
7
+            - 9092:9092

+ 21
- 0
src/main/java/rocks/zipcode/io/ApplicationWebXml.java Zobrazit soubor

@@ -0,0 +1,21 @@
1
+package rocks.zipcode.io;
2
+
3
+import rocks.zipcode.io.config.DefaultProfileUtil;
4
+import org.springframework.boot.builder.SpringApplicationBuilder;
5
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
6
+
7
+/**
8
+ * This is a helper Java class that provides an alternative to creating a web.xml.
9
+ * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc.
10
+ */
11
+public class ApplicationWebXml extends SpringBootServletInitializer {
12
+
13
+    @Override
14
+    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
15
+        /**
16
+         * set a default to use when no profile is configured.
17
+         */
18
+        DefaultProfileUtil.addDefaultProfile(application.application());
19
+        return application.sources(ZipConnectApp.class);
20
+    }
21
+}

+ 100
- 0
src/main/java/rocks/zipcode/io/ZipConnectApp.java Zobrazit soubor

@@ -0,0 +1,100 @@
1
+package rocks.zipcode.io;
2
+
3
+import rocks.zipcode.io.config.ApplicationProperties;
4
+import rocks.zipcode.io.config.DefaultProfileUtil;
5
+
6
+import io.github.jhipster.config.JHipsterConstants;
7
+
8
+import org.apache.commons.lang3.StringUtils;
9
+import org.slf4j.Logger;
10
+import org.slf4j.LoggerFactory;
11
+import org.springframework.boot.SpringApplication;
12
+import org.springframework.boot.autoconfigure.SpringBootApplication;
13
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
14
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
15
+import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
16
+import org.springframework.core.env.Environment;
17
+
18
+import javax.annotation.PostConstruct;
19
+import java.net.InetAddress;
20
+import java.net.UnknownHostException;
21
+import java.util.Arrays;
22
+import java.util.Collection;
23
+
24
+@SpringBootApplication
25
+@EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class})
26
+@EnableDiscoveryClient
27
+public class ZipConnectApp {
28
+
29
+    private static final Logger log = LoggerFactory.getLogger(ZipConnectApp.class);
30
+
31
+    private final Environment env;
32
+
33
+    public ZipConnectApp(Environment env) {
34
+        this.env = env;
35
+    }
36
+
37
+    /**
38
+     * Initializes ZipConnect.
39
+     * <p>
40
+     * Spring profiles can be configured with a program argument --spring.profiles.active=your-active-profile
41
+     * <p>
42
+     * You can find more information on how profiles work with JHipster on <a href="https://www.jhipster.tech/profiles/">https://www.jhipster.tech/profiles/</a>.
43
+     */
44
+    @PostConstruct
45
+    public void initApplication() {
46
+        Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles());
47
+        if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
48
+            log.error("You have misconfigured your application! It should not run " +
49
+                "with both the 'dev' and 'prod' profiles at the same time.");
50
+        }
51
+        if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) {
52
+            log.error("You have misconfigured your application! It should not " +
53
+                "run with both the 'dev' and 'cloud' profiles at the same time.");
54
+        }
55
+    }
56
+
57
+    /**
58
+     * Main method, used to run the application.
59
+     *
60
+     * @param args the command line arguments
61
+     */
62
+    public static void main(String[] args) {
63
+        SpringApplication app = new SpringApplication(ZipConnectApp.class);
64
+        DefaultProfileUtil.addDefaultProfile(app);
65
+        Environment env = app.run(args).getEnvironment();
66
+        logApplicationStartup(env);
67
+    }
68
+
69
+    private static void logApplicationStartup(Environment env) {
70
+        String protocol = "http";
71
+        if (env.getProperty("server.ssl.key-store") != null) {
72
+            protocol = "https";
73
+        }
74
+        String serverPort = env.getProperty("server.port");
75
+        String contextPath = env.getProperty("server.servlet.context-path");
76
+        if (StringUtils.isBlank(contextPath)) {
77
+            contextPath = "/";
78
+        }
79
+        String hostAddress = "localhost";
80
+        try {
81
+            hostAddress = InetAddress.getLocalHost().getHostAddress();
82
+        } catch (UnknownHostException e) {
83
+            log.warn("The host name could not be determined, using `localhost` as fallback");
84
+        }
85
+        log.info("\n----------------------------------------------------------\n\t" +
86
+                "Application '{}' is running! Access URLs:\n\t" +
87
+                "Local: \t\t{}://localhost:{}{}\n\t" +
88
+                "External: \t{}://{}:{}{}\n\t" +
89
+                "Profile(s): \t{}\n----------------------------------------------------------",
90
+            env.getProperty("spring.application.name"),
91
+            protocol,
92
+            serverPort,
93
+            contextPath,
94
+            protocol,
95
+            hostAddress,
96
+            serverPort,
97
+            contextPath,
98
+            env.getActiveProfiles());
99
+    }
100
+}

+ 98
- 0
src/main/java/rocks/zipcode/io/aop/logging/LoggingAspect.java Zobrazit soubor

@@ -0,0 +1,98 @@
1
+package rocks.zipcode.io.aop.logging;
2
+
3
+import io.github.jhipster.config.JHipsterConstants;
4
+
5
+import org.aspectj.lang.JoinPoint;
6
+import org.aspectj.lang.ProceedingJoinPoint;
7
+import org.aspectj.lang.annotation.AfterThrowing;
8
+import org.aspectj.lang.annotation.Around;
9
+import org.aspectj.lang.annotation.Aspect;
10
+import org.aspectj.lang.annotation.Pointcut;
11
+import org.slf4j.Logger;
12
+import org.slf4j.LoggerFactory;
13
+import org.springframework.core.env.Environment;
14
+
15
+import java.util.Arrays;
16
+
17
+/**
18
+ * Aspect for logging execution of service and repository Spring components.
19
+ *
20
+ * By default, it only runs with the "dev" profile.
21
+ */
22
+@Aspect
23
+public class LoggingAspect {
24
+
25
+    private final Logger log = LoggerFactory.getLogger(this.getClass());
26
+
27
+    private final Environment env;
28
+
29
+    public LoggingAspect(Environment env) {
30
+        this.env = env;
31
+    }
32
+
33
+    /**
34
+     * Pointcut that matches all repositories, services and Web REST endpoints.
35
+     */
36
+    @Pointcut("within(@org.springframework.stereotype.Repository *)" +
37
+        " || within(@org.springframework.stereotype.Service *)" +
38
+        " || within(@org.springframework.web.bind.annotation.RestController *)")
39
+    public void springBeanPointcut() {
40
+        // Method is empty as this is just a Pointcut, the implementations are in the advices.
41
+    }
42
+
43
+    /**
44
+     * Pointcut that matches all Spring beans in the application's main packages.
45
+     */
46
+    @Pointcut("within(rocks.zipcode.io.repository..*)"+
47
+        " || within(rocks.zipcode.io.service..*)"+
48
+        " || within(rocks.zipcode.io.web.rest..*)")
49
+    public void applicationPackagePointcut() {
50
+        // Method is empty as this is just a Pointcut, the implementations are in the advices.
51
+    }
52
+
53
+    /**
54
+     * Advice that logs methods throwing exceptions.
55
+     *
56
+     * @param joinPoint join point for advice
57
+     * @param e exception
58
+     */
59
+    @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e")
60
+    public void logAfterThrowing(JoinPoint joinPoint, Throwable e) {
61
+        if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
62
+            log.error("Exception in {}.{}() with cause = \'{}\' and exception = \'{}\'", joinPoint.getSignature().getDeclaringTypeName(),
63
+                joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL", e.getMessage(), e);
64
+
65
+        } else {
66
+            log.error("Exception in {}.{}() with cause = {}", joinPoint.getSignature().getDeclaringTypeName(),
67
+                joinPoint.getSignature().getName(), e.getCause() != null? e.getCause() : "NULL");
68
+        }
69
+    }
70
+
71
+    /**
72
+     * Advice that logs when a method is entered and exited.
73
+     *
74
+     * @param joinPoint join point for advice
75
+     * @return result
76
+     * @throws Throwable throws IllegalArgumentException
77
+     */
78
+    @Around("applicationPackagePointcut() && springBeanPointcut()")
79
+    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
80
+        if (log.isDebugEnabled()) {
81
+            log.debug("Enter: {}.{}() with argument[s] = {}", joinPoint.getSignature().getDeclaringTypeName(),
82
+                joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs()));
83
+        }
84
+        try {
85
+            Object result = joinPoint.proceed();
86
+            if (log.isDebugEnabled()) {
87
+                log.debug("Exit: {}.{}() with result = {}", joinPoint.getSignature().getDeclaringTypeName(),
88
+                    joinPoint.getSignature().getName(), result);
89
+            }
90
+            return result;
91
+        } catch (IllegalArgumentException e) {
92
+            log.error("Illegal argument: {} in {}.{}()", Arrays.toString(joinPoint.getArgs()),
93
+                joinPoint.getSignature().getDeclaringTypeName(), joinPoint.getSignature().getName());
94
+
95
+            throw e;
96
+        }
97
+    }
98
+}

+ 14
- 0
src/main/java/rocks/zipcode/io/config/ApplicationProperties.java Zobrazit soubor

@@ -0,0 +1,14 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import org.springframework.boot.context.properties.ConfigurationProperties;
4
+
5
+/**
6
+ * Properties specific to Zip Connect.
7
+ * <p>
8
+ * Properties are configured in the application.yml file.
9
+ * See {@link io.github.jhipster.config.JHipsterProperties} for a good example.
10
+ */
11
+@ConfigurationProperties(prefix = "application", ignoreUnknownFields = false)
12
+public class ApplicationProperties {
13
+
14
+}

+ 59
- 0
src/main/java/rocks/zipcode/io/config/AsyncConfiguration.java Zobrazit soubor

@@ -0,0 +1,59 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor;
4
+import io.github.jhipster.config.JHipsterProperties;
5
+
6
+import org.slf4j.Logger;
7
+import org.slf4j.LoggerFactory;
8
+import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
9
+import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler;
10
+import org.springframework.context.annotation.Bean;
11
+import org.springframework.context.annotation.Configuration;
12
+import org.springframework.scheduling.annotation.*;
13
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
14
+import org.springframework.scheduling.annotation.SchedulingConfigurer;
15
+import org.springframework.scheduling.config.ScheduledTaskRegistrar;
16
+
17
+import java.util.concurrent.Executor;
18
+import java.util.concurrent.Executors;
19
+
20
+@Configuration
21
+@EnableAsync
22
+@EnableScheduling
23
+public class AsyncConfiguration implements AsyncConfigurer, SchedulingConfigurer {
24
+
25
+    private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class);
26
+
27
+    private final JHipsterProperties jHipsterProperties;
28
+
29
+    public AsyncConfiguration(JHipsterProperties jHipsterProperties) {
30
+        this.jHipsterProperties = jHipsterProperties;
31
+    }
32
+
33
+    @Override
34
+    @Bean(name = "taskExecutor")
35
+    public Executor getAsyncExecutor() {
36
+        log.debug("Creating Async Task Executor");
37
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
38
+        executor.setCorePoolSize(jHipsterProperties.getAsync().getCorePoolSize());
39
+        executor.setMaxPoolSize(jHipsterProperties.getAsync().getMaxPoolSize());
40
+        executor.setQueueCapacity(jHipsterProperties.getAsync().getQueueCapacity());
41
+        executor.setThreadNamePrefix("zip-connect-Executor-");
42
+        return new ExceptionHandlingAsyncTaskExecutor(executor);
43
+    }
44
+
45
+    @Override
46
+    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
47
+        return new SimpleAsyncUncaughtExceptionHandler();
48
+    }
49
+    
50
+    @Override
51
+    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
52
+        taskRegistrar.setScheduler(scheduledTaskExecutor());
53
+    }
54
+
55
+    @Bean
56
+    public Executor scheduledTaskExecutor() {
57
+        return Executors.newScheduledThreadPool(jHipsterProperties.getAsync().getCorePoolSize());
58
+    }
59
+}

+ 155
- 0
src/main/java/rocks/zipcode/io/config/CacheConfiguration.java Zobrazit soubor

@@ -0,0 +1,155 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.JHipsterConstants;
4
+import io.github.jhipster.config.JHipsterProperties;
5
+
6
+import com.hazelcast.config.*;
7
+import com.hazelcast.core.HazelcastInstance;
8
+import com.hazelcast.core.Hazelcast;
9
+
10
+import org.slf4j.Logger;
11
+import org.slf4j.LoggerFactory;
12
+import org.springframework.beans.factory.annotation.Autowired;
13
+import org.springframework.boot.autoconfigure.web.ServerProperties;
14
+
15
+import org.springframework.cache.CacheManager;
16
+import org.springframework.cache.annotation.EnableCaching;
17
+import org.springframework.cloud.client.ServiceInstance;
18
+import org.springframework.cloud.client.discovery.DiscoveryClient;
19
+import org.springframework.cloud.client.serviceregistry.Registration;
20
+import org.springframework.context.annotation.*;
21
+import org.springframework.core.env.Environment;
22
+
23
+import javax.annotation.PreDestroy;
24
+
25
+@Configuration
26
+@EnableCaching
27
+public class CacheConfiguration {
28
+
29
+    private final Logger log = LoggerFactory.getLogger(CacheConfiguration.class);
30
+
31
+    private final Environment env;
32
+
33
+    private final ServerProperties serverProperties;
34
+
35
+    private final DiscoveryClient discoveryClient;
36
+
37
+    private Registration registration;
38
+
39
+    public CacheConfiguration(Environment env, ServerProperties serverProperties, DiscoveryClient discoveryClient) {
40
+        this.env = env;
41
+        this.serverProperties = serverProperties;
42
+        this.discoveryClient = discoveryClient;
43
+    }
44
+
45
+    @Autowired(required = false)
46
+    public void setRegistration(Registration registration) {
47
+        this.registration = registration;
48
+    }
49
+
50
+    @PreDestroy
51
+    public void destroy() {
52
+        log.info("Closing Cache Manager");
53
+        Hazelcast.shutdownAll();
54
+    }
55
+
56
+    @Bean
57
+    public CacheManager cacheManager(HazelcastInstance hazelcastInstance) {
58
+        log.debug("Starting HazelcastCacheManager");
59
+        CacheManager cacheManager = new com.hazelcast.spring.cache.HazelcastCacheManager(hazelcastInstance);
60
+        return cacheManager;
61
+    }
62
+
63
+    @Bean
64
+    public HazelcastInstance hazelcastInstance(JHipsterProperties jHipsterProperties) {
65
+        log.debug("Configuring Hazelcast");
66
+        HazelcastInstance hazelCastInstance = Hazelcast.getHazelcastInstanceByName("ZipConnect");
67
+        if (hazelCastInstance != null) {
68
+            log.debug("Hazelcast already initialized");
69
+            return hazelCastInstance;
70
+        }
71
+        Config config = new Config();
72
+        config.setInstanceName("ZipConnect");
73
+        config.getNetworkConfig().getJoin().getMulticastConfig().setEnabled(false);
74
+        if (this.registration == null) {
75
+            log.warn("No discovery service is set up, Hazelcast cannot create a cluster.");
76
+        } else {
77
+            // The serviceId is by default the application's name,
78
+            // see the "spring.application.name" standard Spring property
79
+            String serviceId = registration.getServiceId();
80
+            log.debug("Configuring Hazelcast clustering for instanceId: {}", serviceId);
81
+            // In development, everything goes through 127.0.0.1, with a different port
82
+            if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
83
+                log.debug("Application is running with the \"dev\" profile, Hazelcast " +
84
+                          "cluster will only work with localhost instances");
85
+
86
+                System.setProperty("hazelcast.local.localAddress", "127.0.0.1");
87
+                config.getNetworkConfig().setPort(serverProperties.getPort() + 5701);
88
+                config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
89
+                for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
90
+                    String clusterMember = "127.0.0.1:" + (instance.getPort() + 5701);
91
+                    log.debug("Adding Hazelcast (dev) cluster member " + clusterMember);
92
+                    config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
93
+                }
94
+            } else { // Production configuration, one host per instance all using port 5701
95
+                config.getNetworkConfig().setPort(5701);
96
+                config.getNetworkConfig().getJoin().getTcpIpConfig().setEnabled(true);
97
+                for (ServiceInstance instance : discoveryClient.getInstances(serviceId)) {
98
+                    String clusterMember = instance.getHost() + ":5701";
99
+                    log.debug("Adding Hazelcast (prod) cluster member " + clusterMember);
100
+                    config.getNetworkConfig().getJoin().getTcpIpConfig().addMember(clusterMember);
101
+                }
102
+            }
103
+        }
104
+        config.getMapConfigs().put("default", initializeDefaultMapConfig(jHipsterProperties));
105
+
106
+        // Full reference is available at: http://docs.hazelcast.org/docs/management-center/3.9/manual/html/Deploying_and_Starting.html
107
+        config.setManagementCenterConfig(initializeDefaultManagementCenterConfig(jHipsterProperties));
108
+        config.getMapConfigs().put("rocks.zipcode.io.domain.*", initializeDomainMapConfig(jHipsterProperties));
109
+        return Hazelcast.newHazelcastInstance(config);
110
+    }
111
+
112
+    private ManagementCenterConfig initializeDefaultManagementCenterConfig(JHipsterProperties jHipsterProperties) {
113
+        ManagementCenterConfig managementCenterConfig = new ManagementCenterConfig();
114
+        managementCenterConfig.setEnabled(jHipsterProperties.getCache().getHazelcast().getManagementCenter().isEnabled());
115
+        managementCenterConfig.setUrl(jHipsterProperties.getCache().getHazelcast().getManagementCenter().getUrl());
116
+        managementCenterConfig.setUpdateInterval(jHipsterProperties.getCache().getHazelcast().getManagementCenter().getUpdateInterval());
117
+        return managementCenterConfig;
118
+    }
119
+
120
+    private MapConfig initializeDefaultMapConfig(JHipsterProperties jHipsterProperties) {
121
+        MapConfig mapConfig = new MapConfig();
122
+
123
+        /*
124
+        Number of backups. If 1 is set as the backup-count for example,
125
+        then all entries of the map will be copied to another JVM for
126
+        fail-safety. Valid numbers are 0 (no backup), 1, 2, 3.
127
+        */
128
+        mapConfig.setBackupCount(jHipsterProperties.getCache().getHazelcast().getBackupCount());
129
+
130
+        /*
131
+        Valid values are:
132
+        NONE (no eviction),
133
+        LRU (Least Recently Used),
134
+        LFU (Least Frequently Used).
135
+        NONE is the default.
136
+        */
137
+        mapConfig.setEvictionPolicy(EvictionPolicy.LRU);
138
+
139
+        /*
140
+        Maximum size of the map. When max size is reached,
141
+        map is evicted based on the policy defined.
142
+        Any integer between 0 and Integer.MAX_VALUE. 0 means
143
+        Integer.MAX_VALUE. Default is 0.
144
+        */
145
+        mapConfig.setMaxSizeConfig(new MaxSizeConfig(0, MaxSizeConfig.MaxSizePolicy.USED_HEAP_SIZE));
146
+
147
+        return mapConfig;
148
+    }
149
+
150
+    private MapConfig initializeDomainMapConfig(JHipsterProperties jHipsterProperties) {
151
+        MapConfig mapConfig = new MapConfig();
152
+        mapConfig.setTimeToLiveSeconds(jHipsterProperties.getCache().getHazelcast().getTimeToLiveSeconds());
153
+        return mapConfig;
154
+    }
155
+}

+ 29
- 0
src/main/java/rocks/zipcode/io/config/CloudDatabaseConfiguration.java Zobrazit soubor

@@ -0,0 +1,29 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.JHipsterConstants;
4
+
5
+import org.slf4j.Logger;
6
+import org.slf4j.LoggerFactory;
7
+import org.springframework.cache.CacheManager;
8
+import org.springframework.cloud.config.java.AbstractCloudConfig;
9
+import org.springframework.context.annotation.*;
10
+
11
+import javax.sql.DataSource;
12
+import org.springframework.boot.context.properties.ConfigurationProperties;
13
+
14
+
15
+@Configuration
16
+@Profile(JHipsterConstants.SPRING_PROFILE_CLOUD)
17
+public class CloudDatabaseConfiguration extends AbstractCloudConfig {
18
+
19
+    private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class);
20
+    
21
+    private final String CLOUD_CONFIGURATION_HIKARI_PREFIX = "spring.datasource.hikari";
22
+
23
+    @Bean
24
+    @ConfigurationProperties(CLOUD_CONFIGURATION_HIKARI_PREFIX)
25
+    public DataSource dataSource(CacheManager cacheManager) {
26
+        log.info("Configuring JDBC datasource from a cloud provider");
27
+        return connectionFactory().dataSource();
28
+    }
29
+}

+ 17
- 0
src/main/java/rocks/zipcode/io/config/Constants.java Zobrazit soubor

@@ -0,0 +1,17 @@
1
+package rocks.zipcode.io.config;
2
+
3
+/**
4
+ * Application constants.
5
+ */
6
+public final class Constants {
7
+
8
+    // Regex for acceptable logins
9
+    public static final String LOGIN_REGEX = "^[_.@A-Za-z0-9-]*$";
10
+
11
+    public static final String SYSTEM_ACCOUNT = "system";
12
+    public static final String ANONYMOUS_USER = "anonymoususer";
13
+    public static final String DEFAULT_LANGUAGE = "en";
14
+    
15
+    private Constants() {
16
+    }
17
+}

+ 60
- 0
src/main/java/rocks/zipcode/io/config/DatabaseConfiguration.java Zobrazit soubor

@@ -0,0 +1,60 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.JHipsterConstants;
4
+import io.github.jhipster.config.h2.H2ConfigurationHelper;
5
+import org.slf4j.Logger;
6
+import org.slf4j.LoggerFactory;
7
+import org.springframework.context.annotation.Bean;
8
+import org.springframework.context.annotation.Configuration;
9
+import org.springframework.context.annotation.Profile;
10
+
11
+import org.springframework.core.env.Environment;
12
+import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
13
+import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
14
+import org.springframework.transaction.annotation.EnableTransactionManagement;
15
+
16
+import java.sql.SQLException;
17
+import java.lang.NumberFormatException;
18
+
19
+@Configuration
20
+@EnableJpaRepositories("rocks.zipcode.io.repository")
21
+@EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware")
22
+@EnableTransactionManagement
23
+public class DatabaseConfiguration {
24
+
25
+    private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);
26
+
27
+    private final Environment env;
28
+
29
+    public DatabaseConfiguration(Environment env) {
30
+        this.env = env;
31
+    }
32
+
33
+    /**
34
+     * Open the TCP port for the H2 database, so it is available remotely.
35
+     *
36
+     * @return the H2 database TCP server
37
+     * @throws SQLException if the server failed to start
38
+     */
39
+    @Bean(initMethod = "start", destroyMethod = "stop")
40
+    @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
41
+    public Object h2TCPServer() throws SQLException {
42
+        String port = getValidPortForH2();
43
+        log.debug("H2 database is available on port {}", port);
44
+        return H2ConfigurationHelper.createServer(port);
45
+    }
46
+	
47
+    private String getValidPortForH2() throws NumberFormatException {
48
+        int port = Integer.parseInt(env.getProperty("server.port"));
49
+        if (port < 10000) {
50
+            port = 10000 + port;
51
+        } else {
52
+            if (port < 63536) {
53
+                port = port + 2000;
54
+            } else {
55
+                port = port - 2000;
56
+            }
57
+        }
58
+        return String.valueOf(port);
59
+    }
60
+}

+ 20
- 0
src/main/java/rocks/zipcode/io/config/DateTimeFormatConfiguration.java Zobrazit soubor

@@ -0,0 +1,20 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import org.springframework.context.annotation.Configuration;
4
+import org.springframework.format.FormatterRegistry;
5
+import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
6
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
7
+
8
+/**
9
+ * Configure the converters to use the ISO format for dates by default.
10
+ */
11
+@Configuration
12
+public class DateTimeFormatConfiguration implements WebMvcConfigurer {
13
+
14
+    @Override
15
+    public void addFormatters(FormatterRegistry registry) {
16
+        DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
17
+        registrar.setUseIsoFormat(true);
18
+        registrar.registerFormatters(registry);
19
+    }
20
+}

+ 51
- 0
src/main/java/rocks/zipcode/io/config/DefaultProfileUtil.java Zobrazit soubor

@@ -0,0 +1,51 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.JHipsterConstants;
4
+
5
+import org.springframework.boot.SpringApplication;
6
+import org.springframework.core.env.Environment;
7
+
8
+import java.util.*;
9
+
10
+/**
11
+ * Utility class to load a Spring profile to be used as default
12
+ * when there is no <code>spring.profiles.active</code> set in the environment or as command line argument.
13
+ * If the value is not available in <code>application.yml</code> then <code>dev</code> profile will be used as default.
14
+ */
15
+public final class DefaultProfileUtil {
16
+
17
+    private static final String SPRING_PROFILE_DEFAULT = "spring.profiles.default";
18
+
19
+    private DefaultProfileUtil() {
20
+    }
21
+
22
+    /**
23
+     * Set a default to use when no profile is configured.
24
+     *
25
+     * @param app the Spring application
26
+     */
27
+    public static void addDefaultProfile(SpringApplication app) {
28
+        Map<String, Object> defProperties = new HashMap<>();
29
+        /*
30
+        * The default profile to use when no other profiles are defined
31
+        * This cannot be set in the <code>application.yml</code> file.
32
+        * See https://github.com/spring-projects/spring-boot/issues/1219
33
+        */
34
+        defProperties.put(SPRING_PROFILE_DEFAULT, JHipsterConstants.SPRING_PROFILE_DEVELOPMENT);
35
+        app.setDefaultProperties(defProperties);
36
+    }
37
+
38
+    /**
39
+     * Get the profiles that are applied else get default profiles.
40
+     *
41
+     * @param env spring environment
42
+     * @return profiles
43
+     */
44
+    public static String[] getActiveProfiles(Environment env) {
45
+        String[] profiles = env.getActiveProfiles();
46
+        if (profiles.length == 0) {
47
+            return env.getDefaultProfiles();
48
+        }
49
+        return profiles;
50
+    }
51
+}

+ 63
- 0
src/main/java/rocks/zipcode/io/config/JacksonConfiguration.java Zobrazit soubor

@@ -0,0 +1,63 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import com.fasterxml.jackson.datatype.hibernate5.Hibernate5Module;
4
+import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
5
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
6
+import com.fasterxml.jackson.module.afterburner.AfterburnerModule;
7
+
8
+import org.springframework.context.annotation.Bean;
9
+import org.springframework.context.annotation.Configuration;
10
+import org.zalando.problem.ProblemModule;
11
+import org.zalando.problem.violations.ConstraintViolationProblemModule;
12
+
13
+@Configuration
14
+public class JacksonConfiguration {
15
+
16
+    /**
17
+     * Support for Java date and time API.
18
+     * @return the corresponding Jackson module.
19
+     */
20
+    @Bean
21
+    public JavaTimeModule javaTimeModule() {
22
+        return new JavaTimeModule();
23
+    }
24
+
25
+    @Bean
26
+    public Jdk8Module jdk8TimeModule() {
27
+        return new Jdk8Module();
28
+    }
29
+
30
+
31
+    /*
32
+     * Support for Hibernate types in Jackson.
33
+     */
34
+    @Bean
35
+    public Hibernate5Module hibernate5Module() {
36
+        return new Hibernate5Module();
37
+    }
38
+
39
+    /*
40
+     * Jackson Afterburner module to speed up serialization/deserialization.
41
+     */
42
+    @Bean
43
+    public AfterburnerModule afterburnerModule() {
44
+        return new AfterburnerModule();
45
+    }
46
+
47
+    /*
48
+     * Module for serialization/deserialization of RFC7807 Problem.
49
+     */
50
+    @Bean
51
+    ProblemModule problemModule() {
52
+        return new ProblemModule();
53
+    }
54
+
55
+    /*
56
+     * Module for serialization/deserialization of ConstraintViolationProblem.
57
+     */
58
+    @Bean
59
+    ConstraintViolationProblemModule constraintViolationProblemModule() {
60
+        return new ConstraintViolationProblemModule();
61
+    }
62
+
63
+}

+ 53
- 0
src/main/java/rocks/zipcode/io/config/LiquibaseConfiguration.java Zobrazit soubor

@@ -0,0 +1,53 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import javax.sql.DataSource;
4
+
5
+import org.slf4j.Logger;
6
+import org.slf4j.LoggerFactory;
7
+import org.springframework.beans.factory.annotation.Qualifier;
8
+import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties;
9
+import org.springframework.cache.CacheManager;
10
+import org.springframework.context.annotation.Bean;
11
+import org.springframework.context.annotation.Configuration;
12
+import org.springframework.core.env.Environment;
13
+import org.springframework.core.task.TaskExecutor;
14
+
15
+import io.github.jhipster.config.JHipsterConstants;
16
+import io.github.jhipster.config.liquibase.AsyncSpringLiquibase;
17
+import liquibase.integration.spring.SpringLiquibase;
18
+
19
+@Configuration
20
+public class LiquibaseConfiguration {
21
+
22
+    private final Logger log = LoggerFactory.getLogger(LiquibaseConfiguration.class);
23
+
24
+    private final Environment env;
25
+
26
+    private final CacheManager cacheManager;
27
+
28
+    public LiquibaseConfiguration(Environment env, CacheManager cacheManager) {
29
+        this.env = env;
30
+        this.cacheManager = cacheManager;
31
+    }
32
+
33
+    @Bean
34
+    public SpringLiquibase liquibase(@Qualifier("taskExecutor") TaskExecutor taskExecutor,
35
+            DataSource dataSource, LiquibaseProperties liquibaseProperties) {
36
+
37
+        // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
38
+        SpringLiquibase liquibase = new AsyncSpringLiquibase(taskExecutor, env);
39
+        liquibase.setDataSource(dataSource);
40
+        liquibase.setChangeLog("classpath:config/liquibase/master.xml");
41
+        liquibase.setContexts(liquibaseProperties.getContexts());
42
+        liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
43
+        liquibase.setDropFirst(liquibaseProperties.isDropFirst());
44
+        liquibase.setChangeLogParameters(liquibaseProperties.getParameters());
45
+        if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE)) {
46
+            liquibase.setShouldRun(false);
47
+        } else {
48
+            liquibase.setShouldRun(liquibaseProperties.isEnabled());
49
+            log.debug("Configuring Liquibase");
50
+        }
51
+        return liquibase;
52
+    }
53
+}

+ 27
- 0
src/main/java/rocks/zipcode/io/config/LocaleConfiguration.java Zobrazit soubor

@@ -0,0 +1,27 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.locale.AngularCookieLocaleResolver;
4
+
5
+import org.springframework.context.annotation.Bean;
6
+import org.springframework.context.annotation.Configuration;
7
+import org.springframework.web.servlet.LocaleResolver;
8
+import org.springframework.web.servlet.config.annotation.*;
9
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
10
+
11
+@Configuration
12
+public class LocaleConfiguration implements WebMvcConfigurer {
13
+
14
+    @Bean(name = "localeResolver")
15
+    public LocaleResolver localeResolver() {
16
+        AngularCookieLocaleResolver cookieLocaleResolver = new AngularCookieLocaleResolver();
17
+        cookieLocaleResolver.setCookieName("NG_TRANSLATE_LANG_KEY");
18
+        return cookieLocaleResolver;
19
+    }
20
+
21
+    @Override
22
+    public void addInterceptors(InterceptorRegistry registry) {
23
+        LocaleChangeInterceptor localeChangeInterceptor = new LocaleChangeInterceptor();
24
+        localeChangeInterceptor.setParamName("language");
25
+        registry.addInterceptor(localeChangeInterceptor);
26
+    }
27
+}

+ 19
- 0
src/main/java/rocks/zipcode/io/config/LoggingAspectConfiguration.java Zobrazit soubor

@@ -0,0 +1,19 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import rocks.zipcode.io.aop.logging.LoggingAspect;
4
+
5
+import io.github.jhipster.config.JHipsterConstants;
6
+
7
+import org.springframework.context.annotation.*;
8
+import org.springframework.core.env.Environment;
9
+
10
+@Configuration
11
+@EnableAspectJAutoProxy
12
+public class LoggingAspectConfiguration {
13
+
14
+    @Bean
15
+    @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)
16
+    public LoggingAspect loggingAspect(Environment env) {
17
+        return new LoggingAspect(env);
18
+    }
19
+}

+ 158
- 0
src/main/java/rocks/zipcode/io/config/LoggingConfiguration.java Zobrazit soubor

@@ -0,0 +1,158 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import java.net.InetSocketAddress;
4
+import java.util.Iterator;
5
+
6
+import io.github.jhipster.config.JHipsterProperties;
7
+
8
+import ch.qos.logback.classic.AsyncAppender;
9
+import ch.qos.logback.classic.Level;
10
+import ch.qos.logback.classic.LoggerContext;
11
+import ch.qos.logback.classic.boolex.OnMarkerEvaluator;
12
+import ch.qos.logback.classic.spi.ILoggingEvent;
13
+import ch.qos.logback.classic.spi.LoggerContextListener;
14
+import ch.qos.logback.core.Appender;
15
+import ch.qos.logback.core.filter.EvaluatorFilter;
16
+import ch.qos.logback.core.spi.ContextAwareBase;
17
+import ch.qos.logback.core.spi.FilterReply;
18
+import net.logstash.logback.appender.LogstashTcpSocketAppender;
19
+import net.logstash.logback.encoder.LogstashEncoder;
20
+import net.logstash.logback.stacktrace.ShortenedThrowableConverter;
21
+import org.slf4j.Logger;
22
+import org.slf4j.LoggerFactory;
23
+import org.springframework.beans.factory.annotation.Value;
24
+import org.springframework.cloud.context.config.annotation.RefreshScope;
25
+import org.springframework.context.annotation.Configuration;
26
+
27
+@Configuration
28
+@RefreshScope
29
+public class LoggingConfiguration {
30
+
31
+    private static final String LOGSTASH_APPENDER_NAME = "LOGSTASH";
32
+
33
+    private static final String ASYNC_LOGSTASH_APPENDER_NAME = "ASYNC_LOGSTASH";
34
+
35
+    private final Logger log = LoggerFactory.getLogger(LoggingConfiguration.class);
36
+
37
+    private LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
38
+
39
+    private final String appName;
40
+
41
+    private final String serverPort;
42
+
43
+    private final JHipsterProperties jHipsterProperties;
44
+
45
+    public LoggingConfiguration(@Value("${spring.application.name}") String appName, @Value("${server.port}") String serverPort,
46
+         JHipsterProperties jHipsterProperties) {
47
+        this.appName = appName;
48
+        this.serverPort = serverPort;
49
+        this.jHipsterProperties = jHipsterProperties;
50
+        if (jHipsterProperties.getLogging().getLogstash().isEnabled()) {
51
+            addLogstashAppender(context);
52
+            addContextListener(context);
53
+        }
54
+        if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
55
+            setMetricsMarkerLogbackFilter(context);
56
+        }
57
+    }
58
+
59
+    private void addContextListener(LoggerContext context) {
60
+        LogbackLoggerContextListener loggerContextListener = new LogbackLoggerContextListener();
61
+        loggerContextListener.setContext(context);
62
+        context.addListener(loggerContextListener);
63
+    }
64
+
65
+    private void addLogstashAppender(LoggerContext context) {
66
+        log.info("Initializing Logstash logging");
67
+
68
+        LogstashTcpSocketAppender logstashAppender = new LogstashTcpSocketAppender();
69
+        logstashAppender.setName(LOGSTASH_APPENDER_NAME);
70
+        logstashAppender.setContext(context);
71
+        String customFields = "{\"app_name\":\"" + appName + "\",\"app_port\":\"" + serverPort + "\"}";
72
+
73
+        // More documentation is available at: https://github.com/logstash/logstash-logback-encoder
74
+        LogstashEncoder logstashEncoder = new LogstashEncoder();
75
+        // Set the Logstash appender config from JHipster properties
76
+        logstashEncoder.setCustomFields(customFields);
77
+        // Set the Logstash appender config from JHipster properties
78
+        logstashAppender.addDestinations(new InetSocketAddress(jHipsterProperties.getLogging().getLogstash().getHost(), jHipsterProperties.getLogging().getLogstash().getPort()));
79
+
80
+        ShortenedThrowableConverter throwableConverter = new ShortenedThrowableConverter();
81
+        throwableConverter.setRootCauseFirst(true);
82
+        logstashEncoder.setThrowableConverter(throwableConverter);
83
+        logstashEncoder.setCustomFields(customFields);
84
+
85
+        logstashAppender.setEncoder(logstashEncoder);
86
+        logstashAppender.start();
87
+
88
+        // Wrap the appender in an Async appender for performance
89
+        AsyncAppender asyncLogstashAppender = new AsyncAppender();
90
+        asyncLogstashAppender.setContext(context);
91
+        asyncLogstashAppender.setName(ASYNC_LOGSTASH_APPENDER_NAME);
92
+        asyncLogstashAppender.setQueueSize(jHipsterProperties.getLogging().getLogstash().getQueueSize());
93
+        asyncLogstashAppender.addAppender(logstashAppender);
94
+        asyncLogstashAppender.start();
95
+
96
+        context.getLogger("ROOT").addAppender(asyncLogstashAppender);
97
+    }
98
+
99
+    // Configure a log filter to remove "metrics" logs from all appenders except the "LOGSTASH" appender
100
+    private void setMetricsMarkerLogbackFilter(LoggerContext context) {
101
+        log.info("Filtering metrics logs from all appenders except the {} appender", LOGSTASH_APPENDER_NAME);
102
+        OnMarkerEvaluator onMarkerMetricsEvaluator = new OnMarkerEvaluator();
103
+        onMarkerMetricsEvaluator.setContext(context);
104
+        onMarkerMetricsEvaluator.addMarker("metrics");
105
+        onMarkerMetricsEvaluator.start();
106
+        EvaluatorFilter<ILoggingEvent> metricsFilter = new EvaluatorFilter<>();
107
+        metricsFilter.setContext(context);
108
+        metricsFilter.setEvaluator(onMarkerMetricsEvaluator);
109
+        metricsFilter.setOnMatch(FilterReply.DENY);
110
+        metricsFilter.start();
111
+
112
+        for (ch.qos.logback.classic.Logger logger : context.getLoggerList()) {
113
+            for (Iterator<Appender<ILoggingEvent>> it = logger.iteratorForAppenders(); it.hasNext();) {
114
+                Appender<ILoggingEvent> appender = it.next();
115
+                if (!appender.getName().equals(ASYNC_LOGSTASH_APPENDER_NAME)) {
116
+                    log.debug("Filter metrics logs from the {} appender", appender.getName());
117
+                    appender.setContext(context);
118
+                    appender.addFilter(metricsFilter);
119
+                    appender.start();
120
+                }
121
+            }
122
+        }
123
+    }
124
+
125
+    /**
126
+     * Logback configuration is achieved by configuration file and API.
127
+     * When configuration file change is detected, the configuration is reset.
128
+     * This listener ensures that the programmatic configuration is also re-applied after reset.
129
+     */
130
+    class LogbackLoggerContextListener extends ContextAwareBase implements LoggerContextListener {
131
+
132
+        @Override
133
+        public boolean isResetResistant() {
134
+            return true;
135
+        }
136
+
137
+        @Override
138
+        public void onStart(LoggerContext context) {
139
+            addLogstashAppender(context);
140
+        }
141
+
142
+        @Override
143
+        public void onReset(LoggerContext context) {
144
+            addLogstashAppender(context);
145
+        }
146
+
147
+        @Override
148
+        public void onStop(LoggerContext context) {
149
+            // Nothing to do.
150
+        }
151
+
152
+        @Override
153
+        public void onLevelChange(ch.qos.logback.classic.Logger logger, Level level) {
154
+            // Nothing to do.
155
+        }
156
+    }
157
+
158
+}

+ 119
- 0
src/main/java/rocks/zipcode/io/config/MetricsConfiguration.java Zobrazit soubor

@@ -0,0 +1,119 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import io.github.jhipster.config.JHipsterProperties;
4
+
5
+import com.codahale.metrics.JmxReporter;
6
+import com.codahale.metrics.JvmAttributeGaugeSet;
7
+import com.codahale.metrics.MetricRegistry;
8
+import com.codahale.metrics.Slf4jReporter;
9
+import com.codahale.metrics.health.HealthCheckRegistry;
10
+import com.codahale.metrics.jvm.*;
11
+import com.ryantenney.metrics.spring.config.annotation.EnableMetrics;
12
+import com.ryantenney.metrics.spring.config.annotation.MetricsConfigurerAdapter;
13
+import com.zaxxer.hikari.HikariDataSource;
14
+import io.prometheus.client.CollectorRegistry;
15
+import io.prometheus.client.dropwizard.DropwizardExports;
16
+import io.prometheus.client.exporter.MetricsServlet;
17
+import org.slf4j.Logger;
18
+import org.slf4j.LoggerFactory;
19
+import org.slf4j.Marker;
20
+import org.slf4j.MarkerFactory;
21
+import org.springframework.beans.factory.annotation.Autowired;
22
+import org.springframework.boot.web.servlet.ServletContextInitializer;
23
+import org.springframework.context.annotation.*;
24
+
25
+import javax.annotation.PostConstruct;
26
+import javax.servlet.ServletContext;
27
+import java.lang.management.ManagementFactory;
28
+import java.util.concurrent.TimeUnit;
29
+
30
+@Configuration
31
+@EnableMetrics(proxyTargetClass = true)
32
+public class MetricsConfiguration extends MetricsConfigurerAdapter implements ServletContextInitializer {
33
+
34
+    private static final String PROP_METRIC_REG_JVM_MEMORY = "jvm.memory";
35
+    private static final String PROP_METRIC_REG_JVM_GARBAGE = "jvm.garbage";
36
+    private static final String PROP_METRIC_REG_JVM_THREADS = "jvm.threads";
37
+    private static final String PROP_METRIC_REG_JVM_FILES = "jvm.files";
38
+    private static final String PROP_METRIC_REG_JVM_BUFFERS = "jvm.buffers";
39
+    private static final String PROP_METRIC_REG_JVM_ATTRIBUTE_SET = "jvm.attributes";
40
+
41
+    private final Logger log = LoggerFactory.getLogger(MetricsConfiguration.class);
42
+
43
+    private MetricRegistry metricRegistry = new MetricRegistry();
44
+
45
+    private HealthCheckRegistry healthCheckRegistry = new HealthCheckRegistry();
46
+
47
+    private final JHipsterProperties jHipsterProperties;
48
+
49
+    private HikariDataSource hikariDataSource;
50
+
51
+    public MetricsConfiguration(JHipsterProperties jHipsterProperties) {
52
+        this.jHipsterProperties = jHipsterProperties;
53
+    }
54
+
55
+    @Autowired(required = false)
56
+    public void setHikariDataSource(HikariDataSource hikariDataSource) {
57
+        this.hikariDataSource = hikariDataSource;
58
+    }
59
+
60
+    @Override
61
+    @Bean
62
+    public MetricRegistry getMetricRegistry() {
63
+        return metricRegistry;
64
+    }
65
+
66
+    @Override
67
+    @Bean
68
+    public HealthCheckRegistry getHealthCheckRegistry() {
69
+        return healthCheckRegistry;
70
+    }
71
+
72
+    @PostConstruct
73
+    public void init() {
74
+        log.debug("Registering JVM gauges");
75
+        metricRegistry.register(PROP_METRIC_REG_JVM_MEMORY, new MemoryUsageGaugeSet());
76
+        metricRegistry.register(PROP_METRIC_REG_JVM_GARBAGE, new GarbageCollectorMetricSet());
77
+        metricRegistry.register(PROP_METRIC_REG_JVM_THREADS, new ThreadStatesGaugeSet());
78
+        metricRegistry.register(PROP_METRIC_REG_JVM_FILES, new FileDescriptorRatioGauge());
79
+        metricRegistry.register(PROP_METRIC_REG_JVM_BUFFERS, new BufferPoolMetricSet(ManagementFactory.getPlatformMBeanServer()));
80
+        metricRegistry.register(PROP_METRIC_REG_JVM_ATTRIBUTE_SET, new JvmAttributeGaugeSet());
81
+        if (hikariDataSource != null) {
82
+            log.debug("Monitoring the datasource");
83
+            // remove the factory created by HikariDataSourceMetricsPostProcessor until JHipster migrate to Micrometer
84
+            hikariDataSource.setMetricsTrackerFactory(null);
85
+            hikariDataSource.setMetricRegistry(metricRegistry);
86
+        }
87
+        if (jHipsterProperties.getMetrics().getJmx().isEnabled()) {
88
+            log.debug("Initializing Metrics JMX reporting");
89
+            JmxReporter jmxReporter = JmxReporter.forRegistry(metricRegistry).build();
90
+            jmxReporter.start();
91
+        }
92
+        if (jHipsterProperties.getMetrics().getLogs().isEnabled()) {
93
+            log.info("Initializing Metrics Log reporting");
94
+            Marker metricsMarker = MarkerFactory.getMarker("metrics");
95
+            final Slf4jReporter reporter = Slf4jReporter.forRegistry(metricRegistry)
96
+                .outputTo(LoggerFactory.getLogger("metrics"))
97
+                .markWith(metricsMarker)
98
+                .convertRatesTo(TimeUnit.SECONDS)
99
+                .convertDurationsTo(TimeUnit.MILLISECONDS)
100
+                .build();
101
+            reporter.start(jHipsterProperties.getMetrics().getLogs().getReportFrequency(), TimeUnit.SECONDS);
102
+        }
103
+    }
104
+
105
+    @Override
106
+    public void onStartup(ServletContext servletContext) {
107
+
108
+        if (jHipsterProperties.getMetrics().getPrometheus().isEnabled()) {
109
+            String endpoint = jHipsterProperties.getMetrics().getPrometheus().getEndpoint();
110
+
111
+            log.debug("Initializing prometheus metrics exporting via {}", endpoint);
112
+
113
+            CollectorRegistry.defaultRegistry.register(new DropwizardExports(metricRegistry));
114
+            servletContext
115
+                .addServlet("prometheusMetrics", new MetricsServlet(CollectorRegistry.defaultRegistry))
116
+                .addMapping(endpoint);
117
+        }
118
+    }
119
+}

+ 121
- 0
src/main/java/rocks/zipcode/io/config/SecurityConfiguration.java Zobrazit soubor

@@ -0,0 +1,121 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import rocks.zipcode.io.security.*;
4
+import rocks.zipcode.io.security.jwt.*;
5
+
6
+import org.springframework.beans.factory.BeanInitializationException;
7
+import org.springframework.context.annotation.Bean;
8
+import org.springframework.context.annotation.Configuration;
9
+import org.springframework.context.annotation.Import;
10
+import org.springframework.http.HttpMethod;
11
+import org.springframework.security.authentication.AuthenticationManager;
12
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
13
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
14
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
15
+import org.springframework.security.config.annotation.web.builders.WebSecurity;
16
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
17
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
18
+import org.springframework.security.config.http.SessionCreationPolicy;
19
+import org.springframework.security.core.userdetails.UserDetailsService;
20
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
21
+import org.springframework.security.crypto.password.PasswordEncoder;
22
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
23
+import org.springframework.web.filter.CorsFilter;
24
+import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;
25
+
26
+import javax.annotation.PostConstruct;
27
+
28
+@Configuration
29
+@EnableWebSecurity
30
+@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
31
+@Import(SecurityProblemSupport.class)
32
+public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
33
+
34
+    private final AuthenticationManagerBuilder authenticationManagerBuilder;
35
+
36
+    private final UserDetailsService userDetailsService;
37
+
38
+    private final TokenProvider tokenProvider;
39
+
40
+    private final CorsFilter corsFilter;
41
+
42
+    private final SecurityProblemSupport problemSupport;
43
+
44
+    public SecurityConfiguration(AuthenticationManagerBuilder authenticationManagerBuilder, UserDetailsService userDetailsService, TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) {
45
+        this.authenticationManagerBuilder = authenticationManagerBuilder;
46
+        this.userDetailsService = userDetailsService;
47
+        this.tokenProvider = tokenProvider;
48
+        this.corsFilter = corsFilter;
49
+        this.problemSupport = problemSupport;
50
+    }
51
+
52
+    @PostConstruct
53
+    public void init() {
54
+        try {
55
+            authenticationManagerBuilder
56
+                .userDetailsService(userDetailsService)
57
+                .passwordEncoder(passwordEncoder());
58
+        } catch (Exception e) {
59
+            throw new BeanInitializationException("Security configuration failed", e);
60
+        }
61
+    }
62
+
63
+    @Override
64
+    @Bean
65
+    public AuthenticationManager authenticationManagerBean() throws Exception {
66
+        return super.authenticationManagerBean();
67
+    }
68
+
69
+    @Bean
70
+    public PasswordEncoder passwordEncoder() {
71
+        return new BCryptPasswordEncoder();
72
+    }
73
+
74
+    @Override
75
+    public void configure(WebSecurity web) throws Exception {
76
+        web.ignoring()
77
+            .antMatchers(HttpMethod.OPTIONS, "/**")
78
+            .antMatchers("/app/**/*.{js,html}")
79
+            .antMatchers("/i18n/**")
80
+            .antMatchers("/content/**")
81
+            .antMatchers("/h2-console/**")
82
+            .antMatchers("/swagger-ui/index.html")
83
+            .antMatchers("/test/**");
84
+    }
85
+
86
+    @Override
87
+    public void configure(HttpSecurity http) throws Exception {
88
+        http
89
+            .csrf()
90
+            .disable()
91
+            .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class)
92
+            .exceptionHandling()
93
+            .authenticationEntryPoint(problemSupport)
94
+            .accessDeniedHandler(problemSupport)
95
+        .and()
96
+            .headers()
97
+            .frameOptions()
98
+            .disable()
99
+        .and()
100
+            .sessionManagement()
101
+            .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
102
+        .and()
103
+            .authorizeRequests()
104
+            .antMatchers("/api/register").permitAll()
105
+            .antMatchers("/api/activate").permitAll()
106
+            .antMatchers("/api/authenticate").permitAll()
107
+            .antMatchers("/api/account/reset-password/init").permitAll()
108
+            .antMatchers("/api/account/reset-password/finish").permitAll()
109
+            .antMatchers("/api/**").authenticated()
110
+            .antMatchers("/management/health").permitAll()
111
+            .antMatchers("/management/info").permitAll()
112
+            .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
113
+        .and()
114
+            .apply(securityConfigurerAdapter());
115
+
116
+    }
117
+
118
+    private JWTConfigurer securityConfigurerAdapter() {
119
+        return new JWTConfigurer(tokenProvider);
120
+    }
121
+}

+ 206
- 0
src/main/java/rocks/zipcode/io/config/WebConfigurer.java Zobrazit soubor

@@ -0,0 +1,206 @@
1
+package rocks.zipcode.io.config;
2
+
3
+import com.codahale.metrics.MetricRegistry;
4
+import com.codahale.metrics.servlet.InstrumentedFilter;
5
+import com.codahale.metrics.servlets.MetricsServlet;
6
+import io.github.jhipster.config.JHipsterConstants;
7
+import io.github.jhipster.config.JHipsterProperties;
8
+import io.github.jhipster.config.h2.H2ConfigurationHelper;
9
+import io.github.jhipster.web.filter.CachingHttpHeadersFilter;
10
+import io.undertow.UndertowOptions;
11
+import org.slf4j.Logger;
12
+import org.slf4j.LoggerFactory;
13
+import org.springframework.beans.factory.annotation.Autowired;
14
+import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
15
+import org.springframework.boot.web.server.*;
16
+import org.springframework.boot.web.servlet.ServletContextInitializer;
17
+import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory;
18
+import org.springframework.context.annotation.Bean;
19
+import org.springframework.context.annotation.Configuration;
20
+import org.springframework.core.env.Environment;
21
+import org.springframework.http.MediaType;
22
+import org.springframework.web.cors.CorsConfiguration;
23
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
24
+import org.springframework.web.filter.CorsFilter;
25
+
26
+import javax.servlet.*;
27
+import java.io.File;
28
+import java.io.UnsupportedEncodingException;
29
+import java.nio.charset.StandardCharsets;
30
+import java.nio.file.Paths;
31
+import java.util.*;
32
+
33
+import static java.net.URLDecoder.decode;
34
+
35
+/**
36
+ * Configuration of web application with Servlet 3.0 APIs.
37
+ */
38
+@Configuration
39
+public class WebConfigurer implements ServletContextInitializer, WebServerFactoryCustomizer<WebServerFactory> {
40
+
41
+    private final Logger log = LoggerFactory.getLogger(WebConfigurer.class);
42
+
43
+    private final Environment env;
44
+
45
+    private final JHipsterProperties jHipsterProperties;
46
+
47
+    private MetricRegistry metricRegistry;
48
+
49
+    public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties) {
50
+
51
+        this.env = env;
52
+        this.jHipsterProperties = jHipsterProperties;
53
+    }
54
+
55
+    @Override
56
+    public void onStartup(ServletContext servletContext) throws ServletException {
57
+        if (env.getActiveProfiles().length != 0) {
58
+            log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles());
59
+        }
60
+        EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC);
61
+        initMetrics(servletContext, disps);
62
+        if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) {
63
+            initCachingHttpHeadersFilter(servletContext, disps);
64
+        }
65
+        if (env.acceptsProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT)) {
66
+            initH2Console(servletContext);
67
+        }
68
+        log.info("Web application fully configured");
69
+    }
70
+
71
+    /**
72
+     * Customize the Servlet engine: Mime types, the document root, the cache.
73
+     */
74
+    @Override
75
+    public void customize(WebServerFactory server) {
76
+        setMimeMappings(server);
77
+        // When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets.
78
+        setLocationForStaticAssets(server);
79
+
80
+        /*
81
+         * Enable HTTP/2 for Undertow - https://twitter.com/ankinson/status/829256167700492288
82
+         * HTTP/2 requires HTTPS, so HTTP requests will fallback to HTTP/1.1.
83
+         * See the JHipsterProperties class and your application-*.yml configuration files
84
+         * for more information.
85
+         */
86
+        if (jHipsterProperties.getHttp().getVersion().equals(JHipsterProperties.Http.Version.V_2_0) &&
87
+            server instanceof UndertowServletWebServerFactory) {
88
+
89
+            ((UndertowServletWebServerFactory) server)
90
+                .addBuilderCustomizers(builder ->
91
+                    builder.setServerOption(UndertowOptions.ENABLE_HTTP2, true));
92
+        }
93
+    }
94
+
95
+    private void setMimeMappings(WebServerFactory server) {
96
+        if (server instanceof ConfigurableServletWebServerFactory) {
97
+            MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT);
98
+            // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711
99
+            mappings.add("html", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase());
100
+            // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64
101
+            mappings.add("json", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase());
102
+            ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server;
103
+            servletWebServer.setMimeMappings(mappings);
104
+        }
105
+    }
106
+
107
+    private void setLocationForStaticAssets(WebServerFactory server) {
108
+        if (server instanceof ConfigurableServletWebServerFactory) {
109
+            ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server;
110
+            File root;
111
+            String prefixPath = resolvePathPrefix();
112
+            root = new File(prefixPath + "target/www/");
113
+            if (root.exists() && root.isDirectory()) {
114
+                servletWebServer.setDocumentRoot(root);
115
+            }
116
+        }
117
+    }
118
+
119
+    /**
120
+     * Resolve path prefix to static resources.
121
+     */
122
+    private String resolvePathPrefix() {
123
+        String fullExecutablePath;
124
+        try {
125
+            fullExecutablePath = decode(this.getClass().getResource("").getPath(), StandardCharsets.UTF_8.name());
126
+        } catch (UnsupportedEncodingException e) {
127
+            /* try without decoding if this ever happens */
128
+            fullExecutablePath = this.getClass().getResource("").getPath();
129
+        }
130
+        String rootPath = Paths.get(".").toUri().normalize().getPath();
131
+        String extractedPath = fullExecutablePath.replace(rootPath, "");
132
+        int extractionEndIndex = extractedPath.indexOf("target/");
133
+        if (extractionEndIndex <= 0) {
134
+            return "";
135
+        }
136
+        return extractedPath.substring(0, extractionEndIndex);
137
+    }
138
+
139
+    /**
140
+     * Initializes the caching HTTP Headers Filter.
141
+     */
142
+    private void initCachingHttpHeadersFilter(ServletContext servletContext,
143
+                                              EnumSet<DispatcherType> disps) {
144
+        log.debug("Registering Caching HTTP Headers Filter");
145
+        FilterRegistration.Dynamic cachingHttpHeadersFilter =
146
+            servletContext.addFilter("cachingHttpHeadersFilter",
147
+                new CachingHttpHeadersFilter(jHipsterProperties));
148
+
149
+        cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/i18n/*");
150
+        cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*");
151
+        cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*");
152
+        cachingHttpHeadersFilter.setAsyncSupported(true);
153
+    }
154
+
155
+    /**
156
+     * Initializes Metrics.
157
+     */
158
+    private void initMetrics(ServletContext servletContext, EnumSet<DispatcherType> disps) {
159
+        log.debug("Initializing Metrics registries");
160
+        servletContext.setAttribute(InstrumentedFilter.REGISTRY_ATTRIBUTE,
161
+            metricRegistry);
162
+        servletContext.setAttribute(MetricsServlet.METRICS_REGISTRY,
163
+            metricRegistry);
164
+
165
+        log.debug("Registering Metrics Filter");
166
+        FilterRegistration.Dynamic metricsFilter = servletContext.addFilter("webappMetricsFilter",
167
+            new InstrumentedFilter());
168
+
169
+        metricsFilter.addMappingForUrlPatterns(disps, true, "/*");
170
+        metricsFilter.setAsyncSupported(true);
171
+
172
+        log.debug("Registering Metrics Servlet");
173
+        ServletRegistration.Dynamic metricsAdminServlet =
174
+            servletContext.addServlet("metricsServlet", new MetricsServlet());
175
+
176
+        metricsAdminServlet.addMapping("/management/metrics/*");
177
+        metricsAdminServlet.setAsyncSupported(true);
178
+        metricsAdminServlet.setLoadOnStartup(2);
179
+    }
180
+
181
+    @Bean
182
+    public CorsFilter corsFilter() {
183
+        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
184
+        CorsConfiguration config = jHipsterProperties.getCors();
185
+        if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) {
186
+            log.debug("Registering CORS filter");
187
+            source.registerCorsConfiguration("/api/**", config);
188
+            source.registerCorsConfiguration("/management/**", config);
189
+            source.registerCorsConfiguration("/v2/api-docs", config);
190
+        }
191
+        return new CorsFilter(source);
192
+    }
193
+
194
+    /**
195
+     * Initializes H2 console.
196
+     */
197
+    private void initH2Console(ServletContext servletContext) {
198
+        log.debug("Initialize H2 console");
199
+        H2ConfigurationHelper.initH2Console(servletContext);
200
+    }
201
+
202
+    @Autowired(required = false)
203
+    public void setMetricRegistry(MetricRegistry metricRegistry) {
204
+        this.metricRegistry = metricRegistry;
205
+    }
206
+}

+ 86
- 0
src/main/java/rocks/zipcode/io/config/audit/AuditEventConverter.java Zobrazit soubor

@@ -0,0 +1,86 @@
1
+package rocks.zipcode.io.config.audit;
2
+
3
+import rocks.zipcode.io.domain.PersistentAuditEvent;
4
+
5
+import org.springframework.boot.actuate.audit.AuditEvent;
6
+import org.springframework.security.web.authentication.WebAuthenticationDetails;
7
+import org.springframework.stereotype.Component;
8
+
9
+import java.util.*;
10
+
11
+@Component
12
+public class AuditEventConverter {
13
+
14
+    /**
15
+     * Convert a list of PersistentAuditEvent to a list of AuditEvent
16
+     *
17
+     * @param persistentAuditEvents the list to convert
18
+     * @return the converted list.
19
+     */
20
+    public List<AuditEvent> convertToAuditEvent(Iterable<PersistentAuditEvent> persistentAuditEvents) {
21
+        if (persistentAuditEvents == null) {
22
+            return Collections.emptyList();
23
+        }
24
+        List<AuditEvent> auditEvents = new ArrayList<>();
25
+        for (PersistentAuditEvent persistentAuditEvent : persistentAuditEvents) {
26
+            auditEvents.add(convertToAuditEvent(persistentAuditEvent));
27
+        }
28
+        return auditEvents;
29
+    }
30
+
31
+    /**
32
+     * Convert a PersistentAuditEvent to an AuditEvent
33
+     *
34
+     * @param persistentAuditEvent the event to convert
35
+     * @return the converted list.
36
+     */
37
+    public AuditEvent convertToAuditEvent(PersistentAuditEvent persistentAuditEvent) {
38
+        if (persistentAuditEvent == null) {
39
+            return null;
40
+        }
41
+        return new AuditEvent(persistentAuditEvent.getAuditEventDate(), persistentAuditEvent.getPrincipal(),
42
+            persistentAuditEvent.getAuditEventType(), convertDataToObjects(persistentAuditEvent.getData()));
43
+    }
44
+
45
+    /**
46
+     * Internal conversion. This is needed to support the current SpringBoot actuator AuditEventRepository interface
47
+     *
48
+     * @param data the data to convert
49
+     * @return a map of String, Object
50
+     */
51
+    public Map<String, Object> convertDataToObjects(Map<String, String> data) {
52
+        Map<String, Object> results = new HashMap<>();
53
+
54
+        if (data != null) {
55
+            for (Map.Entry<String, String> entry : data.entrySet()) {
56
+                results.put(entry.getKey(), entry.getValue());
57
+            }
58
+        }
59
+        return results;
60
+    }
61
+
62
+    /**
63
+     * Internal conversion. This method will allow to save additional data.
64
+     * By default, it will save the object as string
65
+     *
66
+     * @param data the data to convert
67
+     * @return a map of String, String
68
+     */
69
+    public Map<String, String> convertDataToStrings(Map<String, Object> data) {
70
+        Map<String, String> results = new HashMap<>();
71
+
72
+        if (data != null) {
73
+            for (Map.Entry<String, Object> entry : data.entrySet()) {
74
+                // Extract the data that will be saved.
75
+                if (entry.getValue() instanceof WebAuthenticationDetails) {
76
+                    WebAuthenticationDetails authenticationDetails = (WebAuthenticationDetails) entry.getValue();
77
+                    results.put("remoteAddress", authenticationDetails.getRemoteAddress());
78
+                    results.put("sessionId", authenticationDetails.getSessionId());
79
+                } else {
80
+                    results.put(entry.getKey(), Objects.toString(entry.getValue()));
81
+                }
82
+            }
83
+        }
84
+        return results;
85
+    }
86
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/config/audit/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Audit specific code.
3
+ */
4
+package rocks.zipcode.io.config.audit;

+ 4
- 0
src/main/java/rocks/zipcode/io/config/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Spring Framework configuration files.
3
+ */
4
+package rocks.zipcode.io.config;

+ 79
- 0
src/main/java/rocks/zipcode/io/domain/AbstractAuditingEntity.java Zobrazit soubor

@@ -0,0 +1,79 @@
1
+package rocks.zipcode.io.domain;
2
+
3
+import com.fasterxml.jackson.annotation.JsonIgnore;
4
+import org.hibernate.envers.Audited;
5
+import org.springframework.data.annotation.CreatedBy;
6
+import org.springframework.data.annotation.CreatedDate;
7
+import org.springframework.data.annotation.LastModifiedBy;
8
+import org.springframework.data.annotation.LastModifiedDate;
9
+import org.springframework.data.jpa.domain.support.AuditingEntityListener;
10
+
11
+import java.io.Serializable;
12
+import java.time.Instant;
13
+import javax.persistence.Column;
14
+import javax.persistence.EntityListeners;
15
+import javax.persistence.MappedSuperclass;
16
+
17
+/**
18
+ * Base abstract class for entities which will hold definitions for created, last modified by and created,
19
+ * last modified by date.
20
+ */
21
+@MappedSuperclass
22
+@Audited
23
+@EntityListeners(AuditingEntityListener.class)
24
+public abstract class AbstractAuditingEntity implements Serializable {
25
+
26
+    private static final long serialVersionUID = 1L;
27
+
28
+    @CreatedBy
29
+    @Column(name = "created_by", nullable = false, length = 50, updatable = false)
30
+    @JsonIgnore
31
+    private String createdBy;
32
+
33
+    @CreatedDate
34
+    @Column(name = "created_date", updatable = false)
35
+    @JsonIgnore
36
+    private Instant createdDate = Instant.now();
37
+
38
+    @LastModifiedBy
39
+    @Column(name = "last_modified_by", length = 50)
40
+    @JsonIgnore
41
+    private String lastModifiedBy;
42
+
43
+    @LastModifiedDate
44
+    @Column(name = "last_modified_date")
45
+    @JsonIgnore
46
+    private Instant lastModifiedDate = Instant.now();
47
+
48
+    public String getCreatedBy() {
49
+        return createdBy;
50
+    }
51
+
52
+    public void setCreatedBy(String createdBy) {
53
+        this.createdBy = createdBy;
54
+    }
55
+
56
+    public Instant getCreatedDate() {
57
+        return createdDate;
58
+    }
59
+
60
+    public void setCreatedDate(Instant createdDate) {
61
+        this.createdDate = createdDate;
62
+    }
63
+
64
+    public String getLastModifiedBy() {
65
+        return lastModifiedBy;
66
+    }
67
+
68
+    public void setLastModifiedBy(String lastModifiedBy) {
69
+        this.lastModifiedBy = lastModifiedBy;
70
+    }
71
+
72
+    public Instant getLastModifiedDate() {
73
+        return lastModifiedDate;
74
+    }
75
+
76
+    public void setLastModifiedDate(Instant lastModifiedDate) {
77
+        this.lastModifiedDate = lastModifiedDate;
78
+    }
79
+}

+ 62
- 0
src/main/java/rocks/zipcode/io/domain/Authority.java Zobrazit soubor

@@ -0,0 +1,62 @@
1
+package rocks.zipcode.io.domain;
2
+
3
+import org.hibernate.annotations.Cache;
4
+import org.hibernate.annotations.CacheConcurrencyStrategy;
5
+import javax.persistence.Entity;
6
+import javax.persistence.Id;
7
+import javax.persistence.Table;
8
+import javax.persistence.Column;
9
+import javax.validation.constraints.NotNull;
10
+import javax.validation.constraints.Size;
11
+import java.io.Serializable;
12
+
13
+/**
14
+ * An authority (a security role) used by Spring Security.
15
+ */
16
+@Entity
17
+@Table(name = "jhi_authority")
18
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
19
+public class Authority implements Serializable {
20
+
21
+    private static final long serialVersionUID = 1L;
22
+
23
+    @NotNull
24
+    @Size(max = 50)
25
+    @Id
26
+    @Column(length = 50)
27
+    private String name;
28
+
29
+    public String getName() {
30
+        return name;
31
+    }
32
+
33
+    public void setName(String name) {
34
+        this.name = name;
35
+    }
36
+
37
+    @Override
38
+    public boolean equals(Object o) {
39
+        if (this == o) {
40
+            return true;
41
+        }
42
+        if (o == null || getClass() != o.getClass()) {
43
+            return false;
44
+        }
45
+
46
+        Authority authority = (Authority) o;
47
+
48
+        return !(name != null ? !name.equals(authority.name) : authority.name != null);
49
+    }
50
+
51
+    @Override
52
+    public int hashCode() {
53
+        return name != null ? name.hashCode() : 0;
54
+    }
55
+
56
+    @Override
57
+    public String toString() {
58
+        return "Authority{" +
59
+            "name='" + name + '\'' +
60
+            "}";
61
+    }
62
+}

+ 109
- 0
src/main/java/rocks/zipcode/io/domain/PersistentAuditEvent.java Zobrazit soubor

@@ -0,0 +1,109 @@
1
+package rocks.zipcode.io.domain;
2
+
3
+import javax.persistence.*;
4
+import javax.validation.constraints.NotNull;
5
+import java.io.Serializable;
6
+import java.time.Instant;
7
+import java.util.HashMap;
8
+import java.util.Objects;
9
+import java.util.Map;
10
+
11
+/**
12
+ * Persist AuditEvent managed by the Spring Boot actuator.
13
+ *
14
+ * @see org.springframework.boot.actuate.audit.AuditEvent
15
+ */
16
+@Entity
17
+@Table(name = "jhi_persistent_audit_event")
18
+public class PersistentAuditEvent implements Serializable {
19
+
20
+    private static final long serialVersionUID = 1L;
21
+
22
+    @Id
23
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
24
+    @Column(name = "event_id")
25
+    private Long id;
26
+
27
+    @NotNull
28
+    @Column(nullable = false)
29
+    private String principal;
30
+
31
+    @Column(name = "event_date")
32
+    private Instant auditEventDate;
33
+
34
+    @Column(name = "event_type")
35
+    private String auditEventType;
36
+
37
+    @ElementCollection
38
+    @MapKeyColumn(name = "name")
39
+    @Column(name = "value")
40
+    @CollectionTable(name = "jhi_persistent_audit_evt_data", joinColumns=@JoinColumn(name="event_id"))
41
+    private Map<String, String> data = new HashMap<>();
42
+
43
+    public Long getId() {
44
+        return id;
45
+    }
46
+
47
+    public void setId(Long id) {
48
+        this.id = id;
49
+    }
50
+
51
+    public String getPrincipal() {
52
+        return principal;
53
+    }
54
+
55
+    public void setPrincipal(String principal) {
56
+        this.principal = principal;
57
+    }
58
+
59
+    public Instant getAuditEventDate() {
60
+        return auditEventDate;
61
+    }
62
+
63
+    public void setAuditEventDate(Instant auditEventDate) {
64
+        this.auditEventDate = auditEventDate;
65
+    }
66
+
67
+    public String getAuditEventType() {
68
+        return auditEventType;
69
+    }
70
+
71
+    public void setAuditEventType(String auditEventType) {
72
+        this.auditEventType = auditEventType;
73
+    }
74
+
75
+    public Map<String, String> getData() {
76
+        return data;
77
+    }
78
+
79
+    public void setData(Map<String, String> data) {
80
+        this.data = data;
81
+    }
82
+
83
+    @Override
84
+    public boolean equals(Object o) {
85
+        if (this == o) {
86
+            return true;
87
+        }
88
+        if (o == null || getClass() != o.getClass()) {
89
+            return false;
90
+        }
91
+
92
+        PersistentAuditEvent persistentAuditEvent = (PersistentAuditEvent) o;
93
+        return !(persistentAuditEvent.getId() == null || getId() == null) && Objects.equals(getId(), persistentAuditEvent.getId());
94
+    }
95
+
96
+    @Override
97
+    public int hashCode() {
98
+        return Objects.hashCode(getId());
99
+    }
100
+
101
+    @Override
102
+    public String toString() {
103
+        return "PersistentAuditEvent{" +
104
+            "principal='" + principal + '\'' +
105
+            ", auditEventDate=" + auditEventDate +
106
+            ", auditEventType='" + auditEventType + '\'' +
107
+            '}';
108
+    }
109
+}

+ 233
- 0
src/main/java/rocks/zipcode/io/domain/User.java Zobrazit soubor

@@ -0,0 +1,233 @@
1
+package rocks.zipcode.io.domain;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+
5
+import com.fasterxml.jackson.annotation.JsonIgnore;
6
+import org.apache.commons.lang3.StringUtils;
7
+import org.hibernate.annotations.BatchSize;
8
+import org.hibernate.annotations.Cache;
9
+import org.hibernate.annotations.CacheConcurrencyStrategy;
10
+import javax.validation.constraints.Email;
11
+
12
+import javax.persistence.*;
13
+import javax.validation.constraints.NotNull;
14
+import javax.validation.constraints.Pattern;
15
+import javax.validation.constraints.Size;
16
+import java.io.Serializable;
17
+import java.util.HashSet;
18
+import java.util.Locale;
19
+import java.util.Objects;
20
+import java.util.Set;
21
+import java.time.Instant;
22
+
23
+/**
24
+ * A user.
25
+ */
26
+@Entity
27
+@Table(name = "jhi_user")
28
+@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
29
+public class User extends AbstractAuditingEntity implements Serializable {
30
+
31
+    private static final long serialVersionUID = 1L;
32
+
33
+    @Id
34
+    @GeneratedValue(strategy = GenerationType.IDENTITY)
35
+    private Long id;
36
+
37
+    @NotNull
38
+    @Pattern(regexp = Constants.LOGIN_REGEX)
39
+    @Size(min = 1, max = 50)
40
+    @Column(length = 50, unique = true, nullable = false)
41
+    private String login;
42
+
43
+    @JsonIgnore
44
+    @NotNull
45
+    @Size(min = 60, max = 60)
46
+    @Column(name = "password_hash", length = 60, nullable = false)
47
+    private String password;
48
+
49
+    @Size(max = 50)
50
+    @Column(name = "first_name", length = 50)
51
+    private String firstName;
52
+
53
+    @Size(max = 50)
54
+    @Column(name = "last_name", length = 50)
55
+    private String lastName;
56
+
57
+    @Email
58
+    @Size(min = 5, max = 254)
59
+    @Column(length = 254, unique = true)
60
+    private String email;
61
+
62
+    @NotNull
63
+    @Column(nullable = false)
64
+    private boolean activated = false;
65
+
66
+    @Size(min = 2, max = 6)
67
+    @Column(name = "lang_key", length = 6)
68
+    private String langKey;
69
+
70
+    @Size(max = 256)
71
+    @Column(name = "image_url", length = 256)
72
+    private String imageUrl;
73
+
74
+    @Size(max = 20)
75
+    @Column(name = "activation_key", length = 20)
76
+    @JsonIgnore
77
+    private String activationKey;
78
+
79
+    @Size(max = 20)
80
+    @Column(name = "reset_key", length = 20)
81
+    @JsonIgnore
82
+    private String resetKey;
83
+
84
+    @Column(name = "reset_date")
85
+    private Instant resetDate = null;
86
+
87
+    @JsonIgnore
88
+    @ManyToMany
89
+    @JoinTable(
90
+        name = "jhi_user_authority",
91
+        joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
92
+        inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")})
93
+    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
94
+    @BatchSize(size = 20)
95
+    private Set<Authority> authorities = new HashSet<>();
96
+
97
+    public Long getId() {
98
+        return id;
99
+    }
100
+
101
+    public void setId(Long id) {
102
+        this.id = id;
103
+    }
104
+
105
+    public String getLogin() {
106
+        return login;
107
+    }
108
+
109
+    // Lowercase the login before saving it in database
110
+    public void setLogin(String login) {
111
+        this.login = StringUtils.lowerCase(login, Locale.ENGLISH);
112
+    }
113
+
114
+    public String getPassword() {
115
+        return password;
116
+    }
117
+
118
+    public void setPassword(String password) {
119
+        this.password = password;
120
+    }
121
+
122
+    public String getFirstName() {
123
+        return firstName;
124
+    }
125
+
126
+    public void setFirstName(String firstName) {
127
+        this.firstName = firstName;
128
+    }
129
+
130
+    public String getLastName() {
131
+        return lastName;
132
+    }
133
+
134
+    public void setLastName(String lastName) {
135
+        this.lastName = lastName;
136
+    }
137
+
138
+    public String getEmail() {
139
+        return email;
140
+    }
141
+
142
+    public void setEmail(String email) {
143
+        this.email = email;
144
+    }
145
+
146
+    public String getImageUrl() {
147
+        return imageUrl;
148
+    }
149
+
150
+    public void setImageUrl(String imageUrl) {
151
+        this.imageUrl = imageUrl;
152
+    }
153
+
154
+    public boolean getActivated() {
155
+        return activated;
156
+    }
157
+
158
+    public void setActivated(boolean activated) {
159
+        this.activated = activated;
160
+    }
161
+
162
+    public String getActivationKey() {
163
+        return activationKey;
164
+    }
165
+
166
+    public void setActivationKey(String activationKey) {
167
+        this.activationKey = activationKey;
168
+    }
169
+
170
+    public String getResetKey() {
171
+        return resetKey;
172
+    }
173
+
174
+    public void setResetKey(String resetKey) {
175
+        this.resetKey = resetKey;
176
+    }
177
+
178
+    public Instant getResetDate() {
179
+        return resetDate;
180
+    }
181
+
182
+    public void setResetDate(Instant resetDate) {
183
+        this.resetDate = resetDate;
184
+    }
185
+
186
+    public String getLangKey() {
187
+        return langKey;
188
+    }
189
+
190
+    public void setLangKey(String langKey) {
191
+        this.langKey = langKey;
192
+    }
193
+
194
+    public Set<Authority> getAuthorities() {
195
+        return authorities;
196
+    }
197
+
198
+    public void setAuthorities(Set<Authority> authorities) {
199
+        this.authorities = authorities;
200
+    }
201
+
202
+    @Override
203
+    public boolean equals(Object o) {
204
+        if (this == o) {
205
+            return true;
206
+        }
207
+        if (o == null || getClass() != o.getClass()) {
208
+            return false;
209
+        }
210
+
211
+        User user = (User) o;
212
+        return !(user.getId() == null || getId() == null) && Objects.equals(getId(), user.getId());
213
+    }
214
+
215
+    @Override
216
+    public int hashCode() {
217
+        return Objects.hashCode(getId());
218
+    }
219
+
220
+    @Override
221
+    public String toString() {
222
+        return "User{" +
223
+            "login='" + login + '\'' +
224
+            ", firstName='" + firstName + '\'' +
225
+            ", lastName='" + lastName + '\'' +
226
+            ", email='" + email + '\'' +
227
+            ", imageUrl='" + imageUrl + '\'' +
228
+            ", activated='" + activated + '\'' +
229
+            ", langKey='" + langKey + '\'' +
230
+            ", activationKey='" + activationKey + '\'' +
231
+            "}";
232
+    }
233
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/domain/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * JPA domain objects.
3
+ */
4
+package rocks.zipcode.io.domain;

+ 11
- 0
src/main/java/rocks/zipcode/io/repository/AuthorityRepository.java Zobrazit soubor

@@ -0,0 +1,11 @@
1
+package rocks.zipcode.io.repository;
2
+
3
+import rocks.zipcode.io.domain.Authority;
4
+
5
+import org.springframework.data.jpa.repository.JpaRepository;
6
+
7
+/**
8
+ * Spring Data JPA repository for the Authority entity.
9
+ */
10
+public interface AuthorityRepository extends JpaRepository<Authority, String> {
11
+}

+ 89
- 0
src/main/java/rocks/zipcode/io/repository/CustomAuditEventRepository.java Zobrazit soubor

@@ -0,0 +1,89 @@
1
+package rocks.zipcode.io.repository;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+import rocks.zipcode.io.config.audit.AuditEventConverter;
5
+import rocks.zipcode.io.domain.PersistentAuditEvent;
6
+
7
+import org.slf4j.Logger;
8
+import org.slf4j.LoggerFactory;
9
+import org.springframework.boot.actuate.audit.AuditEvent;
10
+import org.springframework.boot.actuate.audit.AuditEventRepository;
11
+import org.springframework.stereotype.Repository;
12
+import org.springframework.transaction.annotation.Propagation;
13
+import org.springframework.transaction.annotation.Transactional;
14
+
15
+import java.time.Instant;
16
+import java.util.*;
17
+
18
+/**
19
+ * An implementation of Spring Boot's AuditEventRepository.
20
+ */
21
+@Repository
22
+public class CustomAuditEventRepository implements AuditEventRepository {
23
+
24
+    private static final String AUTHORIZATION_FAILURE = "AUTHORIZATION_FAILURE";
25
+
26
+    /**
27
+     * Should be the same as in Liquibase migration.
28
+     */
29
+    protected static final int EVENT_DATA_COLUMN_MAX_LENGTH = 255;
30
+
31
+    private final PersistenceAuditEventRepository persistenceAuditEventRepository;
32
+
33
+    private final AuditEventConverter auditEventConverter;
34
+
35
+    private final Logger log = LoggerFactory.getLogger(getClass());
36
+
37
+    public CustomAuditEventRepository(PersistenceAuditEventRepository persistenceAuditEventRepository,
38
+            AuditEventConverter auditEventConverter) {
39
+
40
+        this.persistenceAuditEventRepository = persistenceAuditEventRepository;
41
+        this.auditEventConverter = auditEventConverter;
42
+    }
43
+
44
+    @Override
45
+    public List<AuditEvent> find(String principal, Instant after, String type) {
46
+        Iterable<PersistentAuditEvent> persistentAuditEvents =
47
+            persistenceAuditEventRepository.findByPrincipalAndAuditEventDateAfterAndAuditEventType(principal, after, type);
48
+        return auditEventConverter.convertToAuditEvent(persistentAuditEvents);
49
+    }
50
+
51
+    @Override
52
+    @Transactional(propagation = Propagation.REQUIRES_NEW)
53
+    public void add(AuditEvent event) {
54
+        if (!AUTHORIZATION_FAILURE.equals(event.getType()) &&
55
+            !Constants.ANONYMOUS_USER.equals(event.getPrincipal())) {
56
+
57
+            PersistentAuditEvent persistentAuditEvent = new PersistentAuditEvent();
58
+            persistentAuditEvent.setPrincipal(event.getPrincipal());
59
+            persistentAuditEvent.setAuditEventType(event.getType());
60
+            persistentAuditEvent.setAuditEventDate(event.getTimestamp());
61
+            Map<String, String> eventData = auditEventConverter.convertDataToStrings(event.getData());
62
+            persistentAuditEvent.setData(truncate(eventData));
63
+            persistenceAuditEventRepository.save(persistentAuditEvent);
64
+        }
65
+    }
66
+
67
+    /**
68
+     * Truncate event data that might exceed column length.
69
+     */
70
+    private Map<String, String> truncate(Map<String, String> data) {
71
+        Map<String, String> results = new HashMap<>();
72
+
73
+        if (data != null) {
74
+            for (Map.Entry<String, String> entry : data.entrySet()) {
75
+                String value = entry.getValue();
76
+                if (value != null) {
77
+                    int length = value.length();
78
+                    if (length > EVENT_DATA_COLUMN_MAX_LENGTH) {
79
+                        value = value.substring(0, EVENT_DATA_COLUMN_MAX_LENGTH);
80
+                        log.warn("Event data for {} too long ({}) has been truncated to {}. Consider increasing column width.",
81
+                                 entry.getKey(), length, EVENT_DATA_COLUMN_MAX_LENGTH);
82
+                    }
83
+                }
84
+                results.put(entry.getKey(), value);
85
+            }
86
+        }
87
+        return results;
88
+    }
89
+}

+ 25
- 0
src/main/java/rocks/zipcode/io/repository/PersistenceAuditEventRepository.java Zobrazit soubor

@@ -0,0 +1,25 @@
1
+package rocks.zipcode.io.repository;
2
+
3
+import rocks.zipcode.io.domain.PersistentAuditEvent;
4
+import org.springframework.data.domain.Page;
5
+import org.springframework.data.domain.Pageable;
6
+import org.springframework.data.jpa.repository.JpaRepository;
7
+
8
+import java.time.Instant;
9
+import java.util.List;
10
+
11
+/**
12
+ * Spring Data JPA repository for the PersistentAuditEvent entity.
13
+ */
14
+public interface PersistenceAuditEventRepository extends JpaRepository<PersistentAuditEvent, Long> {
15
+
16
+    List<PersistentAuditEvent> findByPrincipal(String principal);
17
+
18
+    List<PersistentAuditEvent> findByAuditEventDateAfter(Instant after);
19
+
20
+    List<PersistentAuditEvent> findByPrincipalAndAuditEventDateAfter(String principal, Instant after);
21
+
22
+    List<PersistentAuditEvent> findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principal, Instant after, String type);
23
+
24
+    Page<PersistentAuditEvent> findAllByAuditEventDateBetween(Instant fromDate, Instant toDate, Pageable pageable);
25
+}

+ 47
- 0
src/main/java/rocks/zipcode/io/repository/UserRepository.java Zobrazit soubor

@@ -0,0 +1,47 @@
1
+package rocks.zipcode.io.repository;
2
+
3
+import rocks.zipcode.io.domain.User;
4
+
5
+import org.springframework.cache.annotation.Cacheable;
6
+import org.springframework.data.domain.Page;
7
+import org.springframework.data.domain.Pageable;
8
+import org.springframework.data.jpa.repository.EntityGraph;
9
+import org.springframework.data.jpa.repository.JpaRepository;
10
+import org.springframework.stereotype.Repository;
11
+import java.util.List;
12
+import java.util.Optional;
13
+import java.time.Instant;
14
+
15
+/**
16
+ * Spring Data JPA repository for the User entity.
17
+ */
18
+@Repository
19
+public interface UserRepository extends JpaRepository<User, Long> {
20
+
21
+    String USERS_BY_LOGIN_CACHE = "usersByLogin";
22
+
23
+    String USERS_BY_EMAIL_CACHE = "usersByEmail";
24
+
25
+    Optional<User> findOneByActivationKey(String activationKey);
26
+
27
+    List<User> findAllByActivatedIsFalseAndCreatedDateBefore(Instant dateTime);
28
+
29
+    Optional<User> findOneByResetKey(String resetKey);
30
+
31
+    Optional<User> findOneByEmailIgnoreCase(String email);
32
+
33
+    Optional<User> findOneByLogin(String login);
34
+
35
+    @EntityGraph(attributePaths = "authorities")
36
+    Optional<User> findOneWithAuthoritiesById(Long id);
37
+
38
+    @EntityGraph(attributePaths = "authorities")
39
+    @Cacheable(cacheNames = USERS_BY_LOGIN_CACHE)
40
+    Optional<User> findOneWithAuthoritiesByLogin(String login);
41
+
42
+    @EntityGraph(attributePaths = "authorities")
43
+    @Cacheable(cacheNames = USERS_BY_EMAIL_CACHE)
44
+    Optional<User> findOneWithAuthoritiesByEmail(String email);
45
+
46
+    Page<User> findAllByLoginNot(Pageable pageable, String login);
47
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/repository/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Spring Data JPA repositories.
3
+ */
4
+package rocks.zipcode.io.repository;

+ 16
- 0
src/main/java/rocks/zipcode/io/security/AuthoritiesConstants.java Zobrazit soubor

@@ -0,0 +1,16 @@
1
+package rocks.zipcode.io.security;
2
+
3
+/**
4
+ * Constants for Spring Security authorities.
5
+ */
6
+public final class AuthoritiesConstants {
7
+
8
+    public static final String ADMIN = "ROLE_ADMIN";
9
+
10
+    public static final String USER = "ROLE_USER";
11
+
12
+    public static final String ANONYMOUS = "ROLE_ANONYMOUS";
13
+
14
+    private AuthoritiesConstants() {
15
+    }
16
+}

+ 62
- 0
src/main/java/rocks/zipcode/io/security/DomainUserDetailsService.java Zobrazit soubor

@@ -0,0 +1,62 @@
1
+package rocks.zipcode.io.security;
2
+
3
+import rocks.zipcode.io.domain.User;
4
+import rocks.zipcode.io.repository.UserRepository;
5
+import org.hibernate.validator.internal.constraintvalidators.hv.EmailValidator;
6
+import org.slf4j.Logger;
7
+import org.slf4j.LoggerFactory;
8
+import org.springframework.security.core.GrantedAuthority;
9
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
10
+import org.springframework.security.core.userdetails.UserDetails;
11
+import org.springframework.security.core.userdetails.UserDetailsService;
12
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
13
+import org.springframework.stereotype.Component;
14
+import org.springframework.transaction.annotation.Transactional;
15
+
16
+import java.util.*;
17
+import java.util.stream.Collectors;
18
+
19
+/**
20
+ * Authenticate a user from the database.
21
+ */
22
+@Component("userDetailsService")
23
+public class DomainUserDetailsService implements UserDetailsService {
24
+
25
+    private final Logger log = LoggerFactory.getLogger(DomainUserDetailsService.class);
26
+
27
+    private final UserRepository userRepository;
28
+
29
+    public DomainUserDetailsService(UserRepository userRepository) {
30
+        this.userRepository = userRepository;
31
+    }
32
+
33
+    @Override
34
+    @Transactional
35
+    public UserDetails loadUserByUsername(final String login) {
36
+        log.debug("Authenticating {}", login);
37
+
38
+        if (new EmailValidator().isValid(login, null)) {
39
+            return userRepository.findOneWithAuthoritiesByEmail(login)
40
+                .map(user -> createSpringSecurityUser(login, user))
41
+                .orElseThrow(() -> new UsernameNotFoundException("User with email " + login + " was not found in the database"));
42
+        }
43
+
44
+        String lowercaseLogin = login.toLowerCase(Locale.ENGLISH);
45
+        return userRepository.findOneWithAuthoritiesByLogin(lowercaseLogin)
46
+            .map(user -> createSpringSecurityUser(lowercaseLogin, user))
47
+            .orElseThrow(() -> new UsernameNotFoundException("User " + lowercaseLogin + " was not found in the database"));
48
+
49
+    }
50
+
51
+    private org.springframework.security.core.userdetails.User createSpringSecurityUser(String lowercaseLogin, User user) {
52
+        if (!user.getActivated()) {
53
+            throw new UserNotActivatedException("User " + lowercaseLogin + " was not activated");
54
+        }
55
+        List<GrantedAuthority> grantedAuthorities = user.getAuthorities().stream()
56
+            .map(authority -> new SimpleGrantedAuthority(authority.getName()))
57
+            .collect(Collectors.toList());
58
+        return new org.springframework.security.core.userdetails.User(user.getLogin(),
59
+            user.getPassword(),
60
+            grantedAuthorities);
61
+    }
62
+}

+ 76
- 0
src/main/java/rocks/zipcode/io/security/SecurityUtils.java Zobrazit soubor

@@ -0,0 +1,76 @@
1
+package rocks.zipcode.io.security;
2
+
3
+import org.springframework.security.core.context.SecurityContext;
4
+import org.springframework.security.core.context.SecurityContextHolder;
5
+import org.springframework.security.core.userdetails.UserDetails;
6
+
7
+import java.util.Optional;
8
+
9
+/**
10
+ * Utility class for Spring Security.
11
+ */
12
+public final class SecurityUtils {
13
+
14
+    private SecurityUtils() {
15
+    }
16
+
17
+    /**
18
+     * Get the login of the current user.
19
+     *
20
+     * @return the login of the current user
21
+     */
22
+    public static Optional<String> getCurrentUserLogin() {
23
+        SecurityContext securityContext = SecurityContextHolder.getContext();
24
+        return Optional.ofNullable(securityContext.getAuthentication())
25
+            .map(authentication -> {
26
+                if (authentication.getPrincipal() instanceof UserDetails) {
27
+                    UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
28
+                    return springSecurityUser.getUsername();
29
+                } else if (authentication.getPrincipal() instanceof String) {
30
+                    return (String) authentication.getPrincipal();
31
+                }
32
+                return null;
33
+            });
34
+    }
35
+
36
+    /**
37
+     * Get the JWT of the current user.
38
+     *
39
+     * @return the JWT of the current user
40
+     */
41
+    public static Optional<String> getCurrentUserJWT() {
42
+        SecurityContext securityContext = SecurityContextHolder.getContext();
43
+        return Optional.ofNullable(securityContext.getAuthentication())
44
+            .filter(authentication -> authentication.getCredentials() instanceof String)
45
+            .map(authentication -> (String) authentication.getCredentials());
46
+    }
47
+
48
+    /**
49
+     * Check if a user is authenticated.
50
+     *
51
+     * @return true if the user is authenticated, false otherwise
52
+     */
53
+    public static boolean isAuthenticated() {
54
+        SecurityContext securityContext = SecurityContextHolder.getContext();
55
+        return Optional.ofNullable(securityContext.getAuthentication())
56
+            .map(authentication -> authentication.getAuthorities().stream()
57
+                .noneMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(AuthoritiesConstants.ANONYMOUS)))
58
+            .orElse(false);
59
+    }
60
+
61
+    /**
62
+     * If the current user has a specific authority (security role).
63
+     * <p>
64
+     * The name of this method comes from the isUserInRole() method in the Servlet API
65
+     *
66
+     * @param authority the authority to check
67
+     * @return true if the current user has the authority, false otherwise
68
+     */
69
+    public static boolean isCurrentUserInRole(String authority) {
70
+        SecurityContext securityContext = SecurityContextHolder.getContext();
71
+        return Optional.ofNullable(securityContext.getAuthentication())
72
+            .map(authentication -> authentication.getAuthorities().stream()
73
+                .anyMatch(grantedAuthority -> grantedAuthority.getAuthority().equals(authority)))
74
+            .orElse(false);
75
+    }
76
+}

+ 20
- 0
src/main/java/rocks/zipcode/io/security/SpringSecurityAuditorAware.java Zobrazit soubor

@@ -0,0 +1,20 @@
1
+package rocks.zipcode.io.security;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+
5
+import java.util.Optional;
6
+
7
+import org.springframework.data.domain.AuditorAware;
8
+import org.springframework.stereotype.Component;
9
+
10
+/**
11
+ * Implementation of AuditorAware based on Spring Security.
12
+ */
13
+@Component
14
+public class SpringSecurityAuditorAware implements AuditorAware<String> {
15
+
16
+    @Override
17
+    public Optional<String> getCurrentAuditor() {
18
+        return Optional.of(SecurityUtils.getCurrentUserLogin().orElse(Constants.SYSTEM_ACCOUNT));
19
+    }
20
+}

+ 19
- 0
src/main/java/rocks/zipcode/io/security/UserNotActivatedException.java Zobrazit soubor

@@ -0,0 +1,19 @@
1
+package rocks.zipcode.io.security;
2
+
3
+import org.springframework.security.core.AuthenticationException;
4
+
5
+/**
6
+ * This exception is thrown in case of a not activated user trying to authenticate.
7
+ */
8
+public class UserNotActivatedException extends AuthenticationException {
9
+
10
+    private static final long serialVersionUID = 1L;
11
+
12
+    public UserNotActivatedException(String message) {
13
+        super(message);
14
+    }
15
+
16
+    public UserNotActivatedException(String message, Throwable t) {
17
+        super(message, t);
18
+    }
19
+}

+ 21
- 0
src/main/java/rocks/zipcode/io/security/jwt/JWTConfigurer.java Zobrazit soubor

@@ -0,0 +1,21 @@
1
+package rocks.zipcode.io.security.jwt;
2
+
3
+import org.springframework.security.config.annotation.SecurityConfigurerAdapter;
4
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
5
+import org.springframework.security.web.DefaultSecurityFilterChain;
6
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
7
+
8
+public class JWTConfigurer extends SecurityConfigurerAdapter<DefaultSecurityFilterChain, HttpSecurity> {
9
+
10
+    private TokenProvider tokenProvider;
11
+
12
+    public JWTConfigurer(TokenProvider tokenProvider) {
13
+        this.tokenProvider = tokenProvider;
14
+    }
15
+
16
+    @Override
17
+    public void configure(HttpSecurity http) throws Exception {
18
+        JWTFilter customFilter = new JWTFilter(tokenProvider);
19
+        http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class);
20
+    }
21
+}

+ 48
- 0
src/main/java/rocks/zipcode/io/security/jwt/JWTFilter.java Zobrazit soubor

@@ -0,0 +1,48 @@
1
+package rocks.zipcode.io.security.jwt;
2
+
3
+import org.springframework.security.core.Authentication;
4
+import org.springframework.security.core.context.SecurityContextHolder;
5
+import org.springframework.util.StringUtils;
6
+import org.springframework.web.filter.GenericFilterBean;
7
+
8
+import javax.servlet.FilterChain;
9
+import javax.servlet.ServletException;
10
+import javax.servlet.ServletRequest;
11
+import javax.servlet.ServletResponse;
12
+import javax.servlet.http.HttpServletRequest;
13
+import java.io.IOException;
14
+
15
+/**
16
+ * Filters incoming requests and installs a Spring Security principal if a header corresponding to a valid user is
17
+ * found.
18
+ */
19
+public class JWTFilter extends GenericFilterBean {
20
+
21
+    public static final String AUTHORIZATION_HEADER = "Authorization";
22
+
23
+    private TokenProvider tokenProvider;
24
+
25
+    public JWTFilter(TokenProvider tokenProvider) {
26
+        this.tokenProvider = tokenProvider;
27
+    }
28
+
29
+    @Override
30
+    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
31
+        throws IOException, ServletException {
32
+        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
33
+        String jwt = resolveToken(httpServletRequest);
34
+        if (StringUtils.hasText(jwt) && this.tokenProvider.validateToken(jwt)) {
35
+            Authentication authentication = this.tokenProvider.getAuthentication(jwt);
36
+            SecurityContextHolder.getContext().setAuthentication(authentication);
37
+        }
38
+        filterChain.doFilter(servletRequest, servletResponse);
39
+    }
40
+
41
+    private String resolveToken(HttpServletRequest request){
42
+        String bearerToken = request.getHeader(AUTHORIZATION_HEADER);
43
+        if (StringUtils.hasText(bearerToken) && bearerToken.startsWith("Bearer ")) {
44
+            return bearerToken.substring(7);
45
+        }
46
+        return null;
47
+    }
48
+}

+ 119
- 0
src/main/java/rocks/zipcode/io/security/jwt/TokenProvider.java Zobrazit soubor

@@ -0,0 +1,119 @@
1
+package rocks.zipcode.io.security.jwt;
2
+
3
+import java.nio.charset.StandardCharsets;
4
+import java.security.Key;
5
+import java.util.*;
6
+import java.util.stream.Collectors;
7
+import javax.annotation.PostConstruct;
8
+
9
+import org.slf4j.Logger;
10
+import org.slf4j.LoggerFactory;
11
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
12
+import org.springframework.security.core.Authentication;
13
+import org.springframework.security.core.GrantedAuthority;
14
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
15
+import org.springframework.security.core.userdetails.User;
16
+import org.springframework.stereotype.Component;
17
+import org.springframework.util.StringUtils;
18
+
19
+import io.github.jhipster.config.JHipsterProperties;
20
+import io.jsonwebtoken.*;
21
+import io.jsonwebtoken.io.Decoders;
22
+import io.jsonwebtoken.security.Keys;
23
+
24
+@Component
25
+public class TokenProvider {
26
+
27
+    private final Logger log = LoggerFactory.getLogger(TokenProvider.class);
28
+
29
+    private static final String AUTHORITIES_KEY = "auth";
30
+
31
+    private Key key;
32
+
33
+    private long tokenValidityInMilliseconds;
34
+
35
+    private long tokenValidityInMillisecondsForRememberMe;
36
+
37
+    private final JHipsterProperties jHipsterProperties;
38
+
39
+    public TokenProvider(JHipsterProperties jHipsterProperties) {
40
+        this.jHipsterProperties = jHipsterProperties;
41
+    }
42
+
43
+    @PostConstruct
44
+    public void init() {
45
+        byte[] keyBytes;
46
+        String secret = jHipsterProperties.getSecurity().getAuthentication().getJwt().getSecret();
47
+        if (!StringUtils.isEmpty(secret)) {
48
+            log.warn("Warning: the JWT key used is not Base64-encoded. " +
49
+                "We recommend using the `jhipster.security.authentication.jwt.base64-secret` key for optimum security.");
50
+            keyBytes = secret.getBytes(StandardCharsets.UTF_8);
51
+        } else {
52
+            log.debug("Using a Base64-encoded JWT secret key");
53
+            keyBytes = Decoders.BASE64.decode(jHipsterProperties.getSecurity().getAuthentication().getJwt().getBase64Secret());
54
+        }
55
+        this.key = Keys.hmacShaKeyFor(keyBytes);
56
+        this.tokenValidityInMilliseconds =
57
+            1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt().getTokenValidityInSeconds();
58
+        this.tokenValidityInMillisecondsForRememberMe =
59
+            1000 * jHipsterProperties.getSecurity().getAuthentication().getJwt()
60
+                .getTokenValidityInSecondsForRememberMe();
61
+    }
62
+
63
+    public String createToken(Authentication authentication, boolean rememberMe) {
64
+        String authorities = authentication.getAuthorities().stream()
65
+            .map(GrantedAuthority::getAuthority)
66
+            .collect(Collectors.joining(","));
67
+
68
+        long now = (new Date()).getTime();
69
+        Date validity;
70
+        if (rememberMe) {
71
+            validity = new Date(now + this.tokenValidityInMillisecondsForRememberMe);
72
+        } else {
73
+            validity = new Date(now + this.tokenValidityInMilliseconds);
74
+        }
75
+
76
+        return Jwts.builder()
77
+            .setSubject(authentication.getName())
78
+            .claim(AUTHORITIES_KEY, authorities)
79
+            .signWith(key, SignatureAlgorithm.HS512)
80
+            .setExpiration(validity)
81
+            .compact();
82
+    }
83
+
84
+    public Authentication getAuthentication(String token) {
85
+        Claims claims = Jwts.parser()
86
+            .setSigningKey(key)
87
+            .parseClaimsJws(token)
88
+            .getBody();
89
+
90
+        Collection<? extends GrantedAuthority> authorities =
91
+            Arrays.stream(claims.get(AUTHORITIES_KEY).toString().split(","))
92
+                .map(SimpleGrantedAuthority::new)
93
+                .collect(Collectors.toList());
94
+
95
+        User principal = new User(claims.getSubject(), "", authorities);
96
+
97
+        return new UsernamePasswordAuthenticationToken(principal, token, authorities);
98
+    }
99
+
100
+    public boolean validateToken(String authToken) {
101
+        try {
102
+            Jwts.parser().setSigningKey(key).parseClaimsJws(authToken);
103
+            return true;
104
+        } catch (io.jsonwebtoken.security.SecurityException | MalformedJwtException e) {
105
+            log.info("Invalid JWT signature.");
106
+            log.trace("Invalid JWT signature trace: {}", e);
107
+        } catch (ExpiredJwtException e) {
108
+            log.info("Expired JWT token.");
109
+            log.trace("Expired JWT token trace: {}", e);
110
+        } catch (UnsupportedJwtException e) {
111
+            log.info("Unsupported JWT token.");
112
+            log.trace("Unsupported JWT token trace: {}", e);
113
+        } catch (IllegalArgumentException e) {
114
+            log.info("JWT token compact of handler are invalid.");
115
+            log.trace("JWT token compact of handler are invalid trace: {}", e);
116
+        }
117
+        return false;
118
+    }
119
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/security/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Spring Security configuration.
3
+ */
4
+package rocks.zipcode.io.security;

+ 51
- 0
src/main/java/rocks/zipcode/io/service/AuditEventService.java Zobrazit soubor

@@ -0,0 +1,51 @@
1
+package rocks.zipcode.io.service;
2
+
3
+import rocks.zipcode.io.config.audit.AuditEventConverter;
4
+import rocks.zipcode.io.repository.PersistenceAuditEventRepository;
5
+import org.springframework.boot.actuate.audit.AuditEvent;
6
+import org.springframework.data.domain.Page;
7
+import org.springframework.data.domain.Pageable;
8
+import org.springframework.stereotype.Service;
9
+import org.springframework.transaction.annotation.Transactional;
10
+
11
+import java.time.Instant;
12
+import java.util.Optional;
13
+
14
+/**
15
+ * Service for managing audit events.
16
+ * <p>
17
+ * This is the default implementation to support SpringBoot Actuator AuditEventRepository
18
+ */
19
+@Service
20
+@Transactional
21
+public class AuditEventService {
22
+
23
+    private final PersistenceAuditEventRepository persistenceAuditEventRepository;
24
+
25
+    private final AuditEventConverter auditEventConverter;
26
+
27
+    public AuditEventService(
28
+        PersistenceAuditEventRepository persistenceAuditEventRepository,
29
+        AuditEventConverter auditEventConverter) {
30
+
31
+        this.persistenceAuditEventRepository = persistenceAuditEventRepository;
32
+        this.auditEventConverter = auditEventConverter;
33
+    }
34
+
35
+    public Page<AuditEvent> findAll(Pageable pageable) {
36
+        return persistenceAuditEventRepository.findAll(pageable)
37
+            .map(auditEventConverter::convertToAuditEvent);
38
+    }
39
+
40
+    public Page<AuditEvent> findByDates(Instant fromDate, Instant toDate, Pageable pageable) {
41
+        return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable)
42
+            .map(auditEventConverter::convertToAuditEvent);
43
+    }
44
+
45
+    public Optional<AuditEvent> find(Long id) {
46
+        return Optional.ofNullable(persistenceAuditEventRepository.findById(id))
47
+            .filter(Optional::isPresent)
48
+            .map(Optional::get)
49
+            .map(auditEventConverter::convertToAuditEvent);
50
+    }
51
+}

+ 105
- 0
src/main/java/rocks/zipcode/io/service/MailService.java Zobrazit soubor

@@ -0,0 +1,105 @@
1
+package rocks.zipcode.io.service;
2
+
3
+import rocks.zipcode.io.domain.User;
4
+
5
+import io.github.jhipster.config.JHipsterProperties;
6
+
7
+import java.nio.charset.StandardCharsets;
8
+import java.util.Locale;
9
+import javax.mail.internet.MimeMessage;
10
+
11
+import org.slf4j.Logger;
12
+import org.slf4j.LoggerFactory;
13
+import org.springframework.context.MessageSource;
14
+import org.springframework.mail.javamail.JavaMailSender;
15
+import org.springframework.mail.javamail.MimeMessageHelper;
16
+import org.springframework.scheduling.annotation.Async;
17
+import org.springframework.stereotype.Service;
18
+import org.thymeleaf.context.Context;
19
+import org.thymeleaf.spring5.SpringTemplateEngine;
20
+
21
+/**
22
+ * Service for sending emails.
23
+ * <p>
24
+ * We use the @Async annotation to send emails asynchronously.
25
+ */
26
+@Service
27
+public class MailService {
28
+
29
+    private final Logger log = LoggerFactory.getLogger(MailService.class);
30
+
31
+    private static final String USER = "user";
32
+
33
+    private static final String BASE_URL = "baseUrl";
34
+
35
+    private final JHipsterProperties jHipsterProperties;
36
+
37
+    private final JavaMailSender javaMailSender;
38
+
39
+    private final MessageSource messageSource;
40
+
41
+    private final SpringTemplateEngine templateEngine;
42
+
43
+    public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender,
44
+            MessageSource messageSource, SpringTemplateEngine templateEngine) {
45
+
46
+        this.jHipsterProperties = jHipsterProperties;
47
+        this.javaMailSender = javaMailSender;
48
+        this.messageSource = messageSource;
49
+        this.templateEngine = templateEngine;
50
+    }
51
+
52
+    @Async
53
+    public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) {
54
+        log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}",
55
+            isMultipart, isHtml, to, subject, content);
56
+
57
+        // Prepare message using a Spring helper
58
+        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
59
+        try {
60
+            MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name());
61
+            message.setTo(to);
62
+            message.setFrom(jHipsterProperties.getMail().getFrom());
63
+            message.setSubject(subject);
64
+            message.setText(content, isHtml);
65
+            javaMailSender.send(mimeMessage);
66
+            log.debug("Sent email to User '{}'", to);
67
+        } catch (Exception e) {
68
+            if (log.isDebugEnabled()) {
69
+                log.warn("Email could not be sent to user '{}'", to, e);
70
+            } else {
71
+                log.warn("Email could not be sent to user '{}': {}", to, e.getMessage());
72
+            }
73
+        }
74
+    }
75
+
76
+    @Async
77
+    public void sendEmailFromTemplate(User user, String templateName, String titleKey) {
78
+        Locale locale = Locale.forLanguageTag(user.getLangKey());
79
+        Context context = new Context(locale);
80
+        context.setVariable(USER, user);
81
+        context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl());
82
+        String content = templateEngine.process(templateName, context);
83
+        String subject = messageSource.getMessage(titleKey, null, locale);
84
+        sendEmail(user.getEmail(), subject, content, false, true);
85
+
86
+    }
87
+
88
+    @Async
89
+    public void sendActivationEmail(User user) {
90
+        log.debug("Sending activation email to '{}'", user.getEmail());
91
+        sendEmailFromTemplate(user, "mail/activationEmail", "email.activation.title");
92
+    }
93
+
94
+    @Async
95
+    public void sendCreationEmail(User user) {
96
+        log.debug("Sending creation email to '{}'", user.getEmail());
97
+        sendEmailFromTemplate(user, "mail/creationEmail", "email.activation.title");
98
+    }
99
+
100
+    @Async
101
+    public void sendPasswordResetMail(User user) {
102
+        log.debug("Sending password reset email to '{}'", user.getEmail());
103
+        sendEmailFromTemplate(user, "mail/passwordResetEmail", "email.reset.title");
104
+    }
105
+}

+ 293
- 0
src/main/java/rocks/zipcode/io/service/UserService.java Zobrazit soubor

@@ -0,0 +1,293 @@
1
+package rocks.zipcode.io.service;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+import rocks.zipcode.io.domain.Authority;
5
+import rocks.zipcode.io.domain.User;
6
+import rocks.zipcode.io.repository.AuthorityRepository;
7
+import rocks.zipcode.io.repository.UserRepository;
8
+import rocks.zipcode.io.security.AuthoritiesConstants;
9
+import rocks.zipcode.io.security.SecurityUtils;
10
+import rocks.zipcode.io.service.dto.UserDTO;
11
+import rocks.zipcode.io.service.util.RandomUtil;
12
+import rocks.zipcode.io.web.rest.errors.*;
13
+
14
+import org.slf4j.Logger;
15
+import org.slf4j.LoggerFactory;
16
+import org.springframework.cache.CacheManager;
17
+import org.springframework.data.domain.Page;
18
+import org.springframework.data.domain.Pageable;
19
+import org.springframework.scheduling.annotation.Scheduled;
20
+import org.springframework.security.crypto.password.PasswordEncoder;
21
+import org.springframework.stereotype.Service;
22
+import org.springframework.transaction.annotation.Transactional;
23
+
24
+import java.time.Instant;
25
+import java.time.temporal.ChronoUnit;
26
+import java.util.*;
27
+import java.util.stream.Collectors;
28
+
29
+/**
30
+ * Service class for managing users.
31
+ */
32
+@Service
33
+@Transactional
34
+public class UserService {
35
+
36
+    private final Logger log = LoggerFactory.getLogger(UserService.class);
37
+
38
+    private final UserRepository userRepository;
39
+
40
+    private final PasswordEncoder passwordEncoder;
41
+
42
+    private final AuthorityRepository authorityRepository;
43
+
44
+    private final CacheManager cacheManager;
45
+
46
+    public UserService(UserRepository userRepository, PasswordEncoder passwordEncoder, AuthorityRepository authorityRepository, CacheManager cacheManager) {
47
+        this.userRepository = userRepository;
48
+        this.passwordEncoder = passwordEncoder;
49
+        this.authorityRepository = authorityRepository;
50
+        this.cacheManager = cacheManager;
51
+    }
52
+
53
+    public Optional<User> activateRegistration(String key) {
54
+        log.debug("Activating user for activation key {}", key);
55
+        return userRepository.findOneByActivationKey(key)
56
+            .map(user -> {
57
+                // activate given user for the registration key.
58
+                user.setActivated(true);
59
+                user.setActivationKey(null);
60
+                this.clearUserCaches(user);
61
+                log.debug("Activated user: {}", user);
62
+                return user;
63
+            });
64
+    }
65
+
66
+    public Optional<User> completePasswordReset(String newPassword, String key) {
67
+        log.debug("Reset user password for reset key {}", key);
68
+        return userRepository.findOneByResetKey(key)
69
+            .filter(user -> user.getResetDate().isAfter(Instant.now().minusSeconds(86400)))
70
+            .map(user -> {
71
+                user.setPassword(passwordEncoder.encode(newPassword));
72
+                user.setResetKey(null);
73
+                user.setResetDate(null);
74
+                this.clearUserCaches(user);
75
+                return user;
76
+            });
77
+    }
78
+
79
+    public Optional<User> requestPasswordReset(String mail) {
80
+        return userRepository.findOneByEmailIgnoreCase(mail)
81
+            .filter(User::getActivated)
82
+            .map(user -> {
83
+                user.setResetKey(RandomUtil.generateResetKey());
84
+                user.setResetDate(Instant.now());
85
+                this.clearUserCaches(user);
86
+                return user;
87
+            });
88
+    }
89
+
90
+    public User registerUser(UserDTO userDTO, String password) {
91
+        userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).ifPresent(existingUser -> {
92
+            boolean removed = removeNonActivatedUser(existingUser);
93
+            if (!removed) {
94
+                throw new LoginAlreadyUsedException();
95
+            }
96
+        });
97
+        userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).ifPresent(existingUser -> {
98
+            boolean removed = removeNonActivatedUser(existingUser);
99
+            if (!removed) {
100
+                throw new EmailAlreadyUsedException();
101
+            }
102
+        });
103
+        User newUser = new User();
104
+        String encryptedPassword = passwordEncoder.encode(password);
105
+        newUser.setLogin(userDTO.getLogin().toLowerCase());
106
+        // new user gets initially a generated password
107
+        newUser.setPassword(encryptedPassword);
108
+        newUser.setFirstName(userDTO.getFirstName());
109
+        newUser.setLastName(userDTO.getLastName());
110
+        newUser.setEmail(userDTO.getEmail().toLowerCase());
111
+        newUser.setImageUrl(userDTO.getImageUrl());
112
+        newUser.setLangKey(userDTO.getLangKey());
113
+        // new user is not active
114
+        newUser.setActivated(false);
115
+        // new user gets registration key
116
+        newUser.setActivationKey(RandomUtil.generateActivationKey());
117
+        Set<Authority> authorities = new HashSet<>();
118
+        authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add);
119
+        newUser.setAuthorities(authorities);
120
+        userRepository.save(newUser);
121
+        this.clearUserCaches(newUser);
122
+        log.debug("Created Information for User: {}", newUser);
123
+        return newUser;
124
+    }
125
+    private boolean removeNonActivatedUser(User existingUser){
126
+        if (existingUser.getActivated()) {
127
+             return false;
128
+        }
129
+        userRepository.delete(existingUser);
130
+        userRepository.flush();
131
+        this.clearUserCaches(existingUser);
132
+        return true;
133
+    }
134
+
135
+    public User createUser(UserDTO userDTO) {
136
+        User user = new User();
137
+        user.setLogin(userDTO.getLogin().toLowerCase());
138
+        user.setFirstName(userDTO.getFirstName());
139
+        user.setLastName(userDTO.getLastName());
140
+        user.setEmail(userDTO.getEmail().toLowerCase());
141
+        user.setImageUrl(userDTO.getImageUrl());
142
+        if (userDTO.getLangKey() == null) {
143
+            user.setLangKey(Constants.DEFAULT_LANGUAGE); // default language
144
+        } else {
145
+            user.setLangKey(userDTO.getLangKey());
146
+        }
147
+        String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword());
148
+        user.setPassword(encryptedPassword);
149
+        user.setResetKey(RandomUtil.generateResetKey());
150
+        user.setResetDate(Instant.now());
151
+        user.setActivated(true);
152
+        if (userDTO.getAuthorities() != null) {
153
+            Set<Authority> authorities = userDTO.getAuthorities().stream()
154
+                .map(authorityRepository::findById)
155
+                .filter(Optional::isPresent)
156
+                .map(Optional::get)
157
+                .collect(Collectors.toSet());
158
+            user.setAuthorities(authorities);
159
+        }
160
+        userRepository.save(user);
161
+        this.clearUserCaches(user);
162
+        log.debug("Created Information for User: {}", user);
163
+        return user;
164
+    }
165
+
166
+    /**
167
+     * Update basic information (first name, last name, email, language) for the current user.
168
+     *
169
+     * @param firstName first name of user
170
+     * @param lastName last name of user
171
+     * @param email email id of user
172
+     * @param langKey language key
173
+     * @param imageUrl image URL of user
174
+     */
175
+    public void updateUser(String firstName, String lastName, String email, String langKey, String imageUrl) {
176
+        SecurityUtils.getCurrentUserLogin()
177
+            .flatMap(userRepository::findOneByLogin)
178
+            .ifPresent(user -> {
179
+                user.setFirstName(firstName);
180
+                user.setLastName(lastName);
181
+                user.setEmail(email.toLowerCase());
182
+                user.setLangKey(langKey);
183
+                user.setImageUrl(imageUrl);
184
+                this.clearUserCaches(user);
185
+                log.debug("Changed Information for User: {}", user);
186
+            });
187
+    }
188
+
189
+    /**
190
+     * Update all information for a specific user, and return the modified user.
191
+     *
192
+     * @param userDTO user to update
193
+     * @return updated user
194
+     */
195
+    public Optional<UserDTO> updateUser(UserDTO userDTO) {
196
+        return Optional.of(userRepository
197
+            .findById(userDTO.getId()))
198
+            .filter(Optional::isPresent)
199
+            .map(Optional::get)
200
+            .map(user -> {
201
+                this.clearUserCaches(user);
202
+                user.setLogin(userDTO.getLogin().toLowerCase());
203
+                user.setFirstName(userDTO.getFirstName());
204
+                user.setLastName(userDTO.getLastName());
205
+                user.setEmail(userDTO.getEmail().toLowerCase());
206
+                user.setImageUrl(userDTO.getImageUrl());
207
+                user.setActivated(userDTO.isActivated());
208
+                user.setLangKey(userDTO.getLangKey());
209
+                Set<Authority> managedAuthorities = user.getAuthorities();
210
+                managedAuthorities.clear();
211
+                userDTO.getAuthorities().stream()
212
+                    .map(authorityRepository::findById)
213
+                    .filter(Optional::isPresent)
214
+                    .map(Optional::get)
215
+                    .forEach(managedAuthorities::add);
216
+                this.clearUserCaches(user);
217
+                log.debug("Changed Information for User: {}", user);
218
+                return user;
219
+            })
220
+            .map(UserDTO::new);
221
+    }
222
+
223
+    public void deleteUser(String login) {
224
+        userRepository.findOneByLogin(login).ifPresent(user -> {
225
+            userRepository.delete(user);
226
+            this.clearUserCaches(user);
227
+            log.debug("Deleted User: {}", user);
228
+        });
229
+    }
230
+
231
+    public void changePassword(String currentClearTextPassword, String newPassword) {
232
+        SecurityUtils.getCurrentUserLogin()
233
+            .flatMap(userRepository::findOneByLogin)
234
+            .ifPresent(user -> {
235
+                String currentEncryptedPassword = user.getPassword();
236
+                if (!passwordEncoder.matches(currentClearTextPassword, currentEncryptedPassword)) {
237
+                    throw new InvalidPasswordException();
238
+                }
239
+                String encryptedPassword = passwordEncoder.encode(newPassword);
240
+                user.setPassword(encryptedPassword);
241
+                this.clearUserCaches(user);
242
+                log.debug("Changed password for User: {}", user);
243
+            });
244
+    }
245
+
246
+    @Transactional(readOnly = true)
247
+    public Page<UserDTO> getAllManagedUsers(Pageable pageable) {
248
+        return userRepository.findAllByLoginNot(pageable, Constants.ANONYMOUS_USER).map(UserDTO::new);
249
+    }
250
+
251
+    @Transactional(readOnly = true)
252
+    public Optional<User> getUserWithAuthoritiesByLogin(String login) {
253
+        return userRepository.findOneWithAuthoritiesByLogin(login);
254
+    }
255
+
256
+    @Transactional(readOnly = true)
257
+    public Optional<User> getUserWithAuthorities(Long id) {
258
+        return userRepository.findOneWithAuthoritiesById(id);
259
+    }
260
+
261
+    @Transactional(readOnly = true)
262
+    public Optional<User> getUserWithAuthorities() {
263
+        return SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneWithAuthoritiesByLogin);
264
+    }
265
+
266
+    /**
267
+     * Not activated users should be automatically deleted after 3 days.
268
+     * <p>
269
+     * This is scheduled to get fired everyday, at 01:00 (am).
270
+     */
271
+    @Scheduled(cron = "0 0 1 * * ?")
272
+    public void removeNotActivatedUsers() {
273
+        userRepository
274
+            .findAllByActivatedIsFalseAndCreatedDateBefore(Instant.now().minus(3, ChronoUnit.DAYS))
275
+            .forEach(user -> {
276
+                log.debug("Deleting not activated user {}", user.getLogin());
277
+                userRepository.delete(user);
278
+                this.clearUserCaches(user);
279
+            });
280
+    }
281
+
282
+    /**
283
+     * @return a list of all the authorities
284
+     */
285
+    public List<String> getAuthorities() {
286
+        return authorityRepository.findAll().stream().map(Authority::getName).collect(Collectors.toList());
287
+    }
288
+
289
+    private void clearUserCaches(User user) {
290
+        Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE)).evict(user.getLogin());
291
+        Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE)).evict(user.getEmail());
292
+    }
293
+}

+ 35
- 0
src/main/java/rocks/zipcode/io/service/dto/PasswordChangeDTO.java Zobrazit soubor

@@ -0,0 +1,35 @@
1
+package rocks.zipcode.io.service.dto;
2
+
3
+/**
4
+ * A DTO representing a password change required data - current and new password.
5
+ */
6
+public class PasswordChangeDTO {
7
+    private String currentPassword;
8
+    private String newPassword;
9
+
10
+    public PasswordChangeDTO() {
11
+        // Empty constructor needed for Jackson.
12
+    }
13
+
14
+    public PasswordChangeDTO(String currentPassword, String newPassword) {
15
+        this.currentPassword = currentPassword;
16
+        this.newPassword = newPassword;
17
+    }
18
+
19
+    public String getCurrentPassword() {
20
+
21
+        return currentPassword;
22
+    }
23
+
24
+    public void setCurrentPassword(String currentPassword) {
25
+        this.currentPassword = currentPassword;
26
+    }
27
+
28
+    public String getNewPassword() {
29
+        return newPassword;
30
+    }
31
+
32
+    public void setNewPassword(String newPassword) {
33
+        this.newPassword = newPassword;
34
+    }
35
+}

+ 199
- 0
src/main/java/rocks/zipcode/io/service/dto/UserDTO.java Zobrazit soubor

@@ -0,0 +1,199 @@
1
+package rocks.zipcode.io.service.dto;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+
5
+import rocks.zipcode.io.domain.Authority;
6
+import rocks.zipcode.io.domain.User;
7
+
8
+import javax.validation.constraints.Email;
9
+import javax.validation.constraints.NotBlank;
10
+
11
+import javax.validation.constraints.*;
12
+import java.time.Instant;
13
+import java.util.Set;
14
+import java.util.stream.Collectors;
15
+
16
+/**
17
+ * A DTO representing a user, with his authorities.
18
+ */
19
+public class UserDTO {
20
+
21
+    private Long id;
22
+
23
+    @NotBlank
24
+    @Pattern(regexp = Constants.LOGIN_REGEX)
25
+    @Size(min = 1, max = 50)
26
+    private String login;
27
+
28
+    @Size(max = 50)
29
+    private String firstName;
30
+
31
+    @Size(max = 50)
32
+    private String lastName;
33
+
34
+    @Email
35
+    @Size(min = 5, max = 254)
36
+    private String email;
37
+
38
+    @Size(max = 256)
39
+    private String imageUrl;
40
+
41
+    private boolean activated = false;
42
+
43
+    @Size(min = 2, max = 6)
44
+    private String langKey;
45
+
46
+    private String createdBy;
47
+
48
+    private Instant createdDate;
49
+
50
+    private String lastModifiedBy;
51
+
52
+    private Instant lastModifiedDate;
53
+
54
+    private Set<String> authorities;
55
+
56
+    public UserDTO() {
57
+        // Empty constructor needed for Jackson.
58
+    }
59
+
60
+    public UserDTO(User user) {
61
+        this.id = user.getId();
62
+        this.login = user.getLogin();
63
+        this.firstName = user.getFirstName();
64
+        this.lastName = user.getLastName();
65
+        this.email = user.getEmail();
66
+        this.activated = user.getActivated();
67
+        this.imageUrl = user.getImageUrl();
68
+        this.langKey = user.getLangKey();
69
+        this.createdBy = user.getCreatedBy();
70
+        this.createdDate = user.getCreatedDate();
71
+        this.lastModifiedBy = user.getLastModifiedBy();
72
+        this.lastModifiedDate = user.getLastModifiedDate();
73
+        this.authorities = user.getAuthorities().stream()
74
+            .map(Authority::getName)
75
+            .collect(Collectors.toSet());
76
+    }
77
+
78
+    public Long getId() {
79
+        return id;
80
+    }
81
+
82
+    public void setId(Long id) {
83
+        this.id = id;
84
+    }
85
+
86
+    public String getLogin() {
87
+        return login;
88
+    }
89
+
90
+    public void setLogin(String login) {
91
+        this.login = login;
92
+    }
93
+
94
+    public String getFirstName() {
95
+        return firstName;
96
+    }
97
+
98
+    public void setFirstName(String firstName) {
99
+        this.firstName = firstName;
100
+    }
101
+
102
+    public String getLastName() {
103
+        return lastName;
104
+    }
105
+
106
+    public void setLastName(String lastName) {
107
+        this.lastName = lastName;
108
+    }
109
+
110
+    public String getEmail() {
111
+        return email;
112
+    }
113
+
114
+    public void setEmail(String email) {
115
+        this.email = email;
116
+    }
117
+
118
+    public String getImageUrl() {
119
+        return imageUrl;
120
+    }
121
+
122
+    public void setImageUrl(String imageUrl) {
123
+        this.imageUrl = imageUrl;
124
+    }
125
+
126
+    public boolean isActivated() {
127
+        return activated;
128
+    }
129
+
130
+    public void setActivated(boolean activated) {
131
+        this.activated = activated;
132
+    }
133
+
134
+    public String getLangKey() {
135
+        return langKey;
136
+    }
137
+
138
+    public void setLangKey(String langKey) {
139
+        this.langKey = langKey;
140
+    }
141
+
142
+    public String getCreatedBy() {
143
+        return createdBy;
144
+    }
145
+
146
+    public void setCreatedBy(String createdBy) {
147
+        this.createdBy = createdBy;
148
+    }
149
+
150
+    public Instant getCreatedDate() {
151
+        return createdDate;
152
+    }
153
+
154
+    public void setCreatedDate(Instant createdDate) {
155
+        this.createdDate = createdDate;
156
+    }
157
+
158
+    public String getLastModifiedBy() {
159
+        return lastModifiedBy;
160
+    }
161
+
162
+    public void setLastModifiedBy(String lastModifiedBy) {
163
+        this.lastModifiedBy = lastModifiedBy;
164
+    }
165
+
166
+    public Instant getLastModifiedDate() {
167
+        return lastModifiedDate;
168
+    }
169
+
170
+    public void setLastModifiedDate(Instant lastModifiedDate) {
171
+        this.lastModifiedDate = lastModifiedDate;
172
+    }
173
+
174
+    public Set<String> getAuthorities() {
175
+        return authorities;
176
+    }
177
+
178
+    public void setAuthorities(Set<String> authorities) {
179
+        this.authorities = authorities;
180
+    }
181
+
182
+    @Override
183
+    public String toString() {
184
+        return "UserDTO{" +
185
+            "login='" + login + '\'' +
186
+            ", firstName='" + firstName + '\'' +
187
+            ", lastName='" + lastName + '\'' +
188
+            ", email='" + email + '\'' +
189
+            ", imageUrl='" + imageUrl + '\'' +
190
+            ", activated=" + activated +
191
+            ", langKey='" + langKey + '\'' +
192
+            ", createdBy=" + createdBy +
193
+            ", createdDate=" + createdDate +
194
+            ", lastModifiedBy='" + lastModifiedBy + '\'' +
195
+            ", lastModifiedDate=" + lastModifiedDate +
196
+            ", authorities=" + authorities +
197
+            "}";
198
+    }
199
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/service/dto/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Data Transfer Objects.
3
+ */
4
+package rocks.zipcode.io.service.dto;

+ 76
- 0
src/main/java/rocks/zipcode/io/service/mapper/UserMapper.java Zobrazit soubor

@@ -0,0 +1,76 @@
1
+package rocks.zipcode.io.service.mapper;
2
+
3
+import rocks.zipcode.io.domain.Authority;
4
+import rocks.zipcode.io.domain.User;
5
+import rocks.zipcode.io.service.dto.UserDTO;
6
+
7
+import org.springframework.stereotype.Service;
8
+
9
+import java.util.*;
10
+import java.util.stream.Collectors;
11
+
12
+/**
13
+ * Mapper for the entity User and its DTO called UserDTO.
14
+ *
15
+ * Normal mappers are generated using MapStruct, this one is hand-coded as MapStruct
16
+ * support is still in beta, and requires a manual step with an IDE.
17
+ */
18
+@Service
19
+public class UserMapper {
20
+
21
+    public UserDTO userToUserDTO(User user) {
22
+        return new UserDTO(user);
23
+    }
24
+
25
+    public List<UserDTO> usersToUserDTOs(List<User> users) {
26
+        return users.stream()
27
+            .filter(Objects::nonNull)
28
+            .map(this::userToUserDTO)
29
+            .collect(Collectors.toList());
30
+    }
31
+
32
+    public User userDTOToUser(UserDTO userDTO) {
33
+        if (userDTO == null) {
34
+            return null;
35
+        } else {
36
+            User user = new User();
37
+            user.setId(userDTO.getId());
38
+            user.setLogin(userDTO.getLogin());
39
+            user.setFirstName(userDTO.getFirstName());
40
+            user.setLastName(userDTO.getLastName());
41
+            user.setEmail(userDTO.getEmail());
42
+            user.setImageUrl(userDTO.getImageUrl());
43
+            user.setActivated(userDTO.isActivated());
44
+            user.setLangKey(userDTO.getLangKey());
45
+            Set<Authority> authorities = this.authoritiesFromStrings(userDTO.getAuthorities());
46
+            if (authorities != null) {
47
+                user.setAuthorities(authorities);
48
+            }
49
+            return user;
50
+        }
51
+    }
52
+
53
+    public List<User> userDTOsToUsers(List<UserDTO> userDTOs) {
54
+        return userDTOs.stream()
55
+            .filter(Objects::nonNull)
56
+            .map(this::userDTOToUser)
57
+            .collect(Collectors.toList());
58
+    }
59
+
60
+    public User userFromId(Long id) {
61
+        if (id == null) {
62
+            return null;
63
+        }
64
+        User user = new User();
65
+        user.setId(id);
66
+        return user;
67
+    }
68
+
69
+    public Set<Authority> authoritiesFromStrings(Set<String> strings) {
70
+        return strings.stream().map(string -> {
71
+            Authority auth = new Authority();
72
+            auth.setName(string);
73
+            return auth;
74
+        }).collect(Collectors.toSet());
75
+    }
76
+}

+ 4
- 0
src/main/java/rocks/zipcode/io/service/mapper/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * MapStruct mappers for mapping domain objects and Data Transfer Objects.
3
+ */
4
+package rocks.zipcode.io.service.mapper;

+ 4
- 0
src/main/java/rocks/zipcode/io/service/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Service layer beans.
3
+ */
4
+package rocks.zipcode.io.service;

+ 41
- 0
src/main/java/rocks/zipcode/io/service/util/RandomUtil.java Zobrazit soubor

@@ -0,0 +1,41 @@
1
+package rocks.zipcode.io.service.util;
2
+
3
+import org.apache.commons.lang3.RandomStringUtils;
4
+
5
+/**
6
+ * Utility class for generating random Strings.
7
+ */
8
+public final class RandomUtil {
9
+
10
+    private static final int DEF_COUNT = 20;
11
+
12
+    private RandomUtil() {
13
+    }
14
+
15
+    /**
16
+     * Generate a password.
17
+     *
18
+     * @return the generated password
19
+     */
20
+    public static String generatePassword() {
21
+        return RandomStringUtils.randomAlphanumeric(DEF_COUNT);
22
+    }
23
+
24
+    /**
25
+     * Generate an activation key.
26
+     *
27
+     * @return the generated activation key
28
+     */
29
+    public static String generateActivationKey() {
30
+        return RandomStringUtils.randomNumeric(DEF_COUNT);
31
+    }
32
+
33
+    /**
34
+     * Generate a reset key.
35
+     *
36
+     * @return the generated reset key
37
+     */
38
+    public static String generateResetKey() {
39
+        return RandomStringUtils.randomNumeric(DEF_COUNT);
40
+    }
41
+}

+ 189
- 0
src/main/java/rocks/zipcode/io/web/rest/AccountResource.java Zobrazit soubor

@@ -0,0 +1,189 @@
1
+package rocks.zipcode.io.web.rest;
2
+
3
+import com.codahale.metrics.annotation.Timed;
4
+
5
+import rocks.zipcode.io.domain.User;
6
+import rocks.zipcode.io.repository.UserRepository;
7
+import rocks.zipcode.io.security.SecurityUtils;
8
+import rocks.zipcode.io.service.MailService;
9
+import rocks.zipcode.io.service.UserService;
10
+import rocks.zipcode.io.service.dto.PasswordChangeDTO;
11
+import rocks.zipcode.io.service.dto.UserDTO;
12
+import rocks.zipcode.io.web.rest.errors.*;
13
+import rocks.zipcode.io.web.rest.vm.KeyAndPasswordVM;
14
+import rocks.zipcode.io.web.rest.vm.ManagedUserVM;
15
+
16
+import org.apache.commons.lang3.StringUtils;
17
+import org.slf4j.Logger;
18
+import org.slf4j.LoggerFactory;
19
+import org.springframework.http.HttpStatus;
20
+import org.springframework.web.bind.annotation.*;
21
+
22
+import javax.servlet.http.HttpServletRequest;
23
+import javax.validation.Valid;
24
+import java.util.*;
25
+
26
+
27
+/**
28
+ * REST controller for managing the current user's account.
29
+ */
30
+@RestController
31
+@RequestMapping("/api")
32
+public class AccountResource {
33
+
34
+    private final Logger log = LoggerFactory.getLogger(AccountResource.class);
35
+
36
+    private final UserRepository userRepository;
37
+
38
+    private final UserService userService;
39
+
40
+    private final MailService mailService;
41
+
42
+    public AccountResource(UserRepository userRepository, UserService userService, MailService mailService) {
43
+
44
+        this.userRepository = userRepository;
45
+        this.userService = userService;
46
+        this.mailService = mailService;
47
+    }
48
+
49
+    /**
50
+     * POST  /register : register the user.
51
+     *
52
+     * @param managedUserVM the managed user View Model
53
+     * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect
54
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used
55
+     * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already used
56
+     */
57
+    @PostMapping("/register")
58
+    @Timed
59
+    @ResponseStatus(HttpStatus.CREATED)
60
+    public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) {
61
+        if (!checkPasswordLength(managedUserVM.getPassword())) {
62
+            throw new InvalidPasswordException();
63
+        }
64
+        User user = userService.registerUser(managedUserVM, managedUserVM.getPassword());
65
+        mailService.sendActivationEmail(user);
66
+    }
67
+
68
+    /**
69
+     * GET  /activate : activate the registered user.
70
+     *
71
+     * @param key the activation key
72
+     * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be activated
73
+     */
74
+    @GetMapping("/activate")
75
+    @Timed
76
+    public void activateAccount(@RequestParam(value = "key") String key) {
77
+        Optional<User> user = userService.activateRegistration(key);
78
+        if (!user.isPresent()) {
79
+            throw new InternalServerErrorException("No user was found for this activation key");
80
+        }
81
+    }
82
+
83
+    /**
84
+     * GET  /authenticate : check if the user is authenticated, and return its login.
85
+     *
86
+     * @param request the HTTP request
87
+     * @return the login if the user is authenticated
88
+     */
89
+    @GetMapping("/authenticate")
90
+    @Timed
91
+    public String isAuthenticated(HttpServletRequest request) {
92
+        log.debug("REST request to check if the current user is authenticated");
93
+        return request.getRemoteUser();
94
+    }
95
+
96
+    /**
97
+     * GET  /account : get the current user.
98
+     *
99
+     * @return the current user
100
+     * @throws RuntimeException 500 (Internal Server Error) if the user couldn't be returned
101
+     */
102
+    @GetMapping("/account")
103
+    @Timed
104
+    public UserDTO getAccount() {
105
+        return userService.getUserWithAuthorities()
106
+            .map(UserDTO::new)
107
+            .orElseThrow(() -> new InternalServerErrorException("User could not be found"));
108
+    }
109
+
110
+    /**
111
+     * POST  /account : update the current user information.
112
+     *
113
+     * @param userDTO the current user information
114
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already used
115
+     * @throws RuntimeException 500 (Internal Server Error) if the user login wasn't found
116
+     */
117
+    @PostMapping("/account")
118
+    @Timed
119
+    public void saveAccount(@Valid @RequestBody UserDTO userDTO) {
120
+        final String userLogin = SecurityUtils.getCurrentUserLogin().orElseThrow(() -> new InternalServerErrorException("Current user login not found"));
121
+        Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail());
122
+        if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userLogin))) {
123
+            throw new EmailAlreadyUsedException();
124
+        }
125
+        Optional<User> user = userRepository.findOneByLogin(userLogin);
126
+        if (!user.isPresent()) {
127
+            throw new InternalServerErrorException("User could not be found");
128
+        }
129
+        userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(),
130
+            userDTO.getLangKey(), userDTO.getImageUrl());
131
+    }
132
+
133
+    /**
134
+     * POST  /account/change-password : changes the current user's password
135
+     *
136
+     * @param passwordChangeDto current and new password
137
+     * @throws InvalidPasswordException 400 (Bad Request) if the new password is incorrect
138
+     */
139
+    @PostMapping(path = "/account/change-password")
140
+    @Timed
141
+    public void changePassword(@RequestBody PasswordChangeDTO passwordChangeDto) {
142
+        if (!checkPasswordLength(passwordChangeDto.getNewPassword())) {
143
+            throw new InvalidPasswordException();
144
+        }
145
+        userService.changePassword(passwordChangeDto.getCurrentPassword(), passwordChangeDto.getNewPassword());
146
+    }
147
+
148
+    /**
149
+     * POST   /account/reset-password/init : Send an email to reset the password of the user
150
+     *
151
+     * @param mail the mail of the user
152
+     * @throws EmailNotFoundException 400 (Bad Request) if the email address is not registered
153
+     */
154
+    @PostMapping(path = "/account/reset-password/init")
155
+    @Timed
156
+    public void requestPasswordReset(@RequestBody String mail) {
157
+       mailService.sendPasswordResetMail(
158
+           userService.requestPasswordReset(mail)
159
+               .orElseThrow(EmailNotFoundException::new)
160
+       );
161
+    }
162
+
163
+    /**
164
+     * POST   /account/reset-password/finish : Finish to reset the password of the user
165
+     *
166
+     * @param keyAndPassword the generated key and the new password
167
+     * @throws InvalidPasswordException 400 (Bad Request) if the password is incorrect
168
+     * @throws RuntimeException 500 (Internal Server Error) if the password could not be reset
169
+     */
170
+    @PostMapping(path = "/account/reset-password/finish")
171
+    @Timed
172
+    public void finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) {
173
+        if (!checkPasswordLength(keyAndPassword.getNewPassword())) {
174
+            throw new InvalidPasswordException();
175
+        }
176
+        Optional<User> user =
177
+            userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey());
178
+
179
+        if (!user.isPresent()) {
180
+            throw new InternalServerErrorException("No user was found for this reset key");
181
+        }
182
+    }
183
+
184
+    private static boolean checkPasswordLength(String password) {
185
+        return !StringUtils.isEmpty(password) &&
186
+            password.length() >= ManagedUserVM.PASSWORD_MIN_LENGTH &&
187
+            password.length() <= ManagedUserVM.PASSWORD_MAX_LENGTH;
188
+    }
189
+}

+ 77
- 0
src/main/java/rocks/zipcode/io/web/rest/AuditResource.java Zobrazit soubor

@@ -0,0 +1,77 @@
1
+package rocks.zipcode.io.web.rest;
2
+
3
+import rocks.zipcode.io.service.AuditEventService;
4
+import rocks.zipcode.io.web.rest.util.PaginationUtil;
5
+
6
+import io.github.jhipster.web.util.ResponseUtil;
7
+import org.springframework.boot.actuate.audit.AuditEvent;
8
+import org.springframework.data.domain.Page;
9
+import org.springframework.data.domain.Pageable;
10
+import org.springframework.http.HttpHeaders;
11
+import org.springframework.http.HttpStatus;
12
+import org.springframework.http.ResponseEntity;
13
+import org.springframework.web.bind.annotation.*;
14
+
15
+import java.time.LocalDate;
16
+import java.time.ZoneId;
17
+import java.util.List;
18
+
19
+/**
20
+ * REST controller for getting the audit events.
21
+ */
22
+@RestController
23
+@RequestMapping("/management/audits")
24
+public class AuditResource {
25
+
26
+    private final AuditEventService auditEventService;
27
+
28
+    public AuditResource(AuditEventService auditEventService) {
29
+        this.auditEventService = auditEventService;
30
+    }
31
+
32
+    /**
33
+     * GET /audits : get a page of AuditEvents.
34
+     *
35
+     * @param pageable the pagination information
36
+     * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
37
+     */
38
+    @GetMapping
39
+    public ResponseEntity<List<AuditEvent>> getAll(Pageable pageable) {
40
+        Page<AuditEvent> page = auditEventService.findAll(pageable);
41
+        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits");
42
+        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
43
+    }
44
+
45
+    /**
46
+     * GET  /audits : get a page of AuditEvents between the fromDate and toDate.
47
+     *
48
+     * @param fromDate the start of the time period of AuditEvents to get
49
+     * @param toDate the end of the time period of AuditEvents to get
50
+     * @param pageable the pagination information
51
+     * @return the ResponseEntity with status 200 (OK) and the list of AuditEvents in body
52
+     */
53
+    @GetMapping(params = {"fromDate", "toDate"})
54
+    public ResponseEntity<List<AuditEvent>> getByDates(
55
+        @RequestParam(value = "fromDate") LocalDate fromDate,
56
+        @RequestParam(value = "toDate") LocalDate toDate,
57
+        Pageable pageable) {
58
+
59
+        Page<AuditEvent> page = auditEventService.findByDates(
60
+            fromDate.atStartOfDay(ZoneId.systemDefault()).toInstant(),
61
+            toDate.atStartOfDay(ZoneId.systemDefault()).plusDays(1).toInstant(),
62
+            pageable);
63
+        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/management/audits");
64
+        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
65
+    }
66
+
67
+    /**
68
+     * GET  /audits/:id : get an AuditEvent by id.
69
+     *
70
+     * @param id the id of the entity to get
71
+     * @return the ResponseEntity with status 200 (OK) and the AuditEvent in body, or status 404 (Not Found)
72
+     */
73
+    @GetMapping("/{id:.+}")
74
+    public ResponseEntity<AuditEvent> get(@PathVariable Long id) {
75
+        return ResponseUtil.wrapOrNotFound(auditEventService.find(id));
76
+    }
77
+}

+ 39
- 0
src/main/java/rocks/zipcode/io/web/rest/LogsResource.java Zobrazit soubor

@@ -0,0 +1,39 @@
1
+package rocks.zipcode.io.web.rest;
2
+
3
+import rocks.zipcode.io.web.rest.vm.LoggerVM;
4
+
5
+import ch.qos.logback.classic.Level;
6
+import ch.qos.logback.classic.LoggerContext;
7
+import com.codahale.metrics.annotation.Timed;
8
+import org.slf4j.LoggerFactory;
9
+import org.springframework.http.HttpStatus;
10
+import org.springframework.web.bind.annotation.*;
11
+
12
+import java.util.List;
13
+import java.util.stream.Collectors;
14
+
15
+/**
16
+ * Controller for view and managing Log Level at runtime.
17
+ */
18
+@RestController
19
+@RequestMapping("/management")
20
+public class LogsResource {
21
+
22
+    @GetMapping("/logs")
23
+    @Timed
24
+    public List<LoggerVM> getList() {
25
+        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
26
+        return context.getLoggerList()
27
+            .stream()
28
+            .map(LoggerVM::new)
29
+            .collect(Collectors.toList());
30
+    }
31
+
32
+    @PutMapping("/logs")
33
+    @ResponseStatus(HttpStatus.NO_CONTENT)
34
+    @Timed
35
+    public void changeLevel(@RequestBody LoggerVM jsonLogger) {
36
+        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
37
+        context.getLogger(jsonLogger.getName()).setLevel(Level.valueOf(jsonLogger.getLevel()));
38
+    }
39
+}

+ 73
- 0
src/main/java/rocks/zipcode/io/web/rest/UserJWTController.java Zobrazit soubor

@@ -0,0 +1,73 @@
1
+package rocks.zipcode.io.web.rest;
2
+
3
+import rocks.zipcode.io.security.jwt.JWTFilter;
4
+import rocks.zipcode.io.security.jwt.TokenProvider;
5
+import rocks.zipcode.io.web.rest.vm.LoginVM;
6
+
7
+import com.codahale.metrics.annotation.Timed;
8
+import com.fasterxml.jackson.annotation.JsonProperty;
9
+
10
+import org.springframework.http.HttpHeaders;
11
+import org.springframework.http.HttpStatus;
12
+import org.springframework.http.ResponseEntity;
13
+import org.springframework.security.authentication.AuthenticationManager;
14
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
15
+import org.springframework.security.core.Authentication;
16
+import org.springframework.security.core.context.SecurityContextHolder;
17
+import org.springframework.web.bind.annotation.*;
18
+
19
+import javax.validation.Valid;
20
+
21
+/**
22
+ * Controller to authenticate users.
23
+ */
24
+@RestController
25
+@RequestMapping("/api")
26
+public class UserJWTController {
27
+
28
+    private final TokenProvider tokenProvider;
29
+
30
+    private final AuthenticationManager authenticationManager;
31
+
32
+    public UserJWTController(TokenProvider tokenProvider, AuthenticationManager authenticationManager) {
33
+        this.tokenProvider = tokenProvider;
34
+        this.authenticationManager = authenticationManager;
35
+    }
36
+
37
+    @PostMapping("/authenticate")
38
+    @Timed
39
+    public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) {
40
+
41
+        UsernamePasswordAuthenticationToken authenticationToken =
42
+            new UsernamePasswordAuthenticationToken(loginVM.getUsername(), loginVM.getPassword());
43
+
44
+        Authentication authentication = this.authenticationManager.authenticate(authenticationToken);
45
+        SecurityContextHolder.getContext().setAuthentication(authentication);
46
+        boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe();
47
+        String jwt = tokenProvider.createToken(authentication, rememberMe);
48
+        HttpHeaders httpHeaders = new HttpHeaders();
49
+        httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt);
50
+        return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK);
51
+    }
52
+
53
+    /**
54
+     * Object to return as body in JWT Authentication.
55
+     */
56
+    static class JWTToken {
57
+
58
+        private String idToken;
59
+
60
+        JWTToken(String idToken) {
61
+            this.idToken = idToken;
62
+        }
63
+
64
+        @JsonProperty("id_token")
65
+        String getIdToken() {
66
+            return idToken;
67
+        }
68
+
69
+        void setIdToken(String idToken) {
70
+            this.idToken = idToken;
71
+        }
72
+    }
73
+}

+ 190
- 0
src/main/java/rocks/zipcode/io/web/rest/UserResource.java Zobrazit soubor

@@ -0,0 +1,190 @@
1
+package rocks.zipcode.io.web.rest;
2
+
3
+import rocks.zipcode.io.config.Constants;
4
+import rocks.zipcode.io.domain.User;
5
+import rocks.zipcode.io.repository.UserRepository;
6
+import rocks.zipcode.io.security.AuthoritiesConstants;
7
+import rocks.zipcode.io.service.MailService;
8
+import rocks.zipcode.io.service.UserService;
9
+import rocks.zipcode.io.service.dto.UserDTO;
10
+import rocks.zipcode.io.web.rest.errors.BadRequestAlertException;
11
+import rocks.zipcode.io.web.rest.errors.EmailAlreadyUsedException;
12
+import rocks.zipcode.io.web.rest.errors.LoginAlreadyUsedException;
13
+import rocks.zipcode.io.web.rest.util.HeaderUtil;
14
+import rocks.zipcode.io.web.rest.util.PaginationUtil;
15
+import com.codahale.metrics.annotation.Timed;
16
+import io.github.jhipster.web.util.ResponseUtil;
17
+
18
+import org.slf4j.Logger;
19
+import org.slf4j.LoggerFactory;
20
+import org.springframework.data.domain.Page;
21
+import org.springframework.data.domain.Pageable;
22
+import org.springframework.http.HttpHeaders;
23
+import org.springframework.http.HttpStatus;
24
+import org.springframework.http.ResponseEntity;
25
+import org.springframework.security.access.prepost.PreAuthorize;
26
+import org.springframework.web.bind.annotation.*;
27
+
28
+import javax.validation.Valid;
29
+import java.net.URI;
30
+import java.net.URISyntaxException;
31
+import java.util.*;
32
+
33
+/**
34
+ * REST controller for managing users.
35
+ * <p>
36
+ * This class accesses the User entity, and needs to fetch its collection of authorities.
37
+ * <p>
38
+ * For a normal use-case, it would be better to have an eager relationship between User and Authority,
39
+ * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join
40
+ * which would be good for performance.
41
+ * <p>
42
+ * We use a View Model and a DTO for 3 reasons:
43
+ * <ul>
44
+ * <li>We want to keep a lazy association between the user and the authorities, because people will
45
+ * quite often do relationships with the user, and we don't want them to get the authorities all
46
+ * the time for nothing (for performance reasons). This is the #1 goal: we should not impact our users'
47
+ * application because of this use-case.</li>
48
+ * <li> Not having an outer join causes n+1 requests to the database. This is not a real issue as
49
+ * we have by default a second-level cache. This means on the first HTTP call we do the n+1 requests,
50
+ * but then all authorities come from the cache, so in fact it's much better than doing an outer join
51
+ * (which will get lots of data from the database, for each HTTP call).</li>
52
+ * <li> As this manages users, for security reasons, we'd rather have a DTO layer.</li>
53
+ * </ul>
54
+ * <p>
55
+ * Another option would be to have a specific JPA entity graph to handle this case.
56
+ */
57
+@RestController
58
+@RequestMapping("/api")
59
+public class UserResource {
60
+
61
+    private final Logger log = LoggerFactory.getLogger(UserResource.class);
62
+
63
+    private final UserService userService;
64
+
65
+    private final UserRepository userRepository;
66
+
67
+    private final MailService mailService;
68
+
69
+    public UserResource(UserService userService, UserRepository userRepository, MailService mailService) {
70
+
71
+        this.userService = userService;
72
+        this.userRepository = userRepository;
73
+        this.mailService = mailService;
74
+    }
75
+
76
+    /**
77
+     * POST  /users  : Creates a new user.
78
+     * <p>
79
+     * Creates a new user if the login and email are not already used, and sends an
80
+     * mail with an activation link.
81
+     * The user needs to be activated on creation.
82
+     *
83
+     * @param userDTO the user to create
84
+     * @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
85
+     * @throws URISyntaxException if the Location URI syntax is incorrect
86
+     * @throws BadRequestAlertException 400 (Bad Request) if the login or email is already in use
87
+     */
88
+    @PostMapping("/users")
89
+    @Timed
90
+    @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
91
+    public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO userDTO) throws URISyntaxException {
92
+        log.debug("REST request to save User : {}", userDTO);
93
+
94
+        if (userDTO.getId() != null) {
95
+            throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists");
96
+            // Lowercase the user login before comparing with database
97
+        } else if (userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).isPresent()) {
98
+            throw new LoginAlreadyUsedException();
99
+        } else if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).isPresent()) {
100
+            throw new EmailAlreadyUsedException();
101
+        } else {
102
+            User newUser = userService.createUser(userDTO);
103
+            mailService.sendCreationEmail(newUser);
104
+            return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin()))
105
+                .headers(HeaderUtil.createAlert( "userManagement.created", newUser.getLogin()))
106
+                .body(newUser);
107
+        }
108
+    }
109
+
110
+    /**
111
+     * PUT /users : Updates an existing User.
112
+     *
113
+     * @param userDTO the user to update
114
+     * @return the ResponseEntity with status 200 (OK) and with body the updated user
115
+     * @throws EmailAlreadyUsedException 400 (Bad Request) if the email is already in use
116
+     * @throws LoginAlreadyUsedException 400 (Bad Request) if the login is already in use
117
+     */
118
+    @PutMapping("/users")
119
+    @Timed
120
+    @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
121
+    public ResponseEntity<UserDTO> updateUser(@Valid @RequestBody UserDTO userDTO) {
122
+        log.debug("REST request to update User : {}", userDTO);
123
+        Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail());
124
+        if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) {
125
+            throw new EmailAlreadyUsedException();
126
+        }
127
+        existingUser = userRepository.findOneByLogin(userDTO.getLogin().toLowerCase());
128
+        if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) {
129
+            throw new LoginAlreadyUsedException();
130
+        }
131
+        Optional<UserDTO> updatedUser = userService.updateUser(userDTO);
132
+
133
+        return ResponseUtil.wrapOrNotFound(updatedUser,
134
+            HeaderUtil.createAlert("userManagement.updated", userDTO.getLogin()));
135
+    }
136
+
137
+    /**
138
+     * GET /users : get all users.
139
+     *
140
+     * @param pageable the pagination information
141
+     * @return the ResponseEntity with status 200 (OK) and with body all users
142
+     */
143
+    @GetMapping("/users")
144
+    @Timed
145
+    public ResponseEntity<List<UserDTO>> getAllUsers(Pageable pageable) {
146
+        final Page<UserDTO> page = userService.getAllManagedUsers(pageable);
147
+        HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(page, "/api/users");
148
+        return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK);
149
+    }
150
+
151
+    /**
152
+     * @return a string list of the all of the roles
153
+     */
154
+    @GetMapping("/users/authorities")
155
+    @Timed
156
+    @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
157
+    public List<String> getAuthorities() {
158
+        return userService.getAuthorities();
159
+    }
160
+
161
+    /**
162
+     * GET /users/:login : get the "login" user.
163
+     *
164
+     * @param login the login of the user to find
165
+     * @return the ResponseEntity with status 200 (OK) and with body the "login" user, or with status 404 (Not Found)
166
+     */
167
+    @GetMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
168
+    @Timed
169
+    public ResponseEntity<UserDTO> getUser(@PathVariable String login) {
170
+        log.debug("REST request to get User : {}", login);
171
+        return ResponseUtil.wrapOrNotFound(
172
+            userService.getUserWithAuthoritiesByLogin(login)
173
+                .map(UserDTO::new));
174
+    }
175
+
176
+    /**
177
+     * DELETE /users/:login : delete the "login" User.
178
+     *
179
+     * @param login the login of the user to delete
180
+     * @return the ResponseEntity with status 200 (OK)
181
+     */
182
+    @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}")
183
+    @Timed
184
+    @PreAuthorize("hasRole(\"" + AuthoritiesConstants.ADMIN + "\")")
185
+    public ResponseEntity<Void> deleteUser(@PathVariable String login) {
186
+        log.debug("REST request to delete User: {}", login);
187
+        userService.deleteUser(login);
188
+        return ResponseEntity.ok().headers(HeaderUtil.createAlert( "userManagement.deleted", login)).build();
189
+    }
190
+}

+ 42
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/BadRequestAlertException.java Zobrazit soubor

@@ -0,0 +1,42 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import org.zalando.problem.AbstractThrowableProblem;
4
+import org.zalando.problem.Status;
5
+
6
+import java.net.URI;
7
+import java.util.HashMap;
8
+import java.util.Map;
9
+
10
+public class BadRequestAlertException extends AbstractThrowableProblem {
11
+
12
+    private static final long serialVersionUID = 1L;
13
+
14
+    private final String entityName;
15
+
16
+    private final String errorKey;
17
+
18
+    public BadRequestAlertException(String defaultMessage, String entityName, String errorKey) {
19
+        this(ErrorConstants.DEFAULT_TYPE, defaultMessage, entityName, errorKey);
20
+    }
21
+
22
+    public BadRequestAlertException(URI type, String defaultMessage, String entityName, String errorKey) {
23
+        super(type, defaultMessage, Status.BAD_REQUEST, null, null, null, getAlertParameters(entityName, errorKey));
24
+        this.entityName = entityName;
25
+        this.errorKey = errorKey;
26
+    }
27
+
28
+    public String getEntityName() {
29
+        return entityName;
30
+    }
31
+
32
+    public String getErrorKey() {
33
+        return errorKey;
34
+    }
35
+
36
+    private static Map<String, Object> getAlertParameters(String entityName, String errorKey) {
37
+        Map<String, Object> parameters = new HashMap<>();
38
+        parameters.put("message", "error." + errorKey);
39
+        parameters.put("params", entityName);
40
+        return parameters;
41
+    }
42
+}

+ 54
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/CustomParameterizedException.java Zobrazit soubor

@@ -0,0 +1,54 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import org.zalando.problem.AbstractThrowableProblem;
4
+
5
+import java.util.HashMap;
6
+import java.util.Map;
7
+
8
+import static org.zalando.problem.Status.BAD_REQUEST;
9
+
10
+/**
11
+ * Custom, parameterized exception, which can be translated on the client side.
12
+ * For example:
13
+ *
14
+ * <pre>
15
+ * throw new CustomParameterizedException(&quot;myCustomError&quot;, &quot;hello&quot;, &quot;world&quot;);
16
+ * </pre>
17
+ *
18
+ * Can be translated with:
19
+ *
20
+ * <pre>
21
+ * "error.myCustomError" :  "The server says {{param0}} to {{param1}}"
22
+ * </pre>
23
+ */
24
+public class CustomParameterizedException extends AbstractThrowableProblem {
25
+
26
+    private static final long serialVersionUID = 1L;
27
+
28
+    private static final String PARAM = "param";
29
+
30
+    public CustomParameterizedException(String message, String... params) {
31
+        this(message, toParamMap(params));
32
+    }
33
+
34
+    public CustomParameterizedException(String message, Map<String, Object> paramMap) {
35
+        super(ErrorConstants.PARAMETERIZED_TYPE, "Parameterized Exception", BAD_REQUEST, null, null, null, toProblemParameters(message, paramMap));
36
+    }
37
+
38
+    public static Map<String, Object> toParamMap(String... params) {
39
+        Map<String, Object> paramMap = new HashMap<>();
40
+        if (params != null && params.length > 0) {
41
+            for (int i = 0; i < params.length; i++) {
42
+                paramMap.put(PARAM + i, params[i]);
43
+            }
44
+        }
45
+        return paramMap;
46
+    }
47
+
48
+    public static Map<String, Object> toProblemParameters(String message, Map<String, Object> paramMap) {
49
+        Map<String, Object> parameters = new HashMap<>();
50
+        parameters.put("message", message);
51
+        parameters.put("params", paramMap);
52
+        return parameters;
53
+    }
54
+}

+ 10
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/EmailAlreadyUsedException.java Zobrazit soubor

@@ -0,0 +1,10 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+public class EmailAlreadyUsedException extends BadRequestAlertException {
4
+
5
+    private static final long serialVersionUID = 1L;
6
+
7
+    public EmailAlreadyUsedException() {
8
+        super(ErrorConstants.EMAIL_ALREADY_USED_TYPE, "Email is already in use!", "userManagement", "emailexists");
9
+    }
10
+}

+ 13
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/EmailNotFoundException.java Zobrazit soubor

@@ -0,0 +1,13 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import org.zalando.problem.AbstractThrowableProblem;
4
+import org.zalando.problem.Status;
5
+
6
+public class EmailNotFoundException extends AbstractThrowableProblem {
7
+
8
+    private static final long serialVersionUID = 1L;
9
+
10
+    public EmailNotFoundException() {
11
+        super(ErrorConstants.EMAIL_NOT_FOUND_TYPE, "Email address not registered", Status.BAD_REQUEST);
12
+    }
13
+}

+ 21
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/ErrorConstants.java Zobrazit soubor

@@ -0,0 +1,21 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import java.net.URI;
4
+
5
+public final class ErrorConstants {
6
+
7
+    public static final String ERR_CONCURRENCY_FAILURE = "error.concurrencyFailure";
8
+    public static final String ERR_VALIDATION = "error.validation";
9
+    public static final String PROBLEM_BASE_URL = "https://www.jhipster.tech/problem";
10
+    public static final URI DEFAULT_TYPE = URI.create(PROBLEM_BASE_URL + "/problem-with-message");
11
+    public static final URI CONSTRAINT_VIOLATION_TYPE = URI.create(PROBLEM_BASE_URL + "/constraint-violation");
12
+    public static final URI PARAMETERIZED_TYPE = URI.create(PROBLEM_BASE_URL + "/parameterized");
13
+    public static final URI ENTITY_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/entity-not-found");
14
+    public static final URI INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password");
15
+    public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used");
16
+    public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used");
17
+    public static final URI EMAIL_NOT_FOUND_TYPE = URI.create(PROBLEM_BASE_URL + "/email-not-found");
18
+
19
+    private ErrorConstants() {
20
+    }
21
+}

+ 107
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/ExceptionTranslator.java Zobrazit soubor

@@ -0,0 +1,107 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import rocks.zipcode.io.web.rest.util.HeaderUtil;
4
+
5
+import org.springframework.dao.ConcurrencyFailureException;
6
+import org.springframework.http.ResponseEntity;
7
+import org.springframework.validation.BindingResult;
8
+import org.springframework.web.bind.MethodArgumentNotValidException;
9
+import org.springframework.web.bind.annotation.ControllerAdvice;
10
+import org.springframework.web.bind.annotation.ExceptionHandler;
11
+import org.springframework.web.context.request.NativeWebRequest;
12
+import org.zalando.problem.DefaultProblem;
13
+import org.zalando.problem.Problem;
14
+import org.zalando.problem.ProblemBuilder;
15
+import org.zalando.problem.Status;
16
+import org.zalando.problem.spring.web.advice.ProblemHandling;
17
+import org.zalando.problem.violations.ConstraintViolationProblem;
18
+
19
+import javax.annotation.Nonnull;
20
+import javax.annotation.Nullable;
21
+import javax.servlet.http.HttpServletRequest;
22
+import java.util.List;
23
+import java.util.NoSuchElementException;
24
+import java.util.stream.Collectors;
25
+
26
+/**
27
+ * Controller advice to translate the server side exceptions to client-friendly json structures.
28
+ * The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807)
29
+ */
30
+@ControllerAdvice
31
+public class ExceptionTranslator implements ProblemHandling {
32
+
33
+    /**
34
+     * Post-process the Problem payload to add the message key for the front-end if needed
35
+     */
36
+    @Override
37
+    public ResponseEntity<Problem> process(@Nullable ResponseEntity<Problem> entity, NativeWebRequest request) {
38
+        if (entity == null) {
39
+            return entity;
40
+        }
41
+        Problem problem = entity.getBody();
42
+        if (!(problem instanceof ConstraintViolationProblem || problem instanceof DefaultProblem)) {
43
+            return entity;
44
+        }
45
+        ProblemBuilder builder = Problem.builder()
46
+            .withType(Problem.DEFAULT_TYPE.equals(problem.getType()) ? ErrorConstants.DEFAULT_TYPE : problem.getType())
47
+            .withStatus(problem.getStatus())
48
+            .withTitle(problem.getTitle())
49
+            .with("path", request.getNativeRequest(HttpServletRequest.class).getRequestURI());
50
+
51
+        if (problem instanceof ConstraintViolationProblem) {
52
+            builder
53
+                .with("violations", ((ConstraintViolationProblem) problem).getViolations())
54
+                .with("message", ErrorConstants.ERR_VALIDATION);
55
+        } else {
56
+            builder
57
+                .withCause(((DefaultProblem) problem).getCause())
58
+                .withDetail(problem.getDetail())
59
+                .withInstance(problem.getInstance());
60
+            problem.getParameters().forEach(builder::with);
61
+            if (!problem.getParameters().containsKey("message") && problem.getStatus() != null) {
62
+                builder.with("message", "error.http." + problem.getStatus().getStatusCode());
63
+            }
64
+        }
65
+        return new ResponseEntity<>(builder.build(), entity.getHeaders(), entity.getStatusCode());
66
+    }
67
+
68
+    @Override
69
+    public ResponseEntity<Problem> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, @Nonnull NativeWebRequest request) {
70
+        BindingResult result = ex.getBindingResult();
71
+        List<FieldErrorVM> fieldErrors = result.getFieldErrors().stream()
72
+            .map(f -> new FieldErrorVM(f.getObjectName(), f.getField(), f.getCode()))
73
+            .collect(Collectors.toList());
74
+
75
+        Problem problem = Problem.builder()
76
+            .withType(ErrorConstants.CONSTRAINT_VIOLATION_TYPE)
77
+            .withTitle("Method argument not valid")
78
+            .withStatus(defaultConstraintViolationStatus())
79
+            .with("message", ErrorConstants.ERR_VALIDATION)
80
+            .with("fieldErrors", fieldErrors)
81
+            .build();
82
+        return create(ex, problem, request);
83
+    }
84
+
85
+    @ExceptionHandler
86
+    public ResponseEntity<Problem> handleNoSuchElementException(NoSuchElementException ex, NativeWebRequest request) {
87
+        Problem problem = Problem.builder()
88
+            .withStatus(Status.NOT_FOUND)
89
+            .with("message", ErrorConstants.ENTITY_NOT_FOUND_TYPE)
90
+            .build();
91
+        return create(ex, problem, request);
92
+    }
93
+
94
+    @ExceptionHandler
95
+    public ResponseEntity<Problem> handleBadRequestAlertException(BadRequestAlertException ex, NativeWebRequest request) {
96
+        return create(ex, request, HeaderUtil.createFailureAlert(ex.getEntityName(), ex.getErrorKey(), ex.getMessage()));
97
+    }
98
+
99
+    @ExceptionHandler
100
+    public ResponseEntity<Problem> handleConcurrencyFailure(ConcurrencyFailureException ex, NativeWebRequest request) {
101
+        Problem problem = Problem.builder()
102
+            .withStatus(Status.CONFLICT)
103
+            .with("message", ErrorConstants.ERR_CONCURRENCY_FAILURE)
104
+            .build();
105
+        return create(ex, problem, request);
106
+    }
107
+}

+ 33
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/FieldErrorVM.java Zobrazit soubor

@@ -0,0 +1,33 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import java.io.Serializable;
4
+
5
+public class FieldErrorVM implements Serializable {
6
+
7
+    private static final long serialVersionUID = 1L;
8
+
9
+    private final String objectName;
10
+
11
+    private final String field;
12
+
13
+    private final String message;
14
+
15
+    public FieldErrorVM(String dto, String field, String message) {
16
+        this.objectName = dto;
17
+        this.field = field;
18
+        this.message = message;
19
+    }
20
+
21
+    public String getObjectName() {
22
+        return objectName;
23
+    }
24
+
25
+    public String getField() {
26
+        return field;
27
+    }
28
+
29
+    public String getMessage() {
30
+        return message;
31
+    }
32
+
33
+}

+ 16
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/InternalServerErrorException.java Zobrazit soubor

@@ -0,0 +1,16 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import org.zalando.problem.AbstractThrowableProblem;
4
+import org.zalando.problem.Status;
5
+
6
+/**
7
+ * Simple exception with a message, that returns an Internal Server Error code.
8
+ */
9
+public class InternalServerErrorException extends AbstractThrowableProblem {
10
+
11
+    private static final long serialVersionUID = 1L;
12
+
13
+    public InternalServerErrorException(String message) {
14
+        super(ErrorConstants.DEFAULT_TYPE, message, Status.INTERNAL_SERVER_ERROR);
15
+    }
16
+}

+ 13
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/InvalidPasswordException.java Zobrazit soubor

@@ -0,0 +1,13 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+import org.zalando.problem.AbstractThrowableProblem;
4
+import org.zalando.problem.Status;
5
+
6
+public class InvalidPasswordException extends AbstractThrowableProblem {
7
+
8
+    private static final long serialVersionUID = 1L;
9
+
10
+    public InvalidPasswordException() {
11
+        super(ErrorConstants.INVALID_PASSWORD_TYPE, "Incorrect password", Status.BAD_REQUEST);
12
+    }
13
+}

+ 10
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/LoginAlreadyUsedException.java Zobrazit soubor

@@ -0,0 +1,10 @@
1
+package rocks.zipcode.io.web.rest.errors;
2
+
3
+public class LoginAlreadyUsedException extends BadRequestAlertException {
4
+
5
+    private static final long serialVersionUID = 1L;
6
+
7
+    public LoginAlreadyUsedException() {
8
+        super(ErrorConstants.LOGIN_ALREADY_USED_TYPE, "Login name already used!", "userManagement", "userexists");
9
+    }
10
+}

+ 6
- 0
src/main/java/rocks/zipcode/io/web/rest/errors/package-info.java Zobrazit soubor

@@ -0,0 +1,6 @@
1
+/**
2
+ * Specific errors used with Zalando's "problem-spring-web" library.
3
+ *
4
+ * More information on https://github.com/zalando/problem-spring-web
5
+ */
6
+package rocks.zipcode.io.web.rest.errors;

+ 4
- 0
src/main/java/rocks/zipcode/io/web/rest/package-info.java Zobrazit soubor

@@ -0,0 +1,4 @@
1
+/**
2
+ * Spring MVC REST controllers.
3
+ */
4
+package rocks.zipcode.io.web.rest;

+ 45
- 0
src/main/java/rocks/zipcode/io/web/rest/util/HeaderUtil.java Zobrazit soubor

@@ -0,0 +1,45 @@
1
+package rocks.zipcode.io.web.rest.util;
2
+
3
+import org.slf4j.Logger;
4
+import org.slf4j.LoggerFactory;
5
+import org.springframework.http.HttpHeaders;
6
+
7
+/**
8
+ * Utility class for HTTP headers creation.
9
+ */
10
+public final class HeaderUtil {
11
+
12
+    private static final Logger log = LoggerFactory.getLogger(HeaderUtil.class);
13
+
14
+    private static final String APPLICATION_NAME = "zipConnectApp";
15
+
16
+    private HeaderUtil() {
17
+    }
18
+
19
+    public static HttpHeaders createAlert(String message, String param) {
20
+        HttpHeaders headers = new HttpHeaders();
21
+        headers.add("X-" + APPLICATION_NAME + "-alert", message);
22
+        headers.add("X-" + APPLICATION_NAME + "-params", param);
23
+        return headers;
24
+    }
25
+
26
+    public static HttpHeaders createEntityCreationAlert(String entityName, String param) {
27
+        return createAlert(APPLICATION_NAME + "." + entityName + ".created", param);
28
+    }
29
+
30
+    public static HttpHeaders createEntityUpdateAlert(String entityName, String param) {
31
+        return createAlert(APPLICATION_NAME + "." + entityName + ".updated", param);
32
+    }
33
+
34
+    public static HttpHeaders createEntityDeletionAlert(String entityName, String param) {
35
+        return createAlert(APPLICATION_NAME + "." + entityName + ".deleted", param);
36
+    }
37
+
38
+    public static HttpHeaders createFailureAlert(String entityName, String errorKey, String defaultMessage) {
39
+        log.error("Entity processing failed, {}", defaultMessage);
40
+        HttpHeaders headers = new HttpHeaders();
41
+        headers.add("X-" + APPLICATION_NAME + "-error", "error." + errorKey);
42
+        headers.add("X-" + APPLICATION_NAME + "-params", entityName);
43
+        return headers;
44
+    }
45
+}

+ 0
- 0
src/main/java/rocks/zipcode/io/web/rest/util/PaginationUtil.java Zobrazit soubor


Některé soubory nejsou zobrazny, neboť je v této revizi změněno mnoho souborů