Subject | Hash | Author | Date (UTC) |
---|---|---|---|
Initial version of honlap generated by JHipster-6.8.0 | fbabb2905b7786b5e91bb5347b816854e35ac3bb | hd | 2020-03-26 08:59:15 |
File .editorconfig added (mode: 100644) (index 0000000..0439866) | |||
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 | # We recommend you to keep these unchanged | ||
10 | end_of_line = lf | ||
11 | charset = utf-8 | ||
12 | trim_trailing_whitespace = true | ||
13 | insert_final_newline = true | ||
14 | |||
15 | # Change these settings to your own preference | ||
16 | indent_style = space | ||
17 | indent_size = 4 | ||
18 | |||
19 | [*.{ts,tsx,js,jsx,json,css,scss,yml}] | ||
20 | indent_size = 2 | ||
21 | |||
22 | [*.md] | ||
23 | trim_trailing_whitespace = false |
File .eslintignore added (mode: 100644) (index 0000000..c8d1f55) | |||
1 | node_modules/ | ||
2 | src/main/docker/ | ||
3 | src/test/javascript/protractor.conf.js | ||
4 | src/test/javascript/jest.conf.js | ||
5 | webpack/ | ||
6 | target/ | ||
7 | build/ | ||
8 | node/ | ||
9 | postcss.config.js |
File .eslintrc.json added (mode: 100644) (index 0000000..2e22599) | |||
1 | { | ||
2 | "plugins": ["@typescript-eslint/tslint"], | ||
3 | "extends": ["jhipster"], | ||
4 | "parserOptions": { | ||
5 | "project": "./tsconfig.json" | ||
6 | }, | ||
7 | "rules": { | ||
8 | "@typescript-eslint/tslint/config": [ | ||
9 | "error", | ||
10 | { | ||
11 | "lintFile": "./tslint.json" | ||
12 | } | ||
13 | ], | ||
14 | "@typescript-eslint/no-unused-vars": [ | ||
15 | "warn", | ||
16 | { | ||
17 | "vars": "all", | ||
18 | "args": "after-used", | ||
19 | "ignoreRestSiblings": false | ||
20 | } | ||
21 | ], | ||
22 | "@typescript-eslint/no-non-null-assertion": "off" | ||
23 | } | ||
24 | } |
File .gitattributes added (mode: 100644) (index 0000000..ca61722) | |||
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 | *.cmd text eol=crlf | ||
12 | *.ps1 text eol=crlf | ||
13 | *.coffee text | ||
14 | *.css text | ||
15 | *.cql text | ||
16 | *.df text | ||
17 | *.ejs text | ||
18 | *.html text | ||
19 | *.java text | ||
20 | *.js text | ||
21 | *.json text | ||
22 | *.less text | ||
23 | *.properties text | ||
24 | *.sass text | ||
25 | *.scss text | ||
26 | *.sh text eol=lf | ||
27 | *.sql text | ||
28 | *.txt text | ||
29 | *.ts text | ||
30 | *.xml text | ||
31 | *.yaml text | ||
32 | *.yml text | ||
33 | |||
34 | # Documents | ||
35 | *.doc diff=astextplain | ||
36 | *.DOC diff=astextplain | ||
37 | *.docx diff=astextplain | ||
38 | *.DOCX diff=astextplain | ||
39 | *.dot diff=astextplain | ||
40 | *.DOT diff=astextplain | ||
41 | *.pdf diff=astextplain | ||
42 | *.PDF diff=astextplain | ||
43 | *.rtf diff=astextplain | ||
44 | *.RTF diff=astextplain | ||
45 | *.markdown text | ||
46 | *.md text | ||
47 | *.adoc text | ||
48 | *.textile text | ||
49 | *.mustache text | ||
50 | *.csv text | ||
51 | *.tab text | ||
52 | *.tsv text | ||
53 | *.txt text | ||
54 | AUTHORS text | ||
55 | CHANGELOG text | ||
56 | CHANGES text | ||
57 | CONTRIBUTING text | ||
58 | COPYING text | ||
59 | copyright text | ||
60 | *COPYRIGHT* text | ||
61 | INSTALL text | ||
62 | license text | ||
63 | LICENSE text | ||
64 | NEWS text | ||
65 | readme text | ||
66 | *README* text | ||
67 | TODO text | ||
68 | |||
69 | # Graphics | ||
70 | *.png binary | ||
71 | *.jpg binary | ||
72 | *.jpeg binary | ||
73 | *.gif binary | ||
74 | *.tif binary | ||
75 | *.tiff binary | ||
76 | *.ico binary | ||
77 | # SVG treated as an asset (binary) by default. If you want to treat it as text, | ||
78 | # comment-out the following line and uncomment the line after. | ||
79 | *.svg binary | ||
80 | #*.svg text | ||
81 | *.eps binary | ||
82 | |||
83 | # These files are binary and should be left untouched | ||
84 | # (binary is a macro for -text -diff) | ||
85 | *.class binary | ||
86 | *.jar binary | ||
87 | *.war binary | ||
88 | |||
89 | ## LINTERS | ||
90 | .csslintrc text | ||
91 | .eslintrc text | ||
92 | .jscsrc text | ||
93 | .jshintrc text | ||
94 | .jshintignore text | ||
95 | .stylelintrc text | ||
96 | |||
97 | ## CONFIGS | ||
98 | *.conf text | ||
99 | *.config text | ||
100 | .editorconfig text | ||
101 | .gitattributes text | ||
102 | .gitconfig text | ||
103 | .gitignore text | ||
104 | .htaccess text | ||
105 | *.npmignore text | ||
106 | |||
107 | ## HEROKU | ||
108 | Procfile text | ||
109 | .slugignore text | ||
110 | |||
111 | ## AUDIO | ||
112 | *.kar binary | ||
113 | *.m4a binary | ||
114 | *.mid binary | ||
115 | *.midi binary | ||
116 | *.mp3 binary | ||
117 | *.ogg binary | ||
118 | *.ra binary | ||
119 | |||
120 | ## VIDEO | ||
121 | *.3gpp binary | ||
122 | *.3gp binary | ||
123 | *.as binary | ||
124 | *.asf binary | ||
125 | *.asx binary | ||
126 | *.fla binary | ||
127 | *.flv binary | ||
128 | *.m4v binary | ||
129 | *.mng binary | ||
130 | *.mov binary | ||
131 | *.mp4 binary | ||
132 | *.mpeg binary | ||
133 | *.mpg binary | ||
134 | *.swc binary | ||
135 | *.swf binary | ||
136 | *.webm binary | ||
137 | |||
138 | ## ARCHIVES | ||
139 | *.7z binary | ||
140 | *.gz binary | ||
141 | *.rar binary | ||
142 | *.tar binary | ||
143 | *.zip binary | ||
144 | |||
145 | ## FONTS | ||
146 | *.ttf binary | ||
147 | *.eot binary | ||
148 | *.otf binary | ||
149 | *.woff binary | ||
150 | *.woff2 binary |
File .gitignore added (mode: 100644) (index 0000000..3bf145e) | |||
1 | ###################### | ||
2 | # Project Specific | ||
3 | ###################### | ||
4 | /src/main/webapp/content/css/main.css | ||
5 | /target/classes/static/** | ||
6 | /src/test/javascript/coverage/ | ||
7 | |||
8 | ###################### | ||
9 | # Node | ||
10 | ###################### | ||
11 | /node/ | ||
12 | node_tmp/ | ||
13 | node_modules/ | ||
14 | npm-debug.log.* | ||
15 | /.awcache/* | ||
16 | /.cache-loader/* | ||
17 | |||
18 | ###################### | ||
19 | # SASS | ||
20 | ###################### | ||
21 | .sass-cache/ | ||
22 | |||
23 | ###################### | ||
24 | # Eclipse | ||
25 | ###################### | ||
26 | *.pydevproject | ||
27 | .project | ||
28 | .metadata | ||
29 | tmp/ | ||
30 | tmp/**/* | ||
31 | *.tmp | ||
32 | *.bak | ||
33 | *.swp | ||
34 | *~.nib | ||
35 | local.properties | ||
36 | .classpath | ||
37 | .settings/ | ||
38 | .loadpath | ||
39 | .factorypath | ||
40 | /src/main/resources/rebel.xml | ||
41 | |||
42 | # External tool builders | ||
43 | .externalToolBuilders/** | ||
44 | |||
45 | # Locally stored "Eclipse launch configurations" | ||
46 | *.launch | ||
47 | |||
48 | # CDT-specific | ||
49 | .cproject | ||
50 | |||
51 | # PDT-specific | ||
52 | .buildpath | ||
53 | |||
54 | # STS-specific | ||
55 | /.sts4-cache/* | ||
56 | ###################### | ||
57 | # Intellij | ||
58 | ###################### | ||
59 | .idea/ | ||
60 | *.iml | ||
61 | *.iws | ||
62 | *.ipr | ||
63 | *.ids | ||
64 | *.orig | ||
65 | classes/ | ||
66 | out/ | ||
67 | |||
68 | ###################### | ||
69 | # Visual Studio Code | ||
70 | ###################### | ||
71 | .vscode/ | ||
72 | |||
73 | ###################### | ||
74 | # Maven | ||
75 | ###################### | ||
76 | /log/ | ||
77 | /target/ | ||
78 | |||
79 | ###################### | ||
80 | # Gradle | ||
81 | ###################### | ||
82 | .gradle/ | ||
83 | /build/ | ||
84 | |||
85 | ###################### | ||
86 | # Package Files | ||
87 | ###################### | ||
88 | *.jar | ||
89 | *.war | ||
90 | *.ear | ||
91 | *.db | ||
92 | |||
93 | ###################### | ||
94 | # Windows | ||
95 | ###################### | ||
96 | # Windows image file caches | ||
97 | Thumbs.db | ||
98 | |||
99 | # Folder config file | ||
100 | Desktop.ini | ||
101 | |||
102 | ###################### | ||
103 | # Mac OSX | ||
104 | ###################### | ||
105 | .DS_Store | ||
106 | .svn | ||
107 | |||
108 | # Thumbnails | ||
109 | ._* | ||
110 | |||
111 | # Files that might appear on external disk | ||
112 | .Spotlight-V100 | ||
113 | .Trashes | ||
114 | |||
115 | ###################### | ||
116 | # Directories | ||
117 | ###################### | ||
118 | /bin/ | ||
119 | /deploy/ | ||
120 | |||
121 | ###################### | ||
122 | # Logs | ||
123 | ###################### | ||
124 | *.log* | ||
125 | |||
126 | ###################### | ||
127 | # Others | ||
128 | ###################### | ||
129 | *.class | ||
130 | *.*~ | ||
131 | *~ | ||
132 | .merge_file* | ||
133 | |||
134 | ###################### | ||
135 | # Gradle Wrapper | ||
136 | ###################### | ||
137 | !gradle/wrapper/gradle-wrapper.jar | ||
138 | |||
139 | ###################### | ||
140 | # Maven Wrapper | ||
141 | ###################### | ||
142 | !.mvn/wrapper/maven-wrapper.jar | ||
143 | |||
144 | ###################### | ||
145 | # ESLint | ||
146 | ###################### | ||
147 | .eslintcache |
File .huskyrc added (mode: 100644) (index 0000000..4d077c8) | |||
1 | { | ||
2 | "hooks": { | ||
3 | "pre-commit": "lint-staged" | ||
4 | } | ||
5 | } |
File .jhipster/PieceOfNews.json added (mode: 100644) (index 0000000..620a6da) | |||
1 | { | ||
2 | "name": "PieceOfNews", | ||
3 | "fields": [ | ||
4 | { | ||
5 | "fieldName": "appId", | ||
6 | "fieldType": "Integer", | ||
7 | "fieldValidateRules": [ | ||
8 | "required" | ||
9 | ] | ||
10 | }, | ||
11 | { | ||
12 | "fieldName": "newsDate", | ||
13 | "fieldType": "Instant", | ||
14 | "fieldValidateRules": [ | ||
15 | "required" | ||
16 | ] | ||
17 | }, | ||
18 | { | ||
19 | "fieldName": "headline", | ||
20 | "fieldType": "String", | ||
21 | "fieldValidateRules": [ | ||
22 | "required", | ||
23 | "maxlength" | ||
24 | ], | ||
25 | "fieldValidateRulesMaxlength": "300" | ||
26 | }, | ||
27 | { | ||
28 | "fieldName": "content", | ||
29 | "fieldType": "String", | ||
30 | "fieldValidateRules": [ | ||
31 | "required", | ||
32 | "maxlength" | ||
33 | ], | ||
34 | "fieldValidateRulesMaxlength": "600" | ||
35 | }, | ||
36 | { | ||
37 | "fieldName": "link", | ||
38 | "fieldType": "String", | ||
39 | "fieldValidateRules": [ | ||
40 | "required", | ||
41 | "maxlength" | ||
42 | ], | ||
43 | "fieldValidateRulesMaxlength": "600" | ||
44 | }, | ||
45 | { | ||
46 | "fieldName": "publishDate", | ||
47 | "fieldType": "Instant" | ||
48 | }, | ||
49 | { | ||
50 | "fieldName": "createdBy", | ||
51 | "fieldType": "String" | ||
52 | }, | ||
53 | { | ||
54 | "fieldName": "createdDate", | ||
55 | "fieldType": "Instant" | ||
56 | }, | ||
57 | { | ||
58 | "fieldName": "lastModifiedBy", | ||
59 | "fieldType": "String" | ||
60 | }, | ||
61 | { | ||
62 | "fieldName": "lastModifiedDate", | ||
63 | "fieldType": "Instant" | ||
64 | } | ||
65 | ], | ||
66 | "relationships": [], | ||
67 | "changelogDate": "20200326085000", | ||
68 | "javadoc": "Hírek", | ||
69 | "entityTableName": "piece_of_news", | ||
70 | "dto": "no", | ||
71 | "pagination": "pagination", | ||
72 | "service": "no", | ||
73 | "jpaMetamodelFiltering": false, | ||
74 | "fluentMethods": true, | ||
75 | "readOnly": false, | ||
76 | "embedded": false, | ||
77 | "clientRootFolder": "", | ||
78 | "applications": [ | ||
79 | "honlap" | ||
80 | ] | ||
81 | } |
File .lintstagedrc.js added (mode: 100644) (index 0000000..58dedb0) | |||
1 | module.exports = { | ||
2 | '{,src/**/}*.{md,json,ts,css,scss,yml}': ['prettier --write', 'git add'] | ||
3 | }; |
File .mvn/wrapper/MavenWrapperDownloader.java added (mode: 100644) (index 0000000..b901097) | |||
1 | /* | ||
2 | * Copyright 2007-present the original author or authors. | ||
3 | * | ||
4 | * Licensed under the Apache License, Version 2.0 (the "License"); | ||
5 | * you may not use this file except in compliance with the License. | ||
6 | * You may obtain a copy of the License at | ||
7 | * | ||
8 | * http://www.apache.org/licenses/LICENSE-2.0 | ||
9 | * | ||
10 | * Unless required by applicable law or agreed to in writing, software | ||
11 | * distributed under the License is distributed on an "AS IS" BASIS, | ||
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
13 | * See the License for the specific language governing permissions and | ||
14 | * limitations under the License. | ||
15 | */ | ||
16 | import java.net.*; | ||
17 | import java.io.*; | ||
18 | import java.nio.channels.*; | ||
19 | import java.util.Properties; | ||
20 | |||
21 | public class MavenWrapperDownloader { | ||
22 | |||
23 | private static final String WRAPPER_VERSION = "0.5.6"; | ||
24 | /** | ||
25 | * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided. | ||
26 | */ | ||
27 | private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/" | ||
28 | + WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar"; | ||
29 | |||
30 | /** | ||
31 | * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to | ||
32 | * use instead of the default one. | ||
33 | */ | ||
34 | private static final String MAVEN_WRAPPER_PROPERTIES_PATH = | ||
35 | ".mvn/wrapper/maven-wrapper.properties"; | ||
36 | |||
37 | /** | ||
38 | * Path where the maven-wrapper.jar will be saved to. | ||
39 | */ | ||
40 | private static final String MAVEN_WRAPPER_JAR_PATH = | ||
41 | ".mvn/wrapper/maven-wrapper.jar"; | ||
42 | |||
43 | /** | ||
44 | * Name of the property which should be used to override the default download url for the wrapper. | ||
45 | */ | ||
46 | private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl"; | ||
47 | |||
48 | public static void main(String args[]) { | ||
49 | System.out.println("- Downloader started"); | ||
50 | File baseDirectory = new File(args[0]); | ||
51 | System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath()); | ||
52 | |||
53 | // If the maven-wrapper.properties exists, read it and check if it contains a custom | ||
54 | // wrapperUrl parameter. | ||
55 | File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH); | ||
56 | String url = DEFAULT_DOWNLOAD_URL; | ||
57 | if(mavenWrapperPropertyFile.exists()) { | ||
58 | FileInputStream mavenWrapperPropertyFileInputStream = null; | ||
59 | try { | ||
60 | mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile); | ||
61 | Properties mavenWrapperProperties = new Properties(); | ||
62 | mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream); | ||
63 | url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url); | ||
64 | } catch (IOException e) { | ||
65 | System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'"); | ||
66 | } finally { | ||
67 | try { | ||
68 | if(mavenWrapperPropertyFileInputStream != null) { | ||
69 | mavenWrapperPropertyFileInputStream.close(); | ||
70 | } | ||
71 | } catch (IOException e) { | ||
72 | // Ignore ... | ||
73 | } | ||
74 | } | ||
75 | } | ||
76 | System.out.println("- Downloading from: " + url); | ||
77 | |||
78 | File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH); | ||
79 | if(!outputFile.getParentFile().exists()) { | ||
80 | if(!outputFile.getParentFile().mkdirs()) { | ||
81 | System.out.println( | ||
82 | "- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'"); | ||
83 | } | ||
84 | } | ||
85 | System.out.println("- Downloading to: " + outputFile.getAbsolutePath()); | ||
86 | try { | ||
87 | downloadFileFromURL(url, outputFile); | ||
88 | System.out.println("Done"); | ||
89 | System.exit(0); | ||
90 | } catch (Throwable e) { | ||
91 | System.out.println("- Error downloading"); | ||
92 | e.printStackTrace(); | ||
93 | System.exit(1); | ||
94 | } | ||
95 | } | ||
96 | |||
97 | private static void downloadFileFromURL(String urlString, File destination) throws Exception { | ||
98 | if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) { | ||
99 | String username = System.getenv("MVNW_USERNAME"); | ||
100 | char[] password = System.getenv("MVNW_PASSWORD").toCharArray(); | ||
101 | Authenticator.setDefault(new Authenticator() { | ||
102 | @Override | ||
103 | protected PasswordAuthentication getPasswordAuthentication() { | ||
104 | return new PasswordAuthentication(username, password); | ||
105 | } | ||
106 | }); | ||
107 | } | ||
108 | URL website = new URL(urlString); | ||
109 | ReadableByteChannel rbc; | ||
110 | rbc = Channels.newChannel(website.openStream()); | ||
111 | FileOutputStream fos = new FileOutputStream(destination); | ||
112 | fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); | ||
113 | fos.close(); | ||
114 | rbc.close(); | ||
115 | } | ||
116 | |||
117 | } |
File .mvn/wrapper/maven-wrapper.jar added (mode: 100644) (index 0000000..2cc7d4a) |
File .mvn/wrapper/maven-wrapper.properties added (mode: 100644) (index 0000000..642d572) | |||
1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip | ||
2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar |
File .prettierignore added (mode: 100644) (index 0000000..91b1ba3) | |||
1 | node_modules | ||
2 | target | ||
3 | package-lock.json | ||
4 | .git |
File .prettierrc added (mode: 100644) (index 0000000..f9b9911) | |||
1 | # Prettier configuration | ||
2 | |||
3 | printWidth: 140 | ||
4 | singleQuote: true | ||
5 | tabWidth: 2 | ||
6 | useTabs: false | ||
7 | |||
8 | # js and ts rules: | ||
9 | arrowParens: avoid | ||
10 | |||
11 | # jsx and tsx rules: | ||
12 | jsxBracketSameLine: false | ||
13 | |||
14 | # java rules: | ||
15 | overrides: | ||
16 | - files: "*.java" | ||
17 | options: | ||
18 | tabWidth: 4 |
File .yo-rc.json added (mode: 100644) (index 0000000..8e18ebf) | |||
1 | { | ||
2 | "generator-jhipster": { | ||
3 | "authenticationType": "jwt", | ||
4 | "cacheProvider": "ehcache", | ||
5 | "clientFramework": "angularX", | ||
6 | "serverPort": "8080", | ||
7 | "serviceDiscoveryType": false, | ||
8 | "skipUserManagement": false, | ||
9 | "baseName": "honlap", | ||
10 | "buildTool": "maven", | ||
11 | "databaseType": "sql", | ||
12 | "devDatabaseType": "h2Disk", | ||
13 | "enableHibernateCache": true, | ||
14 | "enableSwaggerCodegen": false, | ||
15 | "enableTranslation": true, | ||
16 | "jhiPrefix": "auth", | ||
17 | "languages": ["hu", "en"], | ||
18 | "messageBroker": false, | ||
19 | "nativeLanguage": "hu", | ||
20 | "prodDatabaseType": "postgresql", | ||
21 | "searchEngine": false, | ||
22 | "skipClient": false, | ||
23 | "testFrameworks": ["protractor", "cucumber"], | ||
24 | "websocket": false, | ||
25 | "packageName": "hu.dns.honlap", | ||
26 | "packageFolder": "hu/dns/honlap", | ||
27 | "applicationType": "monolith", | ||
28 | "jhipsterVersion": "6.8.0", | ||
29 | "creationTimestamp": 1585212540093, | ||
30 | "skipServer": false, | ||
31 | "clientPackageManager": "npm", | ||
32 | "clientTheme": "none", | ||
33 | "clientThemeVariant": "", | ||
34 | "useSass": true, | ||
35 | "jwtSecretKey": "ZmYxOTYwOGZiYTY1OTJiMTQ3MDNhNGJiNTM3ZWMxN2U1ZTVjODdlMDhmZmNkMGRhYTQxY2ZiMGQzM2Q0ZTNmYzc2YjNjMzU5ZmVkZDgzZDc3OTYxZDMzNzdiNzc3MmVkYjA0NDFkOGIxMTI0MjRiNTMzYzRkNzFkMTJiYWE4Y2Y=", | ||
36 | "embeddableLaunchScript": false, | ||
37 | "entitySuffix": "", | ||
38 | "dtoSuffix": "DTO", | ||
39 | "otherModules": [], | ||
40 | "blueprints": [] | ||
41 | }, | ||
42 | "entities": ["PieceOfNews"] | ||
43 | } |
File README.md added (mode: 100644) (index 0000000..c3393ce) | |||
1 | # honlap | ||
2 | |||
3 | This application was generated using JHipster 6.8.0, you can find documentation and help at [https://www.jhipster.tech/documentation-archive/v6.8.0](https://www.jhipster.tech/documentation-archive/v6.8.0). | ||
4 | |||
5 | ## Development | ||
6 | |||
7 | Before you can build this project, you must install and configure the following dependencies on your machine: | ||
8 | |||
9 | 1. [Node.js][]: We use Node to run a development web server and build the project. | ||
10 | Depending on your system, you can install Node either from source or as a pre-packaged bundle. | ||
11 | |||
12 | After installing Node, you should be able to run the following command to install development tools. | ||
13 | You will only need to run this command when dependencies change in [package.json](package.json). | ||
14 | |||
15 | npm install | ||
16 | |||
17 | We use npm scripts and [Webpack][] as our build system. | ||
18 | |||
19 | Run the following commands in two separate terminals to create a blissful development experience where your browser | ||
20 | auto-refreshes when files change on your hard drive. | ||
21 | |||
22 | ./mvnw | ||
23 | npm start | ||
24 | |||
25 | Npm is also used to manage CSS and JavaScript dependencies used in this application. You can upgrade dependencies by | ||
26 | specifying a newer version in [package.json](package.json). You can also run `npm update` and `npm install` to manage dependencies. | ||
27 | Add the `help` flag on any command to see how you can use it. For example, `npm help update`. | ||
28 | |||
29 | The `npm run` command will list all of the scripts available to run for this project. | ||
30 | |||
31 | ### PWA Support | ||
32 | |||
33 | JHipster ships with PWA (Progressive Web App) support, and it's turned off by default. One of the main components of a PWA is a service worker. | ||
34 | |||
35 | The service worker initialization code is commented out by default. To enable it, uncomment the following code in `src/main/webapp/index.html`: | ||
36 | |||
37 | ```html | ||
38 | <script> | ||
39 | if ('serviceWorker' in navigator) { | ||
40 | navigator.serviceWorker.register('./service-worker.js').then(function() { | ||
41 | console.log('Service Worker Registered'); | ||
42 | }); | ||
43 | } | ||
44 | </script> | ||
45 | ``` | ||
46 | |||
47 | Note: [Workbox](https://developers.google.com/web/tools/workbox/) powers JHipster's service worker. It dynamically generates the `service-worker.js` file. | ||
48 | |||
49 | ### Managing dependencies | ||
50 | |||
51 | For example, to add [Leaflet][] library as a runtime dependency of your application, you would run following command: | ||
52 | |||
53 | npm install --save --save-exact leaflet | ||
54 | |||
55 | To benefit from TypeScript type definitions from [DefinitelyTyped][] repository in development, you would run following command: | ||
56 | |||
57 | npm install --save-dev --save-exact @types/leaflet | ||
58 | |||
59 | Then you would import the JS and CSS files specified in library's installation instructions so that [Webpack][] knows about them: | ||
60 | Edit [src/main/webapp/app/vendor.ts](src/main/webapp/app/vendor.ts) file: | ||
61 | |||
62 | ``` | ||
63 | import 'leaflet/dist/leaflet.js'; | ||
64 | ``` | ||
65 | |||
66 | Edit [src/main/webapp/content/scss/vendor.scss](src/main/webapp/content/scss/vendor.scss) file: | ||
67 | |||
68 | ``` | ||
69 | @import '~leaflet/dist/leaflet.css'; | ||
70 | ``` | ||
71 | |||
72 | Note: There are still a few other things remaining to do for Leaflet that we won't detail here. | ||
73 | |||
74 | For further instructions on how to develop with JHipster, have a look at [Using JHipster in development][]. | ||
75 | |||
76 | ### Using Angular CLI | ||
77 | |||
78 | You can also use [Angular CLI][] to generate some custom client code. | ||
79 | |||
80 | For example, the following command: | ||
81 | |||
82 | ng generate component my-component | ||
83 | |||
84 | will generate few files: | ||
85 | |||
86 | create src/main/webapp/app/my-component/my-component.component.html | ||
87 | create src/main/webapp/app/my-component/my-component.component.ts | ||
88 | update src/main/webapp/app/app.module.ts | ||
89 | |||
90 | ## Building for production | ||
91 | |||
92 | ### Packaging as jar | ||
93 | |||
94 | To build the final jar and optimize the honlap application for production, run: | ||
95 | |||
96 | ./mvnw -Pprod clean verify | ||
97 | |||
98 | This will concatenate and minify the client CSS and JavaScript files. It will also modify `index.html` so it references these new files. | ||
99 | To ensure everything worked, run: | ||
100 | |||
101 | java -jar target/*.jar | ||
102 | |||
103 | Then navigate to [http://localhost:8080](http://localhost:8080) in your browser. | ||
104 | |||
105 | Refer to [Using JHipster in production][] for more details. | ||
106 | |||
107 | ### Packaging as war | ||
108 | |||
109 | To package your application as a war in order to deploy it to an application server, run: | ||
110 | |||
111 | ./mvnw -Pprod,war clean verify | ||
112 | |||
113 | ## Testing | ||
114 | |||
115 | To launch your application's tests, run: | ||
116 | |||
117 | ./mvnw verify | ||
118 | |||
119 | ### Client tests | ||
120 | |||
121 | Unit tests are run by [Jest][] and written with [Jasmine][]. They're located in [src/test/javascript/](src/test/javascript/) and can be run with: | ||
122 | |||
123 | npm test | ||
124 | |||
125 | For more information, refer to the [Running tests page][]. | ||
126 | |||
127 | ### Code quality | ||
128 | |||
129 | Sonar is used to analyse code quality. You can start a local Sonar server (accessible on http://localhost:9001) with: | ||
130 | |||
131 | ``` | ||
132 | docker-compose -f src/main/docker/sonar.yml up -d | ||
133 | ``` | ||
134 | |||
135 | You can run a Sonar analysis with using the [sonar-scanner](https://docs.sonarqube.org/display/SCAN/Analyzing+with+SonarQube+Scanner) or by using the maven plugin. | ||
136 | |||
137 | Then, run a Sonar analysis: | ||
138 | |||
139 | ``` | ||
140 | ./mvnw -Pprod clean verify sonar:sonar | ||
141 | ``` | ||
142 | |||
143 | If you need to re-run the Sonar phase, please be sure to specify at least the `initialize` phase since Sonar properties are loaded from the sonar-project.properties file. | ||
144 | |||
145 | ``` | ||
146 | ./mvnw initialize sonar:sonar | ||
147 | ``` | ||
148 | |||
149 | or | ||
150 | |||
151 | For more information, refer to the [Code quality page][]. | ||
152 | |||
153 | ## Using Docker to simplify development (optional) | ||
154 | |||
155 | 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. | ||
156 | |||
157 | For example, to start a postgresql database in a docker container, run: | ||
158 | |||
159 | docker-compose -f src/main/docker/postgresql.yml up -d | ||
160 | |||
161 | To stop it and remove the container, run: | ||
162 | |||
163 | docker-compose -f src/main/docker/postgresql.yml down | ||
164 | |||
165 | You can also fully dockerize your application and all the services that it depends on. | ||
166 | To achieve this, first build a docker image of your app by running: | ||
167 | |||
168 | ./mvnw -Pprod verify jib:dockerBuild | ||
169 | |||
170 | Then run: | ||
171 | |||
172 | docker-compose -f src/main/docker/app.yml up -d | ||
173 | |||
174 | 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. | ||
175 | |||
176 | ## Continuous Integration (optional) | ||
177 | |||
178 | 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. | ||
179 | |||
180 | [jhipster homepage and latest documentation]: https://www.jhipster.tech | ||
181 | [jhipster 6.8.0 archive]: https://www.jhipster.tech/documentation-archive/v6.8.0 | ||
182 | [using jhipster in development]: https://www.jhipster.tech/documentation-archive/v6.8.0/development/ | ||
183 | [using docker and docker-compose]: https://www.jhipster.tech/documentation-archive/v6.8.0/docker-compose | ||
184 | [using jhipster in production]: https://www.jhipster.tech/documentation-archive/v6.8.0/production/ | ||
185 | [running tests page]: https://www.jhipster.tech/documentation-archive/v6.8.0/running-tests/ | ||
186 | [code quality page]: https://www.jhipster.tech/documentation-archive/v6.8.0/code-quality/ | ||
187 | [setting up continuous integration]: https://www.jhipster.tech/documentation-archive/v6.8.0/setting-up-ci/ | ||
188 | [node.js]: https://nodejs.org/ | ||
189 | [yarn]: https://yarnpkg.org/ | ||
190 | [webpack]: https://webpack.github.io/ | ||
191 | [angular cli]: https://cli.angular.io/ | ||
192 | [browsersync]: https://www.browsersync.io/ | ||
193 | [jest]: https://facebook.github.io/jest/ | ||
194 | [jasmine]: https://jasmine.github.io/2.0/introduction.html | ||
195 | [protractor]: https://angular.github.io/protractor/ | ||
196 | [leaflet]: https://leafletjs.com/ | ||
197 | [definitelytyped]: https://definitelytyped.org/ |
File angular.json added (mode: 100644) (index 0000000..ebe0f65) | |||
1 | { | ||
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json", | ||
3 | "version": 1, | ||
4 | "newProjectRoot": "projects", | ||
5 | "projects": { | ||
6 | "honlap": { | ||
7 | "root": "", | ||
8 | "sourceRoot": "src/main/webapp", | ||
9 | "projectType": "application", | ||
10 | "schematics": { | ||
11 | "@schematics/angular:component": { | ||
12 | "skipTests": true, | ||
13 | "style": "scss" | ||
14 | }, | ||
15 | "@schematics/angular:directive": { | ||
16 | "skipTests": true | ||
17 | }, | ||
18 | "@schematics/angular:guard": { | ||
19 | "skipTests": true | ||
20 | }, | ||
21 | "@schematics/angular:pipe": { | ||
22 | "skipTests": true | ||
23 | }, | ||
24 | "@schematics/angular:service": { | ||
25 | "skipTests": true | ||
26 | } | ||
27 | }, | ||
28 | "prefix": "auth", | ||
29 | "architect": {} | ||
30 | } | ||
31 | }, | ||
32 | "defaultProject": "honlap", | ||
33 | "cli": { | ||
34 | "packageManager": "npm" | ||
35 | } | ||
36 | } |
File checkstyle.xml added (mode: 100644) (index 0000000..6e3dbaf) | |||
1 | <?xml version="1.0"?> | ||
2 | <!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.3//EN" | ||
3 | "https://www.puppycrawl.com/dtds/configuration_1_3.dtd"> | ||
4 | <module name="Checker"> | ||
5 | |||
6 | <!-- Configure checker to use UTF-8 encoding --> | ||
7 | <property name="charset" value="UTF-8"/> | ||
8 | <!-- Configure checker to run on files with these extensions --> | ||
9 | <property name="fileExtensions" value=""/> | ||
10 | <!-- For detailed checkstyle configuration, see https://github.com/spring-io/nohttp/tree/master/nohttp-checkstyle --> | ||
11 | <module name="io.spring.nohttp.checkstyle.check.NoHttpCheck"> | ||
12 | <property name="whitelist" value="http://maven.apache.org/POM/4.0.0 | ||
13 | http://www.w3.org/2001/XMLSchema-instance http://maven.apache.org/maven-v4_0_0.xsd"/> | ||
14 | </module> | ||
15 | <!-- Allow suppression with comments | ||
16 | // CHECKSTYLE:OFF | ||
17 | ... ignored content ... | ||
18 | // CHECKSTYLE:ON | ||
19 | --> | ||
20 | <module name="SuppressWithPlainTextCommentFilter"/> | ||
21 | </module> |
File jdl/News_1585209808.jdl added (mode: 100644) (index 0000000..150e5c5) | |||
1 | /** | ||
2 | * The application configuration. | ||
3 | */ | ||
4 | application { | ||
5 | config { | ||
6 | baseName honlap, | ||
7 | jhiPrefix auth, | ||
8 | packageName hu.dns.honlap, | ||
9 | applicationType monolith, | ||
10 | buildTool maven, | ||
11 | prodDatabaseType postgresql, | ||
12 | testFrameworks [protractor,cucumber] | ||
13 | nativeLanguage hu, | ||
14 | languages [hu, en] | ||
15 | } | ||
16 | entities * | ||
17 | } | ||
18 | |||
19 | |||
20 | /** | ||
21 | * Hírek | ||
22 | */ | ||
23 | entity PieceOfNews { | ||
24 | appId Integer required, | ||
25 | newsDate Instant required, | ||
26 | headline String required maxlength(300), | ||
27 | content String required maxlength(600), | ||
28 | link String required maxlength(600), | ||
29 | publishDate Instant, | ||
30 | createdBy String, | ||
31 | createdDate Instant, | ||
32 | lastModifiedBy String, | ||
33 | lastModifiedDate Instant | ||
34 | } | ||
35 | |||
36 | |||
37 | paginate PieceOfNews with pagination |
File mvnw added (mode: 100644) (index 0000000..41c0f0c) | |||
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 | # Maven 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 | fi | ||
118 | |||
119 | if [ -z "$JAVA_HOME" ]; then | ||
120 | javaExecutable="`which javac`" | ||
121 | if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then | ||
122 | # readlink(1) is not available as standard on Solaris 10. | ||
123 | readLink=`which readlink` | ||
124 | if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then | ||
125 | if $darwin ; then | ||
126 | javaHome="`dirname \"$javaExecutable\"`" | ||
127 | javaExecutable="`cd \"$javaHome\" && pwd -P`/javac" | ||
128 | else | ||
129 | javaExecutable="`readlink -f \"$javaExecutable\"`" | ||
130 | fi | ||
131 | javaHome="`dirname \"$javaExecutable\"`" | ||
132 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` | ||
133 | JAVA_HOME="$javaHome" | ||
134 | export JAVA_HOME | ||
135 | fi | ||
136 | fi | ||
137 | fi | ||
138 | |||
139 | if [ -z "$JAVACMD" ] ; then | ||
140 | if [ -n "$JAVA_HOME" ] ; then | ||
141 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then | ||
142 | # IBM's JDK on AIX uses strange locations for the executables | ||
143 | JAVACMD="$JAVA_HOME/jre/sh/java" | ||
144 | else | ||
145 | JAVACMD="$JAVA_HOME/bin/java" | ||
146 | fi | ||
147 | else | ||
148 | JAVACMD="`which java`" | ||
149 | fi | ||
150 | fi | ||
151 | |||
152 | if [ ! -x "$JAVACMD" ] ; then | ||
153 | echo "Error: JAVA_HOME is not defined correctly." >&2 | ||
154 | echo " We cannot execute $JAVACMD" >&2 | ||
155 | exit 1 | ||
156 | fi | ||
157 | |||
158 | if [ -z "$JAVA_HOME" ] ; then | ||
159 | echo "Warning: JAVA_HOME environment variable is not set." | ||
160 | fi | ||
161 | |||
162 | CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher | ||
163 | |||
164 | # traverses directory structure from process work directory to filesystem root | ||
165 | # first directory with .mvn subdirectory is considered project base directory | ||
166 | find_maven_basedir() { | ||
167 | |||
168 | if [ -z "$1" ] | ||
169 | then | ||
170 | echo "Path not specified to find_maven_basedir" | ||
171 | return 1 | ||
172 | fi | ||
173 | |||
174 | basedir="$1" | ||
175 | wdir="$1" | ||
176 | while [ "$wdir" != '/' ] ; do | ||
177 | if [ -d "$wdir"/.mvn ] ; then | ||
178 | basedir=$wdir | ||
179 | break | ||
180 | fi | ||
181 | # workaround for JBEAP-8937 (on Solaris 10/Sparc) | ||
182 | if [ -d "${wdir}" ]; then | ||
183 | wdir=`cd "$wdir/.."; pwd` | ||
184 | fi | ||
185 | # end of workaround | ||
186 | done | ||
187 | echo "${basedir}" | ||
188 | } | ||
189 | |||
190 | # concatenates all lines of a file | ||
191 | concat_lines() { | ||
192 | if [ -f "$1" ]; then | ||
193 | echo "$(tr -s '\n' ' ' < "$1")" | ||
194 | fi | ||
195 | } | ||
196 | |||
197 | BASE_DIR=`find_maven_basedir "$(pwd)"` | ||
198 | if [ -z "$BASE_DIR" ]; then | ||
199 | exit 1; | ||
200 | fi | ||
201 | |||
202 | ########################################################################################## | ||
203 | # Extension to allow automatically downloading the maven-wrapper.jar from Maven-central | ||
204 | # This allows using the maven wrapper in projects that prohibit checking in binary data. | ||
205 | ########################################################################################## | ||
206 | if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then | ||
207 | if [ "$MVNW_VERBOSE" = true ]; then | ||
208 | echo "Found .mvn/wrapper/maven-wrapper.jar" | ||
209 | fi | ||
210 | else | ||
211 | if [ "$MVNW_VERBOSE" = true ]; then | ||
212 | echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..." | ||
213 | fi | ||
214 | if [ -n "$MVNW_REPOURL" ]; then | ||
215 | jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" | ||
216 | else | ||
217 | jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" | ||
218 | fi | ||
219 | while IFS="=" read key value; do | ||
220 | case "$key" in (wrapperUrl) jarUrl="$value"; break ;; | ||
221 | esac | ||
222 | done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties" | ||
223 | if [ "$MVNW_VERBOSE" = true ]; then | ||
224 | echo "Downloading from: $jarUrl" | ||
225 | fi | ||
226 | wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" | ||
227 | if $cygwin; then | ||
228 | wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"` | ||
229 | fi | ||
230 | |||
231 | if command -v wget > /dev/null; then | ||
232 | if [ "$MVNW_VERBOSE" = true ]; then | ||
233 | echo "Found wget ... using wget" | ||
234 | fi | ||
235 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then | ||
236 | wget "$jarUrl" -O "$wrapperJarPath" | ||
237 | else | ||
238 | wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" | ||
239 | fi | ||
240 | elif command -v curl > /dev/null; then | ||
241 | if [ "$MVNW_VERBOSE" = true ]; then | ||
242 | echo "Found curl ... using curl" | ||
243 | fi | ||
244 | if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then | ||
245 | curl -o "$wrapperJarPath" "$jarUrl" -f | ||
246 | else | ||
247 | curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f | ||
248 | fi | ||
249 | |||
250 | else | ||
251 | if [ "$MVNW_VERBOSE" = true ]; then | ||
252 | echo "Falling back to using Java to download" | ||
253 | fi | ||
254 | javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java" | ||
255 | # For Cygwin, switch paths to Windows format before running javac | ||
256 | if $cygwin; then | ||
257 | javaClass=`cygpath --path --windows "$javaClass"` | ||
258 | fi | ||
259 | if [ -e "$javaClass" ]; then | ||
260 | if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then | ||
261 | if [ "$MVNW_VERBOSE" = true ]; then | ||
262 | echo " - Compiling MavenWrapperDownloader.java ..." | ||
263 | fi | ||
264 | # Compiling the Java class | ||
265 | ("$JAVA_HOME/bin/javac" "$javaClass") | ||
266 | fi | ||
267 | if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then | ||
268 | # Running the downloader | ||
269 | if [ "$MVNW_VERBOSE" = true ]; then | ||
270 | echo " - Running MavenWrapperDownloader.java ..." | ||
271 | fi | ||
272 | ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR") | ||
273 | fi | ||
274 | fi | ||
275 | fi | ||
276 | fi | ||
277 | ########################################################################################## | ||
278 | # End of extension | ||
279 | ########################################################################################## | ||
280 | |||
281 | export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"} | ||
282 | if [ "$MVNW_VERBOSE" = true ]; then | ||
283 | echo $MAVEN_PROJECTBASEDIR | ||
284 | fi | ||
285 | MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS" | ||
286 | |||
287 | # For Cygwin, switch paths to Windows format before running java | ||
288 | if $cygwin; then | ||
289 | [ -n "$M2_HOME" ] && | ||
290 | M2_HOME=`cygpath --path --windows "$M2_HOME"` | ||
291 | [ -n "$JAVA_HOME" ] && | ||
292 | JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"` | ||
293 | [ -n "$CLASSPATH" ] && | ||
294 | CLASSPATH=`cygpath --path --windows "$CLASSPATH"` | ||
295 | [ -n "$MAVEN_PROJECTBASEDIR" ] && | ||
296 | MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"` | ||
297 | fi | ||
298 | |||
299 | # Provide a "standardized" way to retrieve the CLI args that will | ||
300 | # work with both Windows and non-Windows executions. | ||
301 | MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@" | ||
302 | export MAVEN_CMD_LINE_ARGS | ||
303 | |||
304 | WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain | ||
305 | |||
306 | exec "$JAVACMD" \ | ||
307 | $MAVEN_OPTS \ | ||
308 | -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \ | ||
309 | "-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \ | ||
310 | ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@" |
File mvnw.cmd added (mode: 100644) (index 0000000..8611571) | |||
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 Maven 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 keystroke 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 by 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.5.6/maven-wrapper-0.5.6.jar" | ||
124 | |||
125 | FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO ( | ||
126 | IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B | ||
127 | ) | ||
128 | |||
129 | @REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central | ||
130 | @REM This allows using the maven wrapper in projects that prohibit checking in binary data. | ||
131 | if exist %WRAPPER_JAR% ( | ||
132 | if "%MVNW_VERBOSE%" == "true" ( | ||
133 | echo Found %WRAPPER_JAR% | ||
134 | ) | ||
135 | ) else ( | ||
136 | if not "%MVNW_REPOURL%" == "" ( | ||
137 | SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar" | ||
138 | ) | ||
139 | if "%MVNW_VERBOSE%" == "true" ( | ||
140 | echo Couldn't find %WRAPPER_JAR%, downloading it ... | ||
141 | echo Downloading from: %DOWNLOAD_URL% | ||
142 | ) | ||
143 | |||
144 | powershell -Command "&{"^ | ||
145 | "$webclient = new-object System.Net.WebClient;"^ | ||
146 | "if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^ | ||
147 | "$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^ | ||
148 | "}"^ | ||
149 | "[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^ | ||
150 | "}" | ||
151 | if "%MVNW_VERBOSE%" == "true" ( | ||
152 | echo Finished downloading %WRAPPER_JAR% | ||
153 | ) | ||
154 | ) | ||
155 | @REM End of extension | ||
156 | |||
157 | @REM Provide a "standardized" way to retrieve the CLI args that will | ||
158 | @REM work with both Windows and non-Windows executions. | ||
159 | set MAVEN_CMD_LINE_ARGS=%* | ||
160 | |||
161 | %MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %* | ||
162 | if ERRORLEVEL 1 goto error | ||
163 | goto end | ||
164 | |||
165 | :error | ||
166 | set ERROR_CODE=1 | ||
167 | |||
168 | :end | ||
169 | @endlocal & set ERROR_CODE=%ERROR_CODE% | ||
170 | |||
171 | if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost | ||
172 | @REM check for post script, once with legacy .bat ending and once with .cmd ending | ||
173 | if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat" | ||
174 | if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd" | ||
175 | :skipRcPost | ||
176 | |||
177 | @REM pause the script if MAVEN_BATCH_PAUSE is set to 'on' | ||
178 | if "%MAVEN_BATCH_PAUSE%" == "on" pause | ||
179 | |||
180 | if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE% | ||
181 | |||
182 | exit /B %ERROR_CODE% |
The diff for file package-lock.json is too big (21585 changes) and cannot be shown. |
File package.json added (mode: 100644) (index 0000000..32de50b) | |||
1 | { | ||
2 | "name": "honlap", | ||
3 | "version": "0.0.1-SNAPSHOT", | ||
4 | "description": "Description for honlap", | ||
5 | "private": true, | ||
6 | "license": "UNLICENSED", | ||
7 | "cacheDirectories": [ | ||
8 | "node_modules" | ||
9 | ], | ||
10 | "dependencies": { | ||
11 | "@angular/common": "9.0.4", | ||
12 | "@angular/compiler": "9.0.4", | ||
13 | "@angular/core": "9.0.4", | ||
14 | "@angular/forms": "9.0.4", | ||
15 | "@angular/localize": "9.0.4", | ||
16 | "@angular/platform-browser": "9.0.4", | ||
17 | "@angular/platform-browser-dynamic": "9.0.4", | ||
18 | "@angular/router": "9.0.4", | ||
19 | "@fortawesome/angular-fontawesome": "0.6.0", | ||
20 | "@fortawesome/fontawesome-svg-core": "1.2.26", | ||
21 | "@fortawesome/free-solid-svg-icons": "5.12.0", | ||
22 | "@ng-bootstrap/ng-bootstrap": "6.0.0", | ||
23 | "@ngx-translate/core": "11.0.1", | ||
24 | "@ngx-translate/http-loader": "4.0.0", | ||
25 | "bootstrap": "4.4.1", | ||
26 | "moment": "2.24.0", | ||
27 | "ng-jhipster": "0.12.0", | ||
28 | "ngx-cookie": "4.0.2", | ||
29 | "ngx-infinite-scroll": "8.0.1", | ||
30 | "ngx-webstorage": "5.0.0", | ||
31 | "rxjs": "6.5.3", | ||
32 | "swagger-ui-dist": "3.24.3", | ||
33 | "tslib": "1.10.0", | ||
34 | "zone.js": "0.10.2" | ||
35 | }, | ||
36 | "devDependencies": { | ||
37 | "@angular/cli": "9.0.4", | ||
38 | "@angular/compiler-cli": "9.0.4", | ||
39 | "@ngtools/webpack": "9.0.4", | ||
40 | "@openapitools/openapi-generator-cli": "1.0.10-4.2.3", | ||
41 | "@types/chai": "4.2.7", | ||
42 | "@types/chai-string": "1.4.2", | ||
43 | "@types/jest": "24.0.23", | ||
44 | "@types/mocha": "5.2.7", | ||
45 | "@types/node": "12.12.17", | ||
46 | "@types/selenium-webdriver": "4.0.5", | ||
47 | "@typescript-eslint/eslint-plugin": "2.11.0", | ||
48 | "@typescript-eslint/eslint-plugin-tslint": "2.11.0", | ||
49 | "@typescript-eslint/parser": "2.11.0", | ||
50 | "autoprefixer": "9.7.3", | ||
51 | "base-href-webpack-plugin": "2.0.0", | ||
52 | "browser-sync": "2.26.7", | ||
53 | "browser-sync-webpack-plugin": "2.2.2", | ||
54 | "chai": "4.2.0", | ||
55 | "chai-as-promised": "7.1.1", | ||
56 | "chai-string": "1.5.0", | ||
57 | "codelyzer": "5.2.0", | ||
58 | "copy-webpack-plugin": "5.1.1", | ||
59 | "css-loader": "3.3.2", | ||
60 | "eslint": "6.7.2", | ||
61 | "eslint-config-jhipster": "0.0.1", | ||
62 | "eslint-config-prettier": "6.7.0", | ||
63 | "eslint-loader": "3.0.3", | ||
64 | "file-loader": "5.0.2", | ||
65 | "friendly-errors-webpack-plugin": "1.7.0", | ||
66 | "generator-jhipster": "6.8.0", | ||
67 | "html-loader": "0.5.5", | ||
68 | "html-webpack-plugin": "3.2.0", | ||
69 | "husky": "3.1.0", | ||
70 | "jest": "24.9.0", | ||
71 | "jest-date-mock": "1.0.7", | ||
72 | "jest-junit": "10.0.0", | ||
73 | "jest-preset-angular": "8.0.0", | ||
74 | "jest-sonar-reporter": "2.0.0", | ||
75 | "lint-staged": "8.2.1", | ||
76 | "merge-jsons-webpack-plugin": "1.0.20", | ||
77 | "mini-css-extract-plugin": "0.8.0", | ||
78 | "mocha": "6.2.2", | ||
79 | "moment-locales-webpack-plugin": "1.1.2", | ||
80 | "optimize-css-assets-webpack-plugin": "5.0.3", | ||
81 | "postcss-loader": "3.0.0", | ||
82 | "prettier": "1.19.1", | ||
83 | "protractor": "5.4.2", | ||
84 | "reflect-metadata": "0.1.13", | ||
85 | "rimraf": "3.0.0", | ||
86 | "sass": "1.23.7", | ||
87 | "sass-loader": "8.0.0", | ||
88 | "simple-progress-webpack-plugin": "1.1.2", | ||
89 | "style-loader": "1.0.1", | ||
90 | "terser-webpack-plugin": "2.3.0", | ||
91 | "thread-loader": "2.1.3", | ||
92 | "to-string-loader": "1.1.6", | ||
93 | "ts-loader": "6.2.1", | ||
94 | "ts-node": "8.5.4", | ||
95 | "tslint": "6.0.0", | ||
96 | "typescript": "3.7.5", | ||
97 | "webdriver-manager": "12.1.7", | ||
98 | "webpack": "4.41.2", | ||
99 | "webpack-bundle-analyzer": "3.6.0", | ||
100 | "webpack-cli": "3.3.10", | ||
101 | "webpack-dev-server": "3.9.0", | ||
102 | "webpack-merge": "4.2.2", | ||
103 | "webpack-notifier": "1.8.0", | ||
104 | "workbox-webpack-plugin": "4.3.1", | ||
105 | "write-file-webpack-plugin": "4.5.1" | ||
106 | }, | ||
107 | "engines": { | ||
108 | "node": ">=8.9.0" | ||
109 | }, | ||
110 | "scripts": { | ||
111 | "prettier:format": "prettier --write \"{,src/**/}*.{md,json,ts,css,scss,yml}\"", | ||
112 | "lint": "eslint . --ext .js,.ts", | ||
113 | "lint:fix": "npm run lint -- --fix", | ||
114 | "ngc": "ngc -p tsconfig.app.json", | ||
115 | "cleanup": "rimraf target/classes/static/ target/classes/aot", | ||
116 | "clean-www": "rimraf target/classes/static/app/{src,target/}", | ||
117 | "e2e": "protractor src/test/javascript/protractor.conf.js", | ||
118 | "postinstall": "node node_modules/protractor/bin/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 | } |
File pom.xml added (mode: 100644) (index 0000000..2b4e616) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
3 | xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> | ||
4 | <modelVersion>4.0.0</modelVersion> | ||
5 | |||
6 | <groupId>hu.dns.honlap</groupId> | ||
7 | <artifactId>honlap</artifactId> | ||
8 | <version>0.0.1-SNAPSHOT</version> | ||
9 | <packaging>jar</packaging> | ||
10 | <name>Honlap</name> | ||
11 | |||
12 | <repositories> | ||
13 | <!-- jhipster-needle-maven-repository --> | ||
14 | </repositories> | ||
15 | |||
16 | <pluginRepositories> | ||
17 | <!-- jhipster-needle-maven-plugin-repository --> | ||
18 | </pluginRepositories> | ||
19 | |||
20 | <!-- jhipster-needle-distribution-management --> | ||
21 | |||
22 | <properties> | ||
23 | <!-- Build properties --> | ||
24 | <maven.version>3.3.9</maven.version> | ||
25 | <java.version>1.8</java.version> | ||
26 | <node.version>v12.16.1</node.version> | ||
27 | <npm.version>6.14.2</npm.version> | ||
28 | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
29 | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||
30 | <project.testresult.directory>${project.build.directory}/test-results</project.testresult.directory> | ||
31 | <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format> | ||
32 | <maven.compiler.source>${java.version}</maven.compiler.source> | ||
33 | <maven.compiler.target>${java.version}</maven.compiler.target> | ||
34 | <argLine>-Djava.security.egd=file:/dev/./urandom -Xmx256m</argLine> | ||
35 | <m2e.apt.activation>jdt_apt</m2e.apt.activation> | ||
36 | <run.addResources>false</run.addResources> | ||
37 | <!-- These remain empty unless the corresponding profile is active --> | ||
38 | <profile.no-liquibase /> | ||
39 | <profile.swagger /> | ||
40 | <profile.tls /> | ||
41 | |||
42 | <!-- Dependency versions --> | ||
43 | <jhipster-dependencies.version>3.6.0</jhipster-dependencies.version> | ||
44 | <!-- The spring-boot version should match the one managed by | ||
45 | https://mvnrepository.com/artifact/io.github.jhipster/jhipster-dependencies/${jhipster-dependencies.version} --> | ||
46 | <spring-boot.version>2.2.5.RELEASE</spring-boot.version> | ||
47 | <!-- The hibernate version should match the one managed by | ||
48 | https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/${spring-boot.version} --> | ||
49 | <hibernate.version>5.4.12.Final</hibernate.version> | ||
50 | <!-- The javassist version should match the one managed by | ||
51 | https://mvnrepository.com/artifact/org.hibernate/hibernate-core/${hibernate.version} --> | ||
52 | <javassist.version>3.24.0-GA</javassist.version> | ||
53 | <!-- The liquibase version should match the one managed by | ||
54 | https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies/${spring-boot.version} --> | ||
55 | <liquibase.version>3.8.7</liquibase.version> | ||
56 | <liquibase-hibernate5.version>3.8</liquibase-hibernate5.version> | ||
57 | <h2.version>1.4.200</h2.version> | ||
58 | <validation-api.version>2.0.1.Final</validation-api.version> | ||
59 | <jaxb-runtime.version>2.3.2</jaxb-runtime.version> | ||
60 | <archunit-junit5.version>0.13.1</archunit-junit5.version> | ||
61 | <mapstruct.version>1.3.1.Final</mapstruct.version> | ||
62 | <!-- Plugin versions --> | ||
63 | <maven-clean-plugin.version>3.1.0</maven-clean-plugin.version> | ||
64 | <maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version> | ||
65 | <maven-javadoc-plugin.version>3.1.1</maven-javadoc-plugin.version> | ||
66 | <maven-eclipse-plugin.version>2.10</maven-eclipse-plugin.version> | ||
67 | <maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version> | ||
68 | <maven-failsafe-plugin.version>3.0.0-M4</maven-failsafe-plugin.version> | ||
69 | <maven-idea-plugin.version>2.2.1</maven-idea-plugin.version> | ||
70 | <maven-resources-plugin.version>3.1.0</maven-resources-plugin.version> | ||
71 | <maven-surefire-plugin.version>3.0.0-M4</maven-surefire-plugin.version> | ||
72 | <maven-war-plugin.version>3.2.3</maven-war-plugin.version> | ||
73 | <maven-checkstyle.version>3.1.1</maven-checkstyle.version> | ||
74 | <checkstyle.version>8.29</checkstyle.version> | ||
75 | <spring-nohttp-checkstyle.version>0.0.4.RELEASE</spring-nohttp-checkstyle.version> | ||
76 | <frontend-maven-plugin.version>1.9.1</frontend-maven-plugin.version> | ||
77 | <git-commit-id-plugin.version>4.0.0</git-commit-id-plugin.version> | ||
78 | <jacoco-maven-plugin.version>0.8.5</jacoco-maven-plugin.version> | ||
79 | <jib-maven-plugin.version>2.0.0</jib-maven-plugin.version> | ||
80 | <lifecycle-mapping.version>1.0.0</lifecycle-mapping.version> | ||
81 | <properties-maven-plugin.version>1.0.0</properties-maven-plugin.version> | ||
82 | <sonar-maven-plugin.version>3.7.0.1746</sonar-maven-plugin.version> | ||
83 | <jacoco.utReportFolder>${project.build.directory}/jacoco/test</jacoco.utReportFolder> | ||
84 | <jacoco.utReportFile>${jacoco.utReportFolder}/test.exec</jacoco.utReportFile> | ||
85 | <jacoco.itReportFolder>${project.build.directory}/jacoco/integrationTest</jacoco.itReportFolder> | ||
86 | <jacoco.itReportFile>${jacoco.itReportFolder}/integrationTest.exec</jacoco.itReportFile> | ||
87 | <junit.utReportFolder>${project.testresult.directory}/test</junit.utReportFolder> | ||
88 | <junit.itReportFolder>${project.testresult.directory}/integrationTest</junit.itReportFolder> | ||
89 | <!-- jhipster-needle-maven-property --> | ||
90 | </properties> | ||
91 | |||
92 | <dependencyManagement> | ||
93 | <dependencies> | ||
94 | <dependency> | ||
95 | <groupId>io.github.jhipster</groupId> | ||
96 | <artifactId>jhipster-dependencies</artifactId> | ||
97 | <version>${jhipster-dependencies.version}</version> | ||
98 | <type>pom</type> | ||
99 | <scope>import</scope> | ||
100 | </dependency> | ||
101 | <!-- jhipster-needle-maven-add-dependency-management --> | ||
102 | </dependencies> | ||
103 | </dependencyManagement> | ||
104 | |||
105 | <dependencies> | ||
106 | <dependency> | ||
107 | <groupId>io.github.jhipster</groupId> | ||
108 | <artifactId>jhipster-framework</artifactId> | ||
109 | </dependency> | ||
110 | <dependency> | ||
111 | <groupId>javax.annotation</groupId> | ||
112 | <artifactId>javax.annotation-api</artifactId> | ||
113 | </dependency> | ||
114 | |||
115 | <dependency> | ||
116 | <groupId>org.springframework.boot</groupId> | ||
117 | <artifactId>spring-boot-starter-cache</artifactId> | ||
118 | </dependency> | ||
119 | <dependency> | ||
120 | <groupId>com.fasterxml.jackson.module</groupId> | ||
121 | <artifactId>jackson-module-jaxb-annotations</artifactId> | ||
122 | </dependency> | ||
123 | <dependency> | ||
124 | <groupId>com.fasterxml.jackson.datatype</groupId> | ||
125 | <artifactId>jackson-datatype-hibernate5</artifactId> | ||
126 | </dependency> | ||
127 | <dependency> | ||
128 | <groupId>com.fasterxml.jackson.datatype</groupId> | ||
129 | <artifactId>jackson-datatype-hppc</artifactId> | ||
130 | </dependency> | ||
131 | <dependency> | ||
132 | <groupId>com.fasterxml.jackson.datatype</groupId> | ||
133 | <artifactId>jackson-datatype-jsr310</artifactId> | ||
134 | </dependency> | ||
135 | <dependency> | ||
136 | <groupId>com.fasterxml.jackson.module</groupId> | ||
137 | <artifactId>jackson-module-afterburner</artifactId> | ||
138 | </dependency> | ||
139 | <dependency> | ||
140 | <groupId>com.h2database</groupId> | ||
141 | <artifactId>h2</artifactId> | ||
142 | <scope>test</scope> | ||
143 | </dependency> | ||
144 | <dependency> | ||
145 | <groupId>io.springfox</groupId> | ||
146 | <artifactId>springfox-swagger2</artifactId> | ||
147 | </dependency> | ||
148 | <dependency> | ||
149 | <groupId>io.springfox</groupId> | ||
150 | <artifactId>springfox-bean-validators</artifactId> | ||
151 | </dependency> | ||
152 | <dependency> | ||
153 | <groupId>com.zaxxer</groupId> | ||
154 | <artifactId>HikariCP</artifactId> | ||
155 | </dependency> | ||
156 | <dependency> | ||
157 | <groupId>commons-io</groupId> | ||
158 | <artifactId>commons-io</artifactId> | ||
159 | </dependency> | ||
160 | <dependency> | ||
161 | <groupId>org.apache.commons</groupId> | ||
162 | <artifactId>commons-lang3</artifactId> | ||
163 | </dependency> | ||
164 | <dependency> | ||
165 | <groupId>javax.cache</groupId> | ||
166 | <artifactId>cache-api</artifactId> | ||
167 | </dependency> | ||
168 | <dependency> | ||
169 | <groupId>org.ehcache</groupId> | ||
170 | <artifactId>ehcache</artifactId> | ||
171 | </dependency> | ||
172 | <dependency> | ||
173 | <groupId>org.hibernate</groupId> | ||
174 | <artifactId>hibernate-jcache</artifactId> | ||
175 | </dependency> | ||
176 | <dependency> | ||
177 | <groupId>org.hibernate</groupId> | ||
178 | <artifactId>hibernate-jpamodelgen</artifactId> | ||
179 | <scope>provided</scope> | ||
180 | </dependency> | ||
181 | <dependency> | ||
182 | <groupId>org.hibernate</groupId> | ||
183 | <artifactId>hibernate-core</artifactId> | ||
184 | </dependency> | ||
185 | <dependency> | ||
186 | <groupId>org.hibernate.validator</groupId> | ||
187 | <artifactId>hibernate-validator</artifactId> | ||
188 | </dependency> | ||
189 | <dependency> | ||
190 | <groupId>org.liquibase</groupId> | ||
191 | <artifactId>liquibase-core</artifactId> | ||
192 | <!-- Inherited version from Spring Boot can't be used because of regressions --> | ||
193 | <version>${liquibase.version}</version> | ||
194 | </dependency> | ||
195 | <dependency> | ||
196 | <groupId>net.logstash.logback</groupId> | ||
197 | <artifactId>logstash-logback-encoder</artifactId> | ||
198 | </dependency> | ||
199 | <dependency> | ||
200 | <groupId>org.postgresql</groupId> | ||
201 | <artifactId>postgresql</artifactId> | ||
202 | </dependency> | ||
203 | <dependency> | ||
204 | <groupId>org.mapstruct</groupId> | ||
205 | <artifactId>mapstruct</artifactId> | ||
206 | </dependency> | ||
207 | <dependency> | ||
208 | <groupId>org.mapstruct</groupId> | ||
209 | <artifactId>mapstruct-processor</artifactId> | ||
210 | <scope>provided</scope> | ||
211 | </dependency> | ||
212 | <dependency> | ||
213 | <groupId>org.springframework.boot</groupId> | ||
214 | <artifactId>spring-boot-configuration-processor</artifactId> | ||
215 | <scope>provided</scope> | ||
216 | </dependency> | ||
217 | <dependency> | ||
218 | <groupId>org.springframework.boot</groupId> | ||
219 | <artifactId>spring-boot-loader-tools</artifactId> | ||
220 | </dependency> | ||
221 | <dependency> | ||
222 | <groupId>org.springframework.boot</groupId> | ||
223 | <artifactId>spring-boot-starter-actuator</artifactId> | ||
224 | </dependency> | ||
225 | <dependency> | ||
226 | <groupId>org.springframework.boot</groupId> | ||
227 | <artifactId>spring-boot-starter-aop</artifactId> | ||
228 | </dependency> | ||
229 | <dependency> | ||
230 | <groupId>org.springframework.boot</groupId> | ||
231 | <artifactId>spring-boot-starter-data-jpa</artifactId> | ||
232 | </dependency> | ||
233 | <dependency> | ||
234 | <groupId>org.springframework.boot</groupId> | ||
235 | <artifactId>spring-boot-starter-logging</artifactId> | ||
236 | </dependency> | ||
237 | <dependency> | ||
238 | <groupId>org.springframework.boot</groupId> | ||
239 | <artifactId>spring-boot-starter-mail</artifactId> | ||
240 | </dependency> | ||
241 | <dependency> | ||
242 | <groupId>org.springframework.boot</groupId> | ||
243 | <artifactId>spring-boot-starter-security</artifactId> | ||
244 | </dependency> | ||
245 | <dependency> | ||
246 | <groupId>org.springframework.boot</groupId> | ||
247 | <artifactId>spring-boot-starter-thymeleaf</artifactId> | ||
248 | </dependency> | ||
249 | <dependency> | ||
250 | <groupId>org.springframework.boot</groupId> | ||
251 | <artifactId>spring-boot-starter-web</artifactId> | ||
252 | </dependency> | ||
253 | <dependency> | ||
254 | <groupId>org.springframework.boot</groupId> | ||
255 | <artifactId>spring-boot-starter-test</artifactId> | ||
256 | <scope>test</scope> | ||
257 | </dependency> | ||
258 | <dependency> | ||
259 | <groupId>org.springframework.boot</groupId> | ||
260 | <artifactId>spring-boot-test</artifactId> | ||
261 | <scope>test</scope> | ||
262 | </dependency> | ||
263 | <dependency> | ||
264 | <groupId>org.springframework.security</groupId> | ||
265 | <artifactId>spring-security-test</artifactId> | ||
266 | <scope>test</scope> | ||
267 | </dependency> | ||
268 | <dependency> | ||
269 | <groupId>com.tngtech.archunit</groupId> | ||
270 | <artifactId>archunit-junit5-api</artifactId> | ||
271 | <version>${archunit-junit5.version}</version> | ||
272 | <scope>test</scope> | ||
273 | </dependency> | ||
274 | <!-- Adding the engine dependency to the surefire-plugin unfortunately does not work in the current version. --> | ||
275 | <!-- https://www.archunit.org/userguide/html/000_Index.html#_junit_5 --> | ||
276 | <dependency> | ||
277 | <groupId>com.tngtech.archunit</groupId> | ||
278 | <artifactId>archunit-junit5-engine</artifactId> | ||
279 | <version>${archunit-junit5.version}</version> | ||
280 | <scope>test</scope> | ||
281 | </dependency> | ||
282 | <dependency> | ||
283 | <groupId>org.zalando</groupId> | ||
284 | <artifactId>problem-spring-web</artifactId> | ||
285 | </dependency> | ||
286 | <dependency> | ||
287 | <groupId>io.jsonwebtoken</groupId> | ||
288 | <artifactId>jjwt-api</artifactId> | ||
289 | </dependency> | ||
290 | <dependency> | ||
291 | <groupId>io.jsonwebtoken</groupId> | ||
292 | <artifactId>jjwt-impl</artifactId> | ||
293 | <scope>runtime</scope> | ||
294 | </dependency> | ||
295 | <dependency> | ||
296 | <groupId>io.jsonwebtoken</groupId> | ||
297 | <artifactId>jjwt-jackson</artifactId> | ||
298 | <scope>runtime</scope> | ||
299 | </dependency> | ||
300 | <!-- Spring Cloud --> | ||
301 | <dependency> | ||
302 | <groupId>org.springframework.boot</groupId> | ||
303 | <artifactId>spring-boot-starter-cloud-connectors</artifactId> | ||
304 | </dependency> | ||
305 | <dependency> | ||
306 | <groupId>org.springframework.security</groupId> | ||
307 | <artifactId>spring-security-data</artifactId> | ||
308 | </dependency> | ||
309 | <dependency> | ||
310 | <groupId>io.micrometer</groupId> | ||
311 | <artifactId>micrometer-registry-prometheus</artifactId> | ||
312 | </dependency> | ||
313 | <dependency> | ||
314 | <groupId>io.dropwizard.metrics</groupId> | ||
315 | <artifactId>metrics-core</artifactId> | ||
316 | </dependency> | ||
317 | <!-- Cucumber --> | ||
318 | <dependency> | ||
319 | <groupId>io.cucumber</groupId> | ||
320 | <artifactId>cucumber-junit</artifactId> | ||
321 | <scope>test</scope> | ||
322 | </dependency> | ||
323 | <dependency> | ||
324 | <groupId>io.cucumber</groupId> | ||
325 | <artifactId>cucumber-spring</artifactId> | ||
326 | <scope>test</scope> | ||
327 | </dependency> | ||
328 | <!-- jhipster-needle-maven-add-dependency --> | ||
329 | </dependencies> | ||
330 | |||
331 | <build> | ||
332 | <defaultGoal>spring-boot:run</defaultGoal> | ||
333 | <testResources> | ||
334 | <testResource> | ||
335 | <directory>src/test/resources/</directory> | ||
336 | </testResource> | ||
337 | <testResource> | ||
338 | <directory>src/test/features</directory> | ||
339 | </testResource> | ||
340 | </testResources> | ||
341 | <plugins> | ||
342 | <plugin> | ||
343 | <groupId>org.apache.maven.plugins</groupId> | ||
344 | <artifactId>maven-compiler-plugin</artifactId> | ||
345 | </plugin> | ||
346 | <plugin> | ||
347 | <groupId>org.apache.maven.plugins</groupId> | ||
348 | <artifactId>maven-checkstyle-plugin</artifactId> | ||
349 | </plugin> | ||
350 | <plugin> | ||
351 | <groupId>org.apache.maven.plugins</groupId> | ||
352 | <artifactId>maven-javadoc-plugin</artifactId> | ||
353 | </plugin> | ||
354 | <plugin> | ||
355 | <groupId>org.apache.maven.plugins</groupId> | ||
356 | <artifactId>maven-eclipse-plugin</artifactId> | ||
357 | </plugin> | ||
358 | <plugin> | ||
359 | <groupId>org.apache.maven.plugins</groupId> | ||
360 | <artifactId>maven-enforcer-plugin</artifactId> | ||
361 | </plugin> | ||
362 | <plugin> | ||
363 | <groupId>org.apache.maven.plugins</groupId> | ||
364 | <artifactId>maven-failsafe-plugin</artifactId> | ||
365 | </plugin> | ||
366 | <plugin> | ||
367 | <groupId>org.apache.maven.plugins</groupId> | ||
368 | <artifactId>maven-idea-plugin</artifactId> | ||
369 | </plugin> | ||
370 | <plugin> | ||
371 | <groupId>org.apache.maven.plugins</groupId> | ||
372 | <artifactId>maven-resources-plugin</artifactId> | ||
373 | </plugin> | ||
374 | <plugin> | ||
375 | <groupId>org.apache.maven.plugins</groupId> | ||
376 | <artifactId>maven-surefire-plugin</artifactId> | ||
377 | </plugin> | ||
378 | <plugin> | ||
379 | <groupId>org.jacoco</groupId> | ||
380 | <artifactId>jacoco-maven-plugin</artifactId> | ||
381 | </plugin> | ||
382 | <plugin> | ||
383 | <groupId>org.sonarsource.scanner.maven</groupId> | ||
384 | <artifactId>sonar-maven-plugin</artifactId> | ||
385 | </plugin> | ||
386 | <plugin> | ||
387 | <groupId>org.liquibase</groupId> | ||
388 | <artifactId>liquibase-maven-plugin</artifactId> | ||
389 | </plugin> | ||
390 | <plugin> | ||
391 | <groupId>org.springframework.boot</groupId> | ||
392 | <artifactId>spring-boot-maven-plugin</artifactId> | ||
393 | </plugin> | ||
394 | <plugin> | ||
395 | <groupId>com.google.cloud.tools</groupId> | ||
396 | <artifactId>jib-maven-plugin</artifactId> | ||
397 | </plugin> | ||
398 | <plugin> | ||
399 | <groupId>org.codehaus.mojo</groupId> | ||
400 | <artifactId>properties-maven-plugin</artifactId> | ||
401 | </plugin> | ||
402 | <!-- jhipster-needle-maven-add-plugin --> | ||
403 | </plugins> | ||
404 | <pluginManagement> | ||
405 | <plugins> | ||
406 | <plugin> | ||
407 | <groupId>org.apache.maven.plugins</groupId> | ||
408 | <artifactId>maven-checkstyle-plugin</artifactId> | ||
409 | <version>${maven-checkstyle.version}</version> | ||
410 | <dependencies> | ||
411 | <dependency> | ||
412 | <groupId>com.puppycrawl.tools</groupId> | ||
413 | <artifactId>checkstyle</artifactId> | ||
414 | <version>${checkstyle.version}</version> | ||
415 | </dependency> | ||
416 | <dependency> | ||
417 | <groupId>io.spring.nohttp</groupId> | ||
418 | <artifactId>nohttp-checkstyle</artifactId> | ||
419 | <version>${spring-nohttp-checkstyle.version}</version> | ||
420 | </dependency> | ||
421 | </dependencies> | ||
422 | <configuration> | ||
423 | <configLocation>checkstyle.xml</configLocation> | ||
424 | <includes>pom.xml,README.md</includes> | ||
425 | <excludes>.git/**/*,target/**/*,node_modules/**/*,node/**/*</excludes> | ||
426 | <sourceDirectories>./</sourceDirectories> | ||
427 | </configuration> | ||
428 | <executions> | ||
429 | <execution> | ||
430 | <goals> | ||
431 | <goal>check</goal> | ||
432 | </goals> | ||
433 | </execution> | ||
434 | </executions> | ||
435 | </plugin> | ||
436 | <plugin> | ||
437 | <groupId>org.apache.maven.plugins</groupId> | ||
438 | <artifactId>maven-compiler-plugin</artifactId> | ||
439 | <version>${maven-compiler-plugin.version}</version> | ||
440 | <configuration> | ||
441 | <source>${java.version}</source> | ||
442 | <target>${java.version}</target> | ||
443 | <annotationProcessorPaths> | ||
444 | <path> | ||
445 | <groupId>org.springframework.boot</groupId> | ||
446 | <artifactId>spring-boot-configuration-processor</artifactId> | ||
447 | <version>${spring-boot.version}</version> | ||
448 | </path> | ||
449 | <path> | ||
450 | <groupId>org.mapstruct</groupId> | ||
451 | <artifactId>mapstruct-processor</artifactId> | ||
452 | <version>${mapstruct.version}</version> | ||
453 | </path> | ||
454 | <!-- For JPA static metamodel generation --> | ||
455 | <path> | ||
456 | <groupId>org.hibernate</groupId> | ||
457 | <artifactId>hibernate-jpamodelgen</artifactId> | ||
458 | <version>${hibernate.version}</version> | ||
459 | </path> | ||
460 | <path> | ||
461 | <groupId>org.glassfish.jaxb</groupId> | ||
462 | <artifactId>jaxb-runtime</artifactId> | ||
463 | <version>${jaxb-runtime.version}</version> | ||
464 | </path> | ||
465 | <!-- jhipster-needle-maven-add-annotation-processor --> | ||
466 | </annotationProcessorPaths> | ||
467 | </configuration> | ||
468 | </plugin> | ||
469 | <plugin> | ||
470 | <groupId>org.apache.maven.plugins</groupId> | ||
471 | <artifactId>maven-javadoc-plugin</artifactId> | ||
472 | <version>${maven-javadoc-plugin.version}</version> | ||
473 | <configuration> | ||
474 | <source>${maven.compiler.source}</source> | ||
475 | </configuration> | ||
476 | </plugin> | ||
477 | <plugin> | ||
478 | <groupId>org.apache.maven.plugins</groupId> | ||
479 | <artifactId>maven-war-plugin</artifactId> | ||
480 | <version>${maven-war-plugin.version}</version> | ||
481 | <executions> | ||
482 | <execution> | ||
483 | <goals> | ||
484 | <goal>war</goal> | ||
485 | </goals> | ||
486 | <phase>package</phase> | ||
487 | </execution> | ||
488 | </executions> | ||
489 | <configuration> | ||
490 | <warSourceIncludes>WEB-INF/**,META-INF/**</warSourceIncludes> | ||
491 | <failOnMissingWebXml>false</failOnMissingWebXml> | ||
492 | <warSourceDirectory>target/classes/static/</warSourceDirectory> | ||
493 | <webResources> | ||
494 | <resource> | ||
495 | <directory>src/main/webapp</directory> | ||
496 | <includes> | ||
497 | <include>WEB-INF/**</include> | ||
498 | </includes> | ||
499 | </resource> | ||
500 | </webResources> | ||
501 | </configuration> | ||
502 | </plugin> | ||
503 | <plugin> | ||
504 | <groupId>com.github.eirslett</groupId> | ||
505 | <artifactId>frontend-maven-plugin</artifactId> | ||
506 | <version>${frontend-maven-plugin.version}</version> | ||
507 | </plugin> | ||
508 | <plugin> | ||
509 | <groupId>org.codehaus.mojo</groupId> | ||
510 | <artifactId>properties-maven-plugin</artifactId> | ||
511 | <version>${properties-maven-plugin.version}</version> | ||
512 | <executions> | ||
513 | <execution> | ||
514 | <phase>initialize</phase> | ||
515 | <goals> | ||
516 | <goal>read-project-properties</goal> | ||
517 | </goals> | ||
518 | <configuration> | ||
519 | <files> | ||
520 | <file>sonar-project.properties</file> | ||
521 | </files> | ||
522 | </configuration> | ||
523 | </execution> | ||
524 | </executions> | ||
525 | </plugin> | ||
526 | |||
527 | <plugin> | ||
528 | <groupId>pl.project13.maven</groupId> | ||
529 | <artifactId>git-commit-id-plugin</artifactId> | ||
530 | <version>${git-commit-id-plugin.version}</version> | ||
531 | <executions> | ||
532 | <execution> | ||
533 | <goals> | ||
534 | <goal>revision</goal> | ||
535 | </goals> | ||
536 | </execution> | ||
537 | </executions> | ||
538 | <configuration> | ||
539 | <failOnNoGitDirectory>false</failOnNoGitDirectory> | ||
540 | <failOnUnableToExtractRepoInfo>false</failOnUnableToExtractRepoInfo> | ||
541 | <generateGitPropertiesFile>true</generateGitPropertiesFile> | ||
542 | <includeOnlyProperties> | ||
543 | <includeOnlyProperty>^git.commit.id.abbrev$</includeOnlyProperty> | ||
544 | <includeOnlyProperty>^git.commit.id.describe$</includeOnlyProperty> | ||
545 | <includeOnlyProperty>^git.branch$</includeOnlyProperty> | ||
546 | </includeOnlyProperties> | ||
547 | </configuration> | ||
548 | </plugin> | ||
549 | <plugin> | ||
550 | <groupId>org.jacoco</groupId> | ||
551 | <artifactId>jacoco-maven-plugin</artifactId> | ||
552 | <version>${jacoco-maven-plugin.version}</version> | ||
553 | <executions> | ||
554 | <execution> | ||
555 | <id>pre-unit-tests</id> | ||
556 | <goals> | ||
557 | <goal>prepare-agent</goal> | ||
558 | </goals> | ||
559 | <configuration> | ||
560 | <!-- Sets the path to the file which contains the execution data. --> | ||
561 | <destFile>${jacoco.utReportFile}</destFile> | ||
562 | </configuration> | ||
563 | </execution> | ||
564 | <!-- Ensures that the code coverage report for unit tests is created after unit tests have been run --> | ||
565 | <execution> | ||
566 | <id>post-unit-test</id> | ||
567 | <phase>test</phase> | ||
568 | <goals> | ||
569 | <goal>report</goal> | ||
570 | </goals> | ||
571 | <configuration> | ||
572 | <dataFile>${jacoco.utReportFile}</dataFile> | ||
573 | <outputDirectory>${jacoco.utReportFolder}</outputDirectory> | ||
574 | </configuration> | ||
575 | </execution> | ||
576 | <execution> | ||
577 | <id>pre-integration-tests</id> | ||
578 | <goals> | ||
579 | <goal>prepare-agent-integration</goal> | ||
580 | </goals> | ||
581 | <configuration> | ||
582 | <!-- Sets the path to the file which contains the execution data. --> | ||
583 | <destFile>${jacoco.itReportFile}</destFile> | ||
584 | </configuration> | ||
585 | </execution> | ||
586 | <!-- Ensures that the code coverage report for integration tests is created after integration tests have been run --> | ||
587 | <execution> | ||
588 | <id>post-integration-tests</id> | ||
589 | <phase>post-integration-test</phase> | ||
590 | <goals> | ||
591 | <goal>report-integration</goal> | ||
592 | </goals> | ||
593 | <configuration> | ||
594 | <dataFile>${jacoco.itReportFile}</dataFile> | ||
595 | <outputDirectory>${jacoco.itReportFolder}</outputDirectory> | ||
596 | </configuration> | ||
597 | </execution> | ||
598 | </executions> | ||
599 | </plugin> | ||
600 | <plugin> | ||
601 | <groupId>com.google.cloud.tools</groupId> | ||
602 | <artifactId>jib-maven-plugin</artifactId> | ||
603 | <version>${jib-maven-plugin.version}</version> | ||
604 | <configuration> | ||
605 | <from> | ||
606 | <image>adoptopenjdk:11-jre-hotspot</image> | ||
607 | </from> | ||
608 | <to> | ||
609 | <image>honlap:latest</image> | ||
610 | </to> | ||
611 | <container> | ||
612 | <entrypoint> | ||
613 | <shell>bash</shell> | ||
614 | <option>-c</option> | ||
615 | <arg>/entrypoint.sh</arg> | ||
616 | </entrypoint> | ||
617 | <ports> | ||
618 | <port>8080</port> | ||
619 | </ports> | ||
620 | <environment> | ||
621 | <SPRING_OUTPUT_ANSI_ENABLED>ALWAYS</SPRING_OUTPUT_ANSI_ENABLED> | ||
622 | <JHIPSTER_SLEEP>0</JHIPSTER_SLEEP> | ||
623 | </environment> | ||
624 | <creationTime>USE_CURRENT_TIMESTAMP</creationTime> | ||
625 | </container> | ||
626 | <extraDirectories> | ||
627 | <paths>src/main/jib</paths> | ||
628 | <permissions> | ||
629 | <permission> | ||
630 | <file>/entrypoint.sh</file> | ||
631 | <mode>755</mode> | ||
632 | </permission> | ||
633 | </permissions> | ||
634 | </extraDirectories> | ||
635 | </configuration> | ||
636 | </plugin> | ||
637 | <plugin> | ||
638 | <groupId>org.liquibase</groupId> | ||
639 | <artifactId>liquibase-maven-plugin</artifactId> | ||
640 | <version>${liquibase.version}</version> | ||
641 | <configuration> | ||
642 | <changeLogFile>${project.basedir}/src/main/resources/config/liquibase/master.xml</changeLogFile> | ||
643 | <diffChangeLogFile>${project.basedir}/src/main/resources/config/liquibase/changelog/${maven.build.timestamp}_changelog.xml</diffChangeLogFile> | ||
644 | <driver>org.h2.Driver</driver> | ||
645 | <url>jdbc:h2:file:${project.build.directory}/h2db/db/honlap</url> | ||
646 | <defaultSchemaName></defaultSchemaName> | ||
647 | <username>honlap</username> | ||
648 | <password></password> | ||
649 | <referenceUrl>hibernate:spring:hu.dns.honlap.domain?dialect=org.hibernate.dialect.H2Dialect&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy</referenceUrl> | ||
650 | <verbose>true</verbose> | ||
651 | <logging>debug</logging> | ||
652 | <contexts>!test</contexts> | ||
653 | </configuration> | ||
654 | <dependencies> | ||
655 | <dependency> | ||
656 | <groupId>org.liquibase</groupId> | ||
657 | <artifactId>liquibase-core</artifactId> | ||
658 | <version>${liquibase.version}</version> | ||
659 | </dependency> | ||
660 | <dependency> | ||
661 | <groupId>org.liquibase.ext</groupId> | ||
662 | <artifactId>liquibase-hibernate5</artifactId> | ||
663 | <version>${liquibase-hibernate5.version}</version> | ||
664 | </dependency> | ||
665 | <dependency> | ||
666 | <groupId>org.springframework.boot</groupId> | ||
667 | <artifactId>spring-boot-starter-data-jpa</artifactId> | ||
668 | <version>${spring-boot.version}</version> | ||
669 | </dependency> | ||
670 | <dependency> | ||
671 | <groupId>javax.validation</groupId> | ||
672 | <artifactId>validation-api</artifactId> | ||
673 | <version>${validation-api.version}</version> | ||
674 | </dependency> | ||
675 | <dependency> | ||
676 | <groupId>org.javassist</groupId> | ||
677 | <artifactId>javassist</artifactId> | ||
678 | <version>${javassist.version}</version> | ||
679 | </dependency> | ||
680 | <dependency> | ||
681 | <groupId>com.h2database</groupId> | ||
682 | <artifactId>h2</artifactId> | ||
683 | <version>${h2.version}</version> | ||
684 | </dependency> | ||
685 | </dependencies> | ||
686 | </plugin> | ||
687 | <plugin> | ||
688 | <artifactId>maven-clean-plugin</artifactId> | ||
689 | <version>${maven-clean-plugin.version}</version> | ||
690 | </plugin> | ||
691 | <plugin> | ||
692 | <groupId>org.apache.maven.plugins</groupId> | ||
693 | <artifactId>maven-eclipse-plugin</artifactId> | ||
694 | <version>${maven-eclipse-plugin.version}</version> | ||
695 | <configuration> | ||
696 | <downloadSources>true</downloadSources> | ||
697 | <downloadJavadocs>true</downloadJavadocs> | ||
698 | </configuration> | ||
699 | </plugin> | ||
700 | <plugin> | ||
701 | <groupId>org.apache.maven.plugins</groupId> | ||
702 | <artifactId>maven-enforcer-plugin</artifactId> | ||
703 | <version>${maven-enforcer-plugin.version}</version> | ||
704 | <executions> | ||
705 | <execution> | ||
706 | <id>enforce-versions</id> | ||
707 | <goals> | ||
708 | <goal>enforce</goal> | ||
709 | </goals> | ||
710 | </execution> | ||
711 | <execution> | ||
712 | <id>enforce-dependencyConvergence</id> | ||
713 | <configuration> | ||
714 | <rules> | ||
715 | <DependencyConvergence /> | ||
716 | </rules> | ||
717 | <fail>false</fail> | ||
718 | </configuration> | ||
719 | <goals> | ||
720 | <goal>enforce</goal> | ||
721 | </goals> | ||
722 | </execution> | ||
723 | </executions> | ||
724 | <configuration> | ||
725 | <rules> | ||
726 | <requireMavenVersion> | ||
727 | <message>You are running an older version of Maven. JHipster requires at least Maven ${maven.version}</message> | ||
728 | <version>[${maven.version},)</version> | ||
729 | </requireMavenVersion> | ||
730 | <requireJavaVersion> | ||
731 | <message>You are running an incompatible version of Java. JHipster supports JDK 8 to 13.</message> | ||
732 | <version>[1.8,14)</version> | ||
733 | </requireJavaVersion> | ||
734 | </rules> | ||
735 | </configuration> | ||
736 | </plugin> | ||
737 | <plugin> | ||
738 | <groupId>org.apache.maven.plugins</groupId> | ||
739 | <artifactId>maven-idea-plugin</artifactId> | ||
740 | <version>${maven-idea-plugin.version}</version> | ||
741 | <configuration> | ||
742 | <exclude>node_modules</exclude> | ||
743 | </configuration> | ||
744 | </plugin> | ||
745 | <plugin> | ||
746 | <groupId>org.apache.maven.plugins</groupId> | ||
747 | <artifactId>maven-resources-plugin</artifactId> | ||
748 | <version>${maven-resources-plugin.version}</version> | ||
749 | <executions> | ||
750 | <execution> | ||
751 | <id>default-resources</id> | ||
752 | <phase>validate</phase> | ||
753 | <goals> | ||
754 | <goal>copy-resources</goal> | ||
755 | </goals> | ||
756 | <configuration> | ||
757 | <outputDirectory>${project.build.directory}/classes</outputDirectory> | ||
758 | <useDefaultDelimiters>false</useDefaultDelimiters> | ||
759 | <delimiters> | ||
760 | <delimiter>#</delimiter> | ||
761 | </delimiters> | ||
762 | <resources> | ||
763 | <resource> | ||
764 | <directory>src/main/resources/</directory> | ||
765 | <filtering>true</filtering> | ||
766 | <includes> | ||
767 | <include>config/*.yml</include> | ||
768 | </includes> | ||
769 | </resource> | ||
770 | <resource> | ||
771 | <directory>src/main/resources/</directory> | ||
772 | <filtering>false</filtering> | ||
773 | <excludes> | ||
774 | <exclude>config/*.yml</exclude> | ||
775 | </excludes> | ||
776 | </resource> | ||
777 | </resources> | ||
778 | </configuration> | ||
779 | </execution> | ||
780 | </executions> | ||
781 | </plugin> | ||
782 | <plugin> | ||
783 | <groupId>org.apache.maven.plugins</groupId> | ||
784 | <artifactId>maven-surefire-plugin</artifactId> | ||
785 | <version>${maven-surefire-plugin.version}</version> | ||
786 | <configuration> | ||
787 | <!-- Force alphabetical order to have a reproducible build --> | ||
788 | <runOrder>alphabetical</runOrder> | ||
789 | <reportsDirectory>${junit.utReportFolder}</reportsDirectory> | ||
790 | <excludes> | ||
791 | <exclude>**/*IT*</exclude> | ||
792 | <exclude>**/*IntTest*</exclude> | ||
793 | </excludes> | ||
794 | </configuration> | ||
795 | </plugin> | ||
796 | <plugin> | ||
797 | <groupId>org.apache.maven.plugins</groupId> | ||
798 | <artifactId>maven-failsafe-plugin</artifactId> | ||
799 | <version>${maven-failsafe-plugin.version}</version> | ||
800 | <configuration> | ||
801 | <!-- Due to spring-boot repackage, without adding this property test classes are not found | ||
802 | See https://github.com/spring-projects/spring-boot/issues/6254 --> | ||
803 | <classesDirectory>${project.build.outputDirectory}</classesDirectory> | ||
804 | <!-- Force alphabetical order to have a reproducible build --> | ||
805 | <runOrder>alphabetical</runOrder> | ||
806 | <reportsDirectory>${junit.itReportFolder}</reportsDirectory> | ||
807 | <includes> | ||
808 | <include>**/*IT*</include> | ||
809 | <include>**/*IntTest*</include> | ||
810 | </includes> | ||
811 | </configuration> | ||
812 | <executions> | ||
813 | <execution> | ||
814 | <id>integration-test</id> | ||
815 | <goals> | ||
816 | <goal>integration-test</goal> | ||
817 | </goals> | ||
818 | </execution> | ||
819 | <execution> | ||
820 | <id>verify</id> | ||
821 | <goals> | ||
822 | <goal>verify</goal> | ||
823 | </goals> | ||
824 | </execution> | ||
825 | </executions> | ||
826 | </plugin> | ||
827 | <plugin> | ||
828 | <groupId>org.sonarsource.scanner.maven</groupId> | ||
829 | <artifactId>sonar-maven-plugin</artifactId> | ||
830 | <version>${sonar-maven-plugin.version}</version> | ||
831 | </plugin> | ||
832 | <plugin> | ||
833 | <groupId>org.springframework.boot</groupId> | ||
834 | <artifactId>spring-boot-maven-plugin</artifactId> | ||
835 | <version>${spring-boot.version}</version> | ||
836 | <executions> | ||
837 | <execution> | ||
838 | <goals> | ||
839 | <goal>repackage</goal> | ||
840 | </goals> | ||
841 | </execution> | ||
842 | </executions> | ||
843 | <configuration> | ||
844 | <mainClass>${start-class}</mainClass> | ||
845 | <fork>true</fork> | ||
846 | <!-- | ||
847 | Enable the line below to have remote debugging of your application on port 5005 | ||
848 | <jvmArguments>-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005</jvmArguments> | ||
849 | --> | ||
850 | </configuration> | ||
851 | |||
852 | </plugin> | ||
853 | <!-- jhipster-needle-maven-add-plugin-management --> | ||
854 | </plugins> | ||
855 | </pluginManagement> | ||
856 | </build> | ||
857 | <profiles> | ||
858 | <profile> | ||
859 | <id>no-liquibase</id> | ||
860 | <properties> | ||
861 | <profile.no-liquibase>,no-liquibase</profile.no-liquibase> | ||
862 | </properties> | ||
863 | </profile> | ||
864 | <profile> | ||
865 | <id>swagger</id> | ||
866 | <properties> | ||
867 | <profile.swagger>,swagger</profile.swagger> | ||
868 | </properties> | ||
869 | </profile> | ||
870 | <profile> | ||
871 | <id>tls</id> | ||
872 | <properties> | ||
873 | <profile.tls>,tls</profile.tls> | ||
874 | </properties> | ||
875 | </profile> | ||
876 | <profile> | ||
877 | <id>webpack</id> | ||
878 | <activation> | ||
879 | <activeByDefault>true</activeByDefault> | ||
880 | </activation> | ||
881 | <dependencies> | ||
882 | <dependency> | ||
883 | <groupId>com.h2database</groupId> | ||
884 | <artifactId>h2</artifactId> | ||
885 | </dependency> | ||
886 | </dependencies> | ||
887 | <build> | ||
888 | <plugins> | ||
889 | <plugin> | ||
890 | <groupId>com.github.eirslett</groupId> | ||
891 | <artifactId>frontend-maven-plugin</artifactId> | ||
892 | <executions> | ||
893 | <execution> | ||
894 | <id>install node and npm</id> | ||
895 | <goals> | ||
896 | <goal>install-node-and-npm</goal> | ||
897 | </goals> | ||
898 | <configuration> | ||
899 | <nodeVersion>${node.version}</nodeVersion> | ||
900 | <npmVersion>${npm.version}</npmVersion> | ||
901 | </configuration> | ||
902 | </execution> | ||
903 | <execution> | ||
904 | <id>npm install</id> | ||
905 | <goals> | ||
906 | <goal>npm</goal> | ||
907 | </goals> | ||
908 | </execution> | ||
909 | <execution> | ||
910 | <id>webpack build dev</id> | ||
911 | <goals> | ||
912 | <goal>npm</goal> | ||
913 | </goals> | ||
914 | <phase>generate-resources</phase> | ||
915 | <configuration> | ||
916 | <arguments>run webpack:build</arguments> | ||
917 | <environmentVariables> | ||
918 | <APP_VERSION>${project.version}</APP_VERSION> | ||
919 | </environmentVariables> | ||
920 | <npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven> | ||
921 | </configuration> | ||
922 | </execution> | ||
923 | </executions> | ||
924 | </plugin> | ||
925 | </plugins> | ||
926 | </build> | ||
927 | <properties> | ||
928 | <!-- default Spring profiles --> | ||
929 | <spring.profiles.active>dev${profile.no-liquibase}</spring.profiles.active> | ||
930 | </properties> | ||
931 | </profile> | ||
932 | <profile> | ||
933 | <id>dev</id> | ||
934 | <activation> | ||
935 | <activeByDefault>true</activeByDefault> | ||
936 | </activation> | ||
937 | <dependencies> | ||
938 | <dependency> | ||
939 | <groupId>org.springframework.boot</groupId> | ||
940 | <artifactId>spring-boot-starter-undertow</artifactId> | ||
941 | </dependency> | ||
942 | <dependency> | ||
943 | <groupId>org.springframework.boot</groupId> | ||
944 | <artifactId>spring-boot-devtools</artifactId> | ||
945 | <optional>true</optional> | ||
946 | </dependency> | ||
947 | <dependency> | ||
948 | <groupId>com.h2database</groupId> | ||
949 | <artifactId>h2</artifactId> | ||
950 | </dependency> | ||
951 | </dependencies> | ||
952 | <properties> | ||
953 | <!-- default Spring profiles --> | ||
954 | <spring.profiles.active>dev${profile.tls}${profile.no-liquibase}</spring.profiles.active> | ||
955 | </properties> | ||
956 | </profile> | ||
957 | <profile> | ||
958 | <id>prod</id> | ||
959 | <dependencies> | ||
960 | <dependency> | ||
961 | <groupId>org.springframework.boot</groupId> | ||
962 | <artifactId>spring-boot-starter-undertow</artifactId> | ||
963 | </dependency> | ||
964 | </dependencies> | ||
965 | <build> | ||
966 | <plugins> | ||
967 | <plugin> | ||
968 | <artifactId>maven-clean-plugin</artifactId> | ||
969 | <configuration> | ||
970 | <filesets> | ||
971 | <fileset> | ||
972 | <directory>target/classes/static/</directory> | ||
973 | </fileset> | ||
974 | </filesets> | ||
975 | </configuration> | ||
976 | </plugin> | ||
977 | <plugin> | ||
978 | <groupId>org.springframework.boot</groupId> | ||
979 | <artifactId>spring-boot-maven-plugin</artifactId> | ||
980 | <executions> | ||
981 | <execution> | ||
982 | <goals> | ||
983 | <goal>build-info</goal> | ||
984 | </goals> | ||
985 | </execution> | ||
986 | </executions> | ||
987 | </plugin> | ||
988 | <plugin> | ||
989 | <groupId>com.github.eirslett</groupId> | ||
990 | <artifactId>frontend-maven-plugin</artifactId> | ||
991 | <executions> | ||
992 | <execution> | ||
993 | <id>install node and npm</id> | ||
994 | <goals> | ||
995 | <goal>install-node-and-npm</goal> | ||
996 | </goals> | ||
997 | <configuration> | ||
998 | <nodeVersion>${node.version}</nodeVersion> | ||
999 | <npmVersion>${npm.version}</npmVersion> | ||
1000 | </configuration> | ||
1001 | </execution> | ||
1002 | <execution> | ||
1003 | <id>npm install</id> | ||
1004 | <goals> | ||
1005 | <goal>npm</goal> | ||
1006 | </goals> | ||
1007 | <configuration> | ||
1008 | <arguments>install</arguments> | ||
1009 | </configuration> | ||
1010 | </execution> | ||
1011 | <execution> | ||
1012 | <id>webpack build test</id> | ||
1013 | <goals> | ||
1014 | <goal>npm</goal> | ||
1015 | </goals> | ||
1016 | <phase>test</phase> | ||
1017 | <configuration> | ||
1018 | <arguments>run webpack:test</arguments> | ||
1019 | <npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven> | ||
1020 | </configuration> | ||
1021 | </execution> | ||
1022 | <execution> | ||
1023 | <id>webpack build prod</id> | ||
1024 | <goals> | ||
1025 | <goal>npm</goal> | ||
1026 | </goals> | ||
1027 | <phase>generate-resources</phase> | ||
1028 | <configuration> | ||
1029 | <arguments>run webpack:prod</arguments> | ||
1030 | <environmentVariables> | ||
1031 | <APP_VERSION>${project.version}</APP_VERSION> | ||
1032 | </environmentVariables> | ||
1033 | <npmInheritsProxyConfigFromMaven>false</npmInheritsProxyConfigFromMaven> | ||
1034 | </configuration> | ||
1035 | </execution> | ||
1036 | </executions> | ||
1037 | </plugin> | ||
1038 | <plugin> | ||
1039 | <groupId>pl.project13.maven</groupId> | ||
1040 | <artifactId>git-commit-id-plugin</artifactId> | ||
1041 | </plugin> | ||
1042 | </plugins> | ||
1043 | </build> | ||
1044 | <properties> | ||
1045 | <!-- default Spring profiles --> | ||
1046 | <spring.profiles.active>prod${profile.swagger}${profile.no-liquibase}</spring.profiles.active> | ||
1047 | </properties> | ||
1048 | </profile> | ||
1049 | <profile> | ||
1050 | <id>war</id> | ||
1051 | <build> | ||
1052 | <plugins> | ||
1053 | <plugin> | ||
1054 | <groupId>org.apache.maven.plugins</groupId> | ||
1055 | <artifactId>maven-war-plugin</artifactId> | ||
1056 | </plugin> | ||
1057 | </plugins> | ||
1058 | </build> | ||
1059 | </profile> | ||
1060 | <profile> | ||
1061 | <!-- | ||
1062 | Profile for applying IDE-specific configuration. | ||
1063 | At the moment it configures MapStruct and Hibernate JPA Metamodel Generator, which you need when working | ||
1064 | with DTOs and entity filtering. | ||
1065 | --> | ||
1066 | <id>IDE</id> | ||
1067 | <dependencies> | ||
1068 | <dependency> | ||
1069 | <groupId>org.mapstruct</groupId> | ||
1070 | <artifactId>mapstruct-processor</artifactId> | ||
1071 | </dependency> | ||
1072 | <dependency> | ||
1073 | <groupId>org.hibernate</groupId> | ||
1074 | <artifactId>hibernate-jpamodelgen</artifactId> | ||
1075 | </dependency> | ||
1076 | </dependencies> | ||
1077 | </profile> | ||
1078 | <profile> | ||
1079 | <!-- This is automatically activated when working in Eclipse --> | ||
1080 | <id>eclipse</id> | ||
1081 | <activation> | ||
1082 | <property> | ||
1083 | <name>m2e.version</name> | ||
1084 | </property> | ||
1085 | </activation> | ||
1086 | <dependencies> | ||
1087 | <!-- The following dependency is added due to issue #9175--> | ||
1088 | <dependency> | ||
1089 | <groupId>org.springframework.boot</groupId> | ||
1090 | <artifactId>spring-boot-starter-undertow</artifactId> | ||
1091 | </dependency> | ||
1092 | </dependencies> | ||
1093 | <build> | ||
1094 | <pluginManagement> | ||
1095 | <plugins> | ||
1096 | <!-- | ||
1097 | This plugin's configuration is used to store Eclipse m2e settings only. | ||
1098 | It has no influence on the Maven build itself. | ||
1099 | Remove when the m2e plugin can correctly bind to Maven lifecycle | ||
1100 | --> | ||
1101 | <plugin> | ||
1102 | <groupId>org.eclipse.m2e</groupId> | ||
1103 | <artifactId>lifecycle-mapping</artifactId> | ||
1104 | <version>${lifecycle-mapping.version}</version> | ||
1105 | <configuration> | ||
1106 | <lifecycleMappingMetadata> | ||
1107 | <pluginExecutions> | ||
1108 | <pluginExecution> | ||
1109 | <pluginExecutionFilter> | ||
1110 | <groupId>org.jacoco</groupId> | ||
1111 | <artifactId> | ||
1112 | jacoco-maven-plugin | ||
1113 | </artifactId> | ||
1114 | <versionRange> | ||
1115 | ${jacoco-maven-plugin.version} | ||
1116 | </versionRange> | ||
1117 | <goals> | ||
1118 | <goal>prepare-agent</goal> | ||
1119 | </goals> | ||
1120 | </pluginExecutionFilter> | ||
1121 | <action> | ||
1122 | <ignore/> | ||
1123 | </action> | ||
1124 | </pluginExecution> | ||
1125 | <pluginExecution> | ||
1126 | <pluginExecutionFilter> | ||
1127 | <groupId>com.github.eirslett</groupId> | ||
1128 | <artifactId>frontend-maven-plugin</artifactId> | ||
1129 | <versionRange>${frontend-maven-plugin.version}</versionRange> | ||
1130 | <goals> | ||
1131 | <goal>install-node-and-npm</goal> | ||
1132 | <goal>npm</goal> | ||
1133 | </goals> | ||
1134 | </pluginExecutionFilter> | ||
1135 | <action> | ||
1136 | <ignore/> | ||
1137 | </action> | ||
1138 | </pluginExecution> | ||
1139 | </pluginExecutions> | ||
1140 | </lifecycleMappingMetadata> | ||
1141 | </configuration> | ||
1142 | </plugin> | ||
1143 | </plugins> | ||
1144 | </pluginManagement> | ||
1145 | </build> | ||
1146 | </profile> | ||
1147 | <!-- jhipster-needle-maven-add-profile --> | ||
1148 | </profiles> | ||
1149 | </project> |
File postcss.config.js added (mode: 100644) (index 0000000..a26de7e) | |||
1 | module.exports = { | ||
2 | plugins: [ | ||
3 | require('autoprefixer') | ||
4 | ] | ||
5 | } |
File proxy.conf.json added (mode: 100644) (index 0000000..3bfe56a) | |||
1 | { | ||
2 | "*": { | ||
3 | "target": "http://localhost:8080", | ||
4 | "secure": false, | ||
5 | "loglevel": "debug" | ||
6 | } | ||
7 | } |
File sonar-project.properties added (mode: 100644) (index 0000000..6023e77) | |||
1 | sonar.projectKey=honlap | ||
2 | sonar.projectName=honlap generated by jhipster | ||
3 | sonar.projectVersion=1.0 | ||
4 | |||
5 | sonar.sources=src/main/ | ||
6 | sonar.host.url=http://localhost:9001 | ||
7 | |||
8 | sonar.tests=src/test/ | ||
9 | sonar.coverage.jacoco.xmlReportPaths=target/jacoco/test/jacoco.xml,target/jacoco/integrationTest/jacoco.xml | ||
10 | sonar.java.codeCoveragePlugin=jacoco | ||
11 | sonar.junit.reportPaths=target/test-results/test,target/test-results/integrationTest | ||
12 | sonar.testExecutionReportPaths=target/test-results/jest/TESTS-results-sonar.xml | ||
13 | sonar.typescript.lcov.reportPaths=target/test-results/lcov.info | ||
14 | |||
15 | sonar.sourceEncoding=UTF-8 | ||
16 | sonar.exclusions=src/main/webapp/content/**/*.*, src/main/webapp/i18n/*.js, target/classes/static/**/*.* | ||
17 | |||
18 | sonar.issue.ignore.multicriteria=S3437,S4502,S4684,UndocumentedApi,BoldAndItalicTagsCheck | ||
19 | # Rule https://sonarcloud.io/coding_rules?open=squid%3AS3437&rule_key=squid%3AS3437 is ignored, as a JPA-managed field cannot be transient | ||
20 | sonar.issue.ignore.multicriteria.S3437.resourceKey=src/main/java/**/* | ||
21 | sonar.issue.ignore.multicriteria.S3437.ruleKey=squid:S3437 | ||
22 | # Rule https://sonarcloud.io/coding_rules?open=squid%3AUndocumentedApi&rule_key=squid%3AUndocumentedApi is ignored, as we want to follow "clean code" guidelines and classes, methods and arguments names should be self-explanatory | ||
23 | sonar.issue.ignore.multicriteria.UndocumentedApi.resourceKey=src/main/java/**/* | ||
24 | sonar.issue.ignore.multicriteria.UndocumentedApi.ruleKey=squid:UndocumentedApi | ||
25 | # Rule https://sonarcloud.io/coding_rules?open=squid%3AS4502&rule_key=squid%3AS4502 is ignored, as for JWT tokens we are not subject to CSRF attack | ||
26 | sonar.issue.ignore.multicriteria.S4502.resourceKey=src/main/java/**/* | ||
27 | sonar.issue.ignore.multicriteria.S4502.ruleKey=squid:S4502 | ||
28 | # Rule https://sonarcloud.io/coding_rules?open=squid%3AS4684&rule_key=squid%3AS4684 | ||
29 | sonar.issue.ignore.multicriteria.S4684.resourceKey=src/main/java/**/* | ||
30 | sonar.issue.ignore.multicriteria.S4684.ruleKey=squid:S4684 | ||
31 | # Rule https://sonarcloud.io/coding_rules?open=Web%3ABoldAndItalicTagsCheck&rule_key=Web%3ABoldAndItalicTagsCheck is ignored. Even if we agree that using the "i" tag is an awful practice, this is what is recommended by http://fontawesome.io/examples/ | ||
32 | sonar.issue.ignore.multicriteria.BoldAndItalicTagsCheck.resourceKey=src/main/webapp/app/**/*.* | ||
33 | sonar.issue.ignore.multicriteria.BoldAndItalicTagsCheck.ruleKey=Web:BoldAndItalicTagsCheck |
File src/main/docker/app.yml added (mode: 100644) (index 0000000..ec96436) | |||
1 | version: '2' | ||
2 | services: | ||
3 | honlap-app: | ||
4 | image: honlap | ||
5 | environment: | ||
6 | - _JAVA_OPTIONS=-Xmx512m -Xms256m | ||
7 | - SPRING_PROFILES_ACTIVE=prod,swagger | ||
8 | - MANAGEMENT_METRICS_EXPORT_PROMETHEUS_ENABLED=true | ||
9 | - SPRING_DATASOURCE_URL=jdbc:postgresql://honlap-postgresql:5432/honlap | ||
10 | - JHIPSTER_SLEEP=30 # gives time for other services to boot before the application | ||
11 | ports: | ||
12 | - 8080:8080 | ||
13 | honlap-postgresql: | ||
14 | extends: | ||
15 | file: postgresql.yml | ||
16 | service: honlap-postgresql |
File src/main/docker/grafana/provisioning/dashboards/JVM.json added (mode: 100644) (index 0000000..5104abc) | |||
1 | { | ||
2 | "annotations": { | ||
3 | "list": [ | ||
4 | { | ||
5 | "builtIn": 1, | ||
6 | "datasource": "-- Grafana --", | ||
7 | "enable": true, | ||
8 | "hide": true, | ||
9 | "iconColor": "rgba(0, 211, 255, 1)", | ||
10 | "limit": 100, | ||
11 | "name": "Annotations & Alerts", | ||
12 | "showIn": 0, | ||
13 | "type": "dashboard" | ||
14 | }, | ||
15 | { | ||
16 | "datasource": "Prometheus", | ||
17 | "enable": true, | ||
18 | "expr": "resets(process_uptime_seconds{application=\"$application\", instance=\"$instance\"}[1m]) > 0", | ||
19 | "iconColor": "rgba(255, 96, 96, 1)", | ||
20 | "name": "Restart Detection", | ||
21 | "showIn": 0, | ||
22 | "step": "1m", | ||
23 | "tagKeys": "restart-tag", | ||
24 | "textFormat": "uptime reset", | ||
25 | "titleFormat": "Restart" | ||
26 | } | ||
27 | ] | ||
28 | }, | ||
29 | "description": "Dashboard for Micrometer instrumented applications (Java, Spring Boot, Micronaut)", | ||
30 | "editable": true, | ||
31 | "gnetId": 4701, | ||
32 | "graphTooltip": 1, | ||
33 | "iteration": 1553765841423, | ||
34 | "links": [], | ||
35 | "panels": [ | ||
36 | { | ||
37 | "content": "\n# Acknowledgments\n\nThank you to [Michael Weirauch](https://twitter.com/emwexx) for creating this dashboard: see original JVM (Micrometer) dashboard at [https://grafana.com/dashboards/4701](https://grafana.com/dashboards/4701)\n\n\n\n", | ||
38 | "gridPos": { | ||
39 | "h": 3, | ||
40 | "w": 24, | ||
41 | "x": 0, | ||
42 | "y": 0 | ||
43 | }, | ||
44 | "id": 141, | ||
45 | "links": [], | ||
46 | "mode": "markdown", | ||
47 | "timeFrom": null, | ||
48 | "timeShift": null, | ||
49 | "title": "Acknowledgments", | ||
50 | "type": "text" | ||
51 | }, | ||
52 | { | ||
53 | "collapsed": false, | ||
54 | "gridPos": { | ||
55 | "h": 1, | ||
56 | "w": 24, | ||
57 | "x": 0, | ||
58 | "y": 3 | ||
59 | }, | ||
60 | "id": 125, | ||
61 | "panels": [], | ||
62 | "repeat": null, | ||
63 | "title": "Quick Facts", | ||
64 | "type": "row" | ||
65 | }, | ||
66 | { | ||
67 | "cacheTimeout": null, | ||
68 | "colorBackground": false, | ||
69 | "colorValue": true, | ||
70 | "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], | ||
71 | "datasource": "Prometheus", | ||
72 | "decimals": 1, | ||
73 | "editable": true, | ||
74 | "error": false, | ||
75 | "format": "s", | ||
76 | "gauge": { | ||
77 | "maxValue": 100, | ||
78 | "minValue": 0, | ||
79 | "show": false, | ||
80 | "thresholdLabels": false, | ||
81 | "thresholdMarkers": true | ||
82 | }, | ||
83 | "gridPos": { | ||
84 | "h": 3, | ||
85 | "w": 6, | ||
86 | "x": 0, | ||
87 | "y": 4 | ||
88 | }, | ||
89 | "height": "", | ||
90 | "id": 63, | ||
91 | "interval": null, | ||
92 | "links": [], | ||
93 | "mappingType": 1, | ||
94 | "mappingTypes": [ | ||
95 | { | ||
96 | "name": "value to text", | ||
97 | "value": 1 | ||
98 | }, | ||
99 | { | ||
100 | "name": "range to text", | ||
101 | "value": 2 | ||
102 | } | ||
103 | ], | ||
104 | "maxDataPoints": 100, | ||
105 | "nullPointMode": "connected", | ||
106 | "nullText": null, | ||
107 | "postfix": "", | ||
108 | "postfixFontSize": "50%", | ||
109 | "prefix": "", | ||
110 | "prefixFontSize": "70%", | ||
111 | "rangeMaps": [ | ||
112 | { | ||
113 | "from": "null", | ||
114 | "text": "N/A", | ||
115 | "to": "null" | ||
116 | } | ||
117 | ], | ||
118 | "sparkline": { | ||
119 | "fillColor": "rgba(31, 118, 189, 0.18)", | ||
120 | "full": false, | ||
121 | "lineColor": "rgb(31, 120, 193)", | ||
122 | "show": false | ||
123 | }, | ||
124 | "tableColumn": "", | ||
125 | "targets": [ | ||
126 | { | ||
127 | "expr": "process_uptime_seconds{application=\"$application\", instance=\"$instance\"}", | ||
128 | "format": "time_series", | ||
129 | "intervalFactor": 2, | ||
130 | "legendFormat": "", | ||
131 | "metric": "", | ||
132 | "refId": "A", | ||
133 | "step": 14400 | ||
134 | } | ||
135 | ], | ||
136 | "thresholds": "", | ||
137 | "title": "Uptime", | ||
138 | "type": "singlestat", | ||
139 | "valueFontSize": "80%", | ||
140 | "valueMaps": [ | ||
141 | { | ||
142 | "op": "=", | ||
143 | "text": "N/A", | ||
144 | "value": "null" | ||
145 | } | ||
146 | ], | ||
147 | "valueName": "current" | ||
148 | }, | ||
149 | { | ||
150 | "cacheTimeout": null, | ||
151 | "colorBackground": false, | ||
152 | "colorValue": true, | ||
153 | "colors": ["rgba(245, 54, 54, 0.9)", "rgba(237, 129, 40, 0.89)", "rgba(50, 172, 45, 0.97)"], | ||
154 | "datasource": "Prometheus", | ||
155 | "decimals": null, | ||
156 | "editable": true, | ||
157 | "error": false, | ||
158 | "format": "dateTimeAsIso", | ||
159 | "gauge": { | ||
160 | "maxValue": 100, | ||
161 | "minValue": 0, | ||
162 | "show": false, | ||
163 | "thresholdLabels": false, | ||
164 | "thresholdMarkers": true | ||
165 | }, | ||
166 | "gridPos": { | ||
167 | "h": 3, | ||
168 | "w": 6, | ||
169 | "x": 6, | ||
170 | "y": 4 | ||
171 | }, | ||
172 | "height": "", | ||
173 | "id": 92, | ||
174 | "interval": null, | ||
175 | "links": [], | ||
176 | "mappingType": 1, | ||
177 | "mappingTypes": [ | ||
178 | { | ||
179 | "name": "value to text", | ||
180 | "value": 1 | ||
181 | }, | ||
182 | { | ||
183 | "name": "range to text", | ||
184 | "value": 2 | ||
185 | } | ||
186 | ], | ||
187 | "maxDataPoints": 100, | ||
188 | "nullPointMode": "connected", | ||
189 | "nullText": null, | ||
190 | "postfix": "", | ||
191 | "postfixFontSize": "50%", | ||
192 | "prefix": "", | ||
193 | "prefixFontSize": "70%", | ||
194 | "rangeMaps": [ | ||
195 | { | ||
196 | "from": "null", | ||
197 | "text": "N/A", | ||
198 | "to": "null" | ||
199 | } | ||
200 | ], | ||
201 | "sparkline": { | ||
202 | "fillColor": "rgba(31, 118, 189, 0.18)", | ||
203 | "full": false, | ||
204 | "lineColor": "rgb(31, 120, 193)", | ||
205 | "show": false | ||
206 | }, | ||
207 | "tableColumn": "", | ||
208 | "targets": [ | ||
209 | { | ||
210 | "expr": "process_start_time_seconds{application=\"$application\", instance=\"$instance\"}*1000", | ||
211 | "format": "time_series", | ||
212 | "intervalFactor": 2, | ||
213 | "legendFormat": "", | ||
214 | "metric": "", | ||
215 | "refId": "A", | ||
216 | "step": 14400 | ||
217 | } | ||
218 | ], | ||
219 | "thresholds": "", | ||
220 | "title": "Start time", | ||
221 | "type": "singlestat", | ||
222 | "valueFontSize": "70%", | ||
223 | "valueMaps": [ | ||
224 | { | ||
225 | "op": "=", | ||
226 | "text": "N/A", | ||
227 | "value": "null" | ||
228 | } | ||
229 | ], | ||
230 | "valueName": "current" | ||
231 | }, | ||
232 | { | ||
233 | "cacheTimeout": null, | ||
234 | "colorBackground": false, | ||
235 | "colorValue": true, | ||
236 | "colors": ["rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"], | ||
237 | "datasource": "Prometheus", | ||
238 | "decimals": 2, | ||
239 | "editable": true, | ||
240 | "error": false, | ||
241 | "format": "percent", | ||
242 | "gauge": { | ||
243 | "maxValue": 100, | ||
244 | "minValue": 0, | ||
245 | "show": false, | ||
246 | "thresholdLabels": false, | ||
247 | "thresholdMarkers": true | ||
248 | }, | ||
249 | "gridPos": { | ||
250 | "h": 3, | ||
251 | "w": 6, | ||
252 | "x": 12, | ||
253 | "y": 4 | ||
254 | }, | ||
255 | "id": 65, | ||
256 | "interval": null, | ||
257 | "links": [], | ||
258 | "mappingType": 1, | ||
259 | "mappingTypes": [ | ||
260 | { | ||
261 | "name": "value to text", | ||
262 | "value": 1 | ||
263 | }, | ||
264 | { | ||
265 | "name": "range to text", | ||
266 | "value": 2 | ||
267 | } | ||
268 | ], | ||
269 | "maxDataPoints": 100, | ||
270 | "nullPointMode": "connected", | ||
271 | "nullText": null, | ||
272 | "postfix": "", | ||
273 | "postfixFontSize": "50%", | ||
274 | "prefix": "", | ||
275 | "prefixFontSize": "70%", | ||
276 | "rangeMaps": [ | ||
277 | { | ||
278 | "from": "null", | ||
279 | "text": "N/A", | ||
280 | "to": "null" | ||
281 | } | ||
282 | ], | ||
283 | "sparkline": { | ||
284 | "fillColor": "rgba(31, 118, 189, 0.18)", | ||
285 | "full": false, | ||
286 | "lineColor": "rgb(31, 120, 193)", | ||
287 | "show": false | ||
288 | }, | ||
289 | "tableColumn": "", | ||
290 | "targets": [ | ||
291 | { | ||
292 | "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"heap\"})", | ||
293 | "format": "time_series", | ||
294 | "intervalFactor": 2, | ||
295 | "legendFormat": "", | ||
296 | "refId": "A", | ||
297 | "step": 14400 | ||
298 | } | ||
299 | ], | ||
300 | "thresholds": "70,90", | ||
301 | "title": "Heap used", | ||
302 | "type": "singlestat", | ||
303 | "valueFontSize": "80%", | ||
304 | "valueMaps": [ | ||
305 | { | ||
306 | "op": "=", | ||
307 | "text": "N/A", | ||
308 | "value": "null" | ||
309 | } | ||
310 | ], | ||
311 | "valueName": "current" | ||
312 | }, | ||
313 | { | ||
314 | "cacheTimeout": null, | ||
315 | "colorBackground": false, | ||
316 | "colorValue": true, | ||
317 | "colors": ["rgba(50, 172, 45, 0.97)", "rgba(237, 129, 40, 0.89)", "rgba(245, 54, 54, 0.9)"], | ||
318 | "datasource": "Prometheus", | ||
319 | "decimals": 2, | ||
320 | "editable": true, | ||
321 | "error": false, | ||
322 | "format": "percent", | ||
323 | "gauge": { | ||
324 | "maxValue": 100, | ||
325 | "minValue": 0, | ||
326 | "show": false, | ||
327 | "thresholdLabels": false, | ||
328 | "thresholdMarkers": true | ||
329 | }, | ||
330 | "gridPos": { | ||
331 | "h": 3, | ||
332 | "w": 6, | ||
333 | "x": 18, | ||
334 | "y": 4 | ||
335 | }, | ||
336 | "id": 75, | ||
337 | "interval": null, | ||
338 | "links": [], | ||
339 | "mappingType": 2, | ||
340 | "mappingTypes": [ | ||
341 | { | ||
342 | "name": "value to text", | ||
343 | "value": 1 | ||
344 | }, | ||
345 | { | ||
346 | "name": "range to text", | ||
347 | "value": 2 | ||
348 | } | ||
349 | ], | ||
350 | "maxDataPoints": 100, | ||
351 | "nullPointMode": "connected", | ||
352 | "nullText": null, | ||
353 | "postfix": "", | ||
354 | "postfixFontSize": "50%", | ||
355 | "prefix": "", | ||
356 | "prefixFontSize": "70%", | ||
357 | "rangeMaps": [ | ||
358 | { | ||
359 | "from": "null", | ||
360 | "text": "N/A", | ||
361 | "to": "null" | ||
362 | }, | ||
363 | { | ||
364 | "from": "-99999999999999999999999999999999", | ||
365 | "text": "N/A", | ||
366 | "to": "0" | ||
367 | } | ||
368 | ], | ||
369 | "sparkline": { | ||
370 | "fillColor": "rgba(31, 118, 189, 0.18)", | ||
371 | "full": false, | ||
372 | "lineColor": "rgb(31, 120, 193)", | ||
373 | "show": false | ||
374 | }, | ||
375 | "tableColumn": "", | ||
376 | "targets": [ | ||
377 | { | ||
378 | "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})*100/sum(jvm_memory_max_bytes{application=\"$application\",instance=\"$instance\", area=\"nonheap\"})", | ||
379 | "format": "time_series", | ||
380 | "intervalFactor": 2, | ||
381 | "legendFormat": "", | ||
382 | "refId": "A", | ||
383 | "step": 14400 | ||
384 | } | ||
385 | ], | ||
386 | "thresholds": "70,90", | ||
387 | "title": "Non-Heap used", | ||
388 | "type": "singlestat", | ||
389 | "valueFontSize": "80%", | ||
390 | "valueMaps": [ | ||
391 | { | ||
392 | "op": "=", | ||
393 | "text": "N/A", | ||
394 | "value": "null" | ||
395 | }, | ||
396 | { | ||
397 | "op": "=", | ||
398 | "text": "x", | ||
399 | "value": "" | ||
400 | } | ||
401 | ], | ||
402 | "valueName": "current" | ||
403 | }, | ||
404 | { | ||
405 | "collapsed": false, | ||
406 | "gridPos": { | ||
407 | "h": 1, | ||
408 | "w": 24, | ||
409 | "x": 0, | ||
410 | "y": 7 | ||
411 | }, | ||
412 | "id": 126, | ||
413 | "panels": [], | ||
414 | "repeat": null, | ||
415 | "title": "I/O Overview", | ||
416 | "type": "row" | ||
417 | }, | ||
418 | { | ||
419 | "aliasColors": {}, | ||
420 | "bars": false, | ||
421 | "dashLength": 10, | ||
422 | "dashes": false, | ||
423 | "datasource": "Prometheus", | ||
424 | "fill": 1, | ||
425 | "gridPos": { | ||
426 | "h": 7, | ||
427 | "w": 8, | ||
428 | "x": 0, | ||
429 | "y": 8 | ||
430 | }, | ||
431 | "id": 111, | ||
432 | "legend": { | ||
433 | "avg": false, | ||
434 | "current": true, | ||
435 | "max": false, | ||
436 | "min": false, | ||
437 | "show": true, | ||
438 | "total": false, | ||
439 | "values": true | ||
440 | }, | ||
441 | "lines": true, | ||
442 | "linewidth": 1, | ||
443 | "links": [], | ||
444 | "nullPointMode": "null", | ||
445 | "paceLength": 10, | ||
446 | "percentage": false, | ||
447 | "pointradius": 5, | ||
448 | "points": false, | ||
449 | "renderer": "flot", | ||
450 | "seriesOverrides": [], | ||
451 | "spaceLength": 10, | ||
452 | "stack": false, | ||
453 | "steppedLine": false, | ||
454 | "targets": [ | ||
455 | { | ||
456 | "expr": "sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\"}[1m]))", | ||
457 | "format": "time_series", | ||
458 | "intervalFactor": 1, | ||
459 | "legendFormat": "HTTP", | ||
460 | "refId": "A" | ||
461 | } | ||
462 | ], | ||
463 | "thresholds": [], | ||
464 | "timeFrom": null, | ||
465 | "timeRegions": [], | ||
466 | "timeShift": null, | ||
467 | "title": "Rate", | ||
468 | "tooltip": { | ||
469 | "shared": true, | ||
470 | "sort": 0, | ||
471 | "value_type": "individual" | ||
472 | }, | ||
473 | "type": "graph", | ||
474 | "xaxis": { | ||
475 | "buckets": null, | ||
476 | "mode": "time", | ||
477 | "name": null, | ||
478 | "show": true, | ||
479 | "values": [] | ||
480 | }, | ||
481 | "yaxes": [ | ||
482 | { | ||
483 | "decimals": null, | ||
484 | "format": "ops", | ||
485 | "label": null, | ||
486 | "logBase": 1, | ||
487 | "max": null, | ||
488 | "min": "0", | ||
489 | "show": true | ||
490 | }, | ||
491 | { | ||
492 | "format": "short", | ||
493 | "label": null, | ||
494 | "logBase": 1, | ||
495 | "max": null, | ||
496 | "min": null, | ||
497 | "show": true | ||
498 | } | ||
499 | ], | ||
500 | "yaxis": { | ||
501 | "align": false, | ||
502 | "alignLevel": null | ||
503 | } | ||
504 | }, | ||
505 | { | ||
506 | "aliasColors": { | ||
507 | "HTTP": "#890f02", | ||
508 | "HTTP - 5xx": "#bf1b00" | ||
509 | }, | ||
510 | "bars": false, | ||
511 | "dashLength": 10, | ||
512 | "dashes": false, | ||
513 | "datasource": "Prometheus", | ||
514 | "fill": 1, | ||
515 | "gridPos": { | ||
516 | "h": 7, | ||
517 | "w": 8, | ||
518 | "x": 8, | ||
519 | "y": 8 | ||
520 | }, | ||
521 | "id": 112, | ||
522 | "legend": { | ||
523 | "avg": false, | ||
524 | "current": true, | ||
525 | "max": false, | ||
526 | "min": false, | ||
527 | "show": true, | ||
528 | "total": false, | ||
529 | "values": true | ||
530 | }, | ||
531 | "lines": true, | ||
532 | "linewidth": 1, | ||
533 | "links": [], | ||
534 | "nullPointMode": "null", | ||
535 | "paceLength": 10, | ||
536 | "percentage": false, | ||
537 | "pointradius": 5, | ||
538 | "points": false, | ||
539 | "renderer": "flot", | ||
540 | "seriesOverrides": [], | ||
541 | "spaceLength": 10, | ||
542 | "stack": false, | ||
543 | "steppedLine": false, | ||
544 | "targets": [ | ||
545 | { | ||
546 | "expr": "sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\", status=~\"5..\"}[1m]))", | ||
547 | "format": "time_series", | ||
548 | "intervalFactor": 1, | ||
549 | "legendFormat": "HTTP - 5xx", | ||
550 | "refId": "A" | ||
551 | } | ||
552 | ], | ||
553 | "thresholds": [], | ||
554 | "timeFrom": null, | ||
555 | "timeRegions": [], | ||
556 | "timeShift": null, | ||
557 | "title": "Errors", | ||
558 | "tooltip": { | ||
559 | "shared": true, | ||
560 | "sort": 0, | ||
561 | "value_type": "individual" | ||
562 | }, | ||
563 | "type": "graph", | ||
564 | "xaxis": { | ||
565 | "buckets": null, | ||
566 | "mode": "time", | ||
567 | "name": null, | ||
568 | "show": true, | ||
569 | "values": [] | ||
570 | }, | ||
571 | "yaxes": [ | ||
572 | { | ||
573 | "decimals": null, | ||
574 | "format": "ops", | ||
575 | "label": null, | ||
576 | "logBase": 1, | ||
577 | "max": null, | ||
578 | "min": "0", | ||
579 | "show": true | ||
580 | }, | ||
581 | { | ||
582 | "format": "short", | ||
583 | "label": null, | ||
584 | "logBase": 1, | ||
585 | "max": null, | ||
586 | "min": null, | ||
587 | "show": true | ||
588 | } | ||
589 | ], | ||
590 | "yaxis": { | ||
591 | "align": false, | ||
592 | "alignLevel": null | ||
593 | } | ||
594 | }, | ||
595 | { | ||
596 | "aliasColors": {}, | ||
597 | "bars": false, | ||
598 | "dashLength": 10, | ||
599 | "dashes": false, | ||
600 | "datasource": "Prometheus", | ||
601 | "fill": 1, | ||
602 | "gridPos": { | ||
603 | "h": 7, | ||
604 | "w": 8, | ||
605 | "x": 16, | ||
606 | "y": 8 | ||
607 | }, | ||
608 | "id": 113, | ||
609 | "legend": { | ||
610 | "avg": false, | ||
611 | "current": true, | ||
612 | "max": false, | ||
613 | "min": false, | ||
614 | "show": true, | ||
615 | "total": false, | ||
616 | "values": true | ||
617 | }, | ||
618 | "lines": true, | ||
619 | "linewidth": 1, | ||
620 | "links": [], | ||
621 | "nullPointMode": "null", | ||
622 | "paceLength": 10, | ||
623 | "percentage": false, | ||
624 | "pointradius": 5, | ||
625 | "points": false, | ||
626 | "renderer": "flot", | ||
627 | "seriesOverrides": [], | ||
628 | "spaceLength": 10, | ||
629 | "stack": false, | ||
630 | "steppedLine": false, | ||
631 | "targets": [ | ||
632 | { | ||
633 | "expr": "sum(rate(http_server_requests_seconds_sum{application=\"$application\", instance=\"$instance\", status!~\"5..\"}[1m]))/sum(rate(http_server_requests_seconds_count{application=\"$application\", instance=\"$instance\", status!~\"5..\"}[1m]))", | ||
634 | "format": "time_series", | ||
635 | "hide": false, | ||
636 | "intervalFactor": 1, | ||
637 | "legendFormat": "HTTP - AVG", | ||
638 | "refId": "A" | ||
639 | }, | ||
640 | { | ||
641 | "expr": "max(http_server_requests_seconds_max{application=\"$application\", instance=\"$instance\", status!~\"5..\"})", | ||
642 | "format": "time_series", | ||
643 | "hide": false, | ||
644 | "intervalFactor": 1, | ||
645 | "legendFormat": "HTTP - MAX", | ||
646 | "refId": "B" | ||
647 | } | ||
648 | ], | ||
649 | "thresholds": [], | ||
650 | "timeFrom": null, | ||
651 | "timeRegions": [], | ||
652 | "timeShift": null, | ||
653 | "title": "Duration", | ||
654 | "tooltip": { | ||
655 | "shared": true, | ||
656 | "sort": 0, | ||
657 | "value_type": "individual" | ||
658 | }, | ||
659 | "type": "graph", | ||
660 | "xaxis": { | ||
661 | "buckets": null, | ||
662 | "mode": "time", | ||
663 | "name": null, | ||
664 | "show": true, | ||
665 | "values": [] | ||
666 | }, | ||
667 | "yaxes": [ | ||
668 | { | ||
669 | "format": "s", | ||
670 | "label": null, | ||
671 | "logBase": 1, | ||
672 | "max": null, | ||
673 | "min": "0", | ||
674 | "show": true | ||
675 | }, | ||
676 | { | ||
677 | "format": "short", | ||
678 | "label": null, | ||
679 | "logBase": 1, | ||
680 | "max": null, | ||
681 | "min": null, | ||
682 | "show": true | ||
683 | } | ||
684 | ], | ||
685 | "yaxis": { | ||
686 | "align": false, | ||
687 | "alignLevel": null | ||
688 | } | ||
689 | }, | ||
690 | { | ||
691 | "collapsed": false, | ||
692 | "gridPos": { | ||
693 | "h": 1, | ||
694 | "w": 24, | ||
695 | "x": 0, | ||
696 | "y": 15 | ||
697 | }, | ||
698 | "id": 127, | ||
699 | "panels": [], | ||
700 | "repeat": null, | ||
701 | "title": "JVM Memory", | ||
702 | "type": "row" | ||
703 | }, | ||
704 | { | ||
705 | "aliasColors": {}, | ||
706 | "bars": false, | ||
707 | "dashLength": 10, | ||
708 | "dashes": false, | ||
709 | "datasource": "Prometheus", | ||
710 | "editable": true, | ||
711 | "error": false, | ||
712 | "fill": 1, | ||
713 | "grid": { | ||
714 | "leftLogBase": 1, | ||
715 | "leftMax": null, | ||
716 | "leftMin": null, | ||
717 | "rightLogBase": 1, | ||
718 | "rightMax": null, | ||
719 | "rightMin": null | ||
720 | }, | ||
721 | "gridPos": { | ||
722 | "h": 7, | ||
723 | "w": 8, | ||
724 | "x": 0, | ||
725 | "y": 16 | ||
726 | }, | ||
727 | "id": 24, | ||
728 | "legend": { | ||
729 | "avg": false, | ||
730 | "current": true, | ||
731 | "max": true, | ||
732 | "min": false, | ||
733 | "show": true, | ||
734 | "total": false, | ||
735 | "values": true | ||
736 | }, | ||
737 | "lines": true, | ||
738 | "linewidth": 1, | ||
739 | "links": [], | ||
740 | "nullPointMode": "null", | ||
741 | "paceLength": 10, | ||
742 | "percentage": false, | ||
743 | "pointradius": 5, | ||
744 | "points": false, | ||
745 | "renderer": "flot", | ||
746 | "seriesOverrides": [], | ||
747 | "spaceLength": 10, | ||
748 | "stack": false, | ||
749 | "steppedLine": false, | ||
750 | "targets": [ | ||
751 | { | ||
752 | "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})", | ||
753 | "format": "time_series", | ||
754 | "intervalFactor": 2, | ||
755 | "legendFormat": "used", | ||
756 | "metric": "", | ||
757 | "refId": "A", | ||
758 | "step": 2400 | ||
759 | }, | ||
760 | { | ||
761 | "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})", | ||
762 | "format": "time_series", | ||
763 | "intervalFactor": 2, | ||
764 | "legendFormat": "committed", | ||
765 | "refId": "B", | ||
766 | "step": 2400 | ||
767 | }, | ||
768 | { | ||
769 | "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"})", | ||
770 | "format": "time_series", | ||
771 | "intervalFactor": 2, | ||
772 | "legendFormat": "max", | ||
773 | "refId": "C", | ||
774 | "step": 2400 | ||
775 | } | ||
776 | ], | ||
777 | "thresholds": [], | ||
778 | "timeFrom": null, | ||
779 | "timeRegions": [], | ||
780 | "timeShift": null, | ||
781 | "title": "JVM Heap", | ||
782 | "tooltip": { | ||
783 | "msResolution": false, | ||
784 | "shared": true, | ||
785 | "sort": 0, | ||
786 | "value_type": "cumulative" | ||
787 | }, | ||
788 | "type": "graph", | ||
789 | "x-axis": true, | ||
790 | "xaxis": { | ||
791 | "buckets": null, | ||
792 | "mode": "time", | ||
793 | "name": null, | ||
794 | "show": true, | ||
795 | "values": [] | ||
796 | }, | ||
797 | "y-axis": true, | ||
798 | "y_formats": ["mbytes", "short"], | ||
799 | "yaxes": [ | ||
800 | { | ||
801 | "format": "bytes", | ||
802 | "label": null, | ||
803 | "logBase": 1, | ||
804 | "max": null, | ||
805 | "min": 0, | ||
806 | "show": true | ||
807 | }, | ||
808 | { | ||
809 | "format": "short", | ||
810 | "label": null, | ||
811 | "logBase": 1, | ||
812 | "max": null, | ||
813 | "min": null, | ||
814 | "show": true | ||
815 | } | ||
816 | ], | ||
817 | "yaxis": { | ||
818 | "align": false, | ||
819 | "alignLevel": null | ||
820 | } | ||
821 | }, | ||
822 | { | ||
823 | "aliasColors": {}, | ||
824 | "bars": false, | ||
825 | "dashLength": 10, | ||
826 | "dashes": false, | ||
827 | "datasource": "Prometheus", | ||
828 | "editable": true, | ||
829 | "error": false, | ||
830 | "fill": 1, | ||
831 | "grid": { | ||
832 | "leftLogBase": 1, | ||
833 | "leftMax": null, | ||
834 | "leftMin": null, | ||
835 | "rightLogBase": 1, | ||
836 | "rightMax": null, | ||
837 | "rightMin": null | ||
838 | }, | ||
839 | "gridPos": { | ||
840 | "h": 7, | ||
841 | "w": 8, | ||
842 | "x": 8, | ||
843 | "y": 16 | ||
844 | }, | ||
845 | "id": 25, | ||
846 | "legend": { | ||
847 | "avg": false, | ||
848 | "current": true, | ||
849 | "max": true, | ||
850 | "min": false, | ||
851 | "show": true, | ||
852 | "total": false, | ||
853 | "values": true | ||
854 | }, | ||
855 | "lines": true, | ||
856 | "linewidth": 1, | ||
857 | "links": [], | ||
858 | "nullPointMode": "null", | ||
859 | "paceLength": 10, | ||
860 | "percentage": false, | ||
861 | "pointradius": 5, | ||
862 | "points": false, | ||
863 | "renderer": "flot", | ||
864 | "seriesOverrides": [], | ||
865 | "spaceLength": 10, | ||
866 | "stack": false, | ||
867 | "steppedLine": false, | ||
868 | "targets": [ | ||
869 | { | ||
870 | "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})", | ||
871 | "format": "time_series", | ||
872 | "interval": "", | ||
873 | "intervalFactor": 2, | ||
874 | "legendFormat": "used", | ||
875 | "metric": "", | ||
876 | "refId": "A", | ||
877 | "step": 2400 | ||
878 | }, | ||
879 | { | ||
880 | "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})", | ||
881 | "format": "time_series", | ||
882 | "intervalFactor": 2, | ||
883 | "legendFormat": "committed", | ||
884 | "refId": "B", | ||
885 | "step": 2400 | ||
886 | }, | ||
887 | { | ||
888 | "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"})", | ||
889 | "format": "time_series", | ||
890 | "intervalFactor": 2, | ||
891 | "legendFormat": "max", | ||
892 | "refId": "C", | ||
893 | "step": 2400 | ||
894 | } | ||
895 | ], | ||
896 | "thresholds": [], | ||
897 | "timeFrom": null, | ||
898 | "timeRegions": [], | ||
899 | "timeShift": null, | ||
900 | "title": "JVM Non-Heap", | ||
901 | "tooltip": { | ||
902 | "msResolution": false, | ||
903 | "shared": true, | ||
904 | "sort": 0, | ||
905 | "value_type": "cumulative" | ||
906 | }, | ||
907 | "type": "graph", | ||
908 | "x-axis": true, | ||
909 | "xaxis": { | ||
910 | "buckets": null, | ||
911 | "mode": "time", | ||
912 | "name": null, | ||
913 | "show": true, | ||
914 | "values": [] | ||
915 | }, | ||
916 | "y-axis": true, | ||
917 | "y_formats": ["mbytes", "short"], | ||
918 | "yaxes": [ | ||
919 | { | ||
920 | "format": "bytes", | ||
921 | "label": null, | ||
922 | "logBase": 1, | ||
923 | "max": null, | ||
924 | "min": 0, | ||
925 | "show": true | ||
926 | }, | ||
927 | { | ||
928 | "format": "short", | ||
929 | "label": null, | ||
930 | "logBase": 1, | ||
931 | "max": null, | ||
932 | "min": null, | ||
933 | "show": true | ||
934 | } | ||
935 | ], | ||
936 | "yaxis": { | ||
937 | "align": false, | ||
938 | "alignLevel": null | ||
939 | } | ||
940 | }, | ||
941 | { | ||
942 | "aliasColors": {}, | ||
943 | "bars": false, | ||
944 | "dashLength": 10, | ||
945 | "dashes": false, | ||
946 | "datasource": "Prometheus", | ||
947 | "editable": true, | ||
948 | "error": false, | ||
949 | "fill": 1, | ||
950 | "grid": { | ||
951 | "leftLogBase": 1, | ||
952 | "leftMax": null, | ||
953 | "leftMin": null, | ||
954 | "rightLogBase": 1, | ||
955 | "rightMax": null, | ||
956 | "rightMin": null | ||
957 | }, | ||
958 | "gridPos": { | ||
959 | "h": 7, | ||
960 | "w": 8, | ||
961 | "x": 16, | ||
962 | "y": 16 | ||
963 | }, | ||
964 | "id": 26, | ||
965 | "legend": { | ||
966 | "alignAsTable": false, | ||
967 | "avg": false, | ||
968 | "current": true, | ||
969 | "max": true, | ||
970 | "min": false, | ||
971 | "show": true, | ||
972 | "total": false, | ||
973 | "values": true | ||
974 | }, | ||
975 | "lines": true, | ||
976 | "linewidth": 1, | ||
977 | "links": [], | ||
978 | "nullPointMode": "null", | ||
979 | "paceLength": 10, | ||
980 | "percentage": false, | ||
981 | "pointradius": 5, | ||
982 | "points": false, | ||
983 | "renderer": "flot", | ||
984 | "seriesOverrides": [], | ||
985 | "spaceLength": 10, | ||
986 | "stack": false, | ||
987 | "steppedLine": false, | ||
988 | "targets": [ | ||
989 | { | ||
990 | "expr": "sum(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\"})", | ||
991 | "format": "time_series", | ||
992 | "intervalFactor": 2, | ||
993 | "legendFormat": "used", | ||
994 | "metric": "", | ||
995 | "refId": "A", | ||
996 | "step": 2400 | ||
997 | }, | ||
998 | { | ||
999 | "expr": "sum(jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\"})", | ||
1000 | "format": "time_series", | ||
1001 | "intervalFactor": 2, | ||
1002 | "legendFormat": "committed", | ||
1003 | "refId": "B", | ||
1004 | "step": 2400 | ||
1005 | }, | ||
1006 | { | ||
1007 | "expr": "sum(jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\"})", | ||
1008 | "format": "time_series", | ||
1009 | "intervalFactor": 2, | ||
1010 | "legendFormat": "max", | ||
1011 | "refId": "C", | ||
1012 | "step": 2400 | ||
1013 | }, | ||
1014 | { | ||
1015 | "expr": "process_memory_vss_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1016 | "format": "time_series", | ||
1017 | "hide": true, | ||
1018 | "intervalFactor": 2, | ||
1019 | "legendFormat": "vss", | ||
1020 | "metric": "", | ||
1021 | "refId": "D", | ||
1022 | "step": 2400 | ||
1023 | }, | ||
1024 | { | ||
1025 | "expr": "process_memory_rss_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1026 | "format": "time_series", | ||
1027 | "intervalFactor": 2, | ||
1028 | "legendFormat": "rss", | ||
1029 | "refId": "E", | ||
1030 | "step": 2400 | ||
1031 | }, | ||
1032 | { | ||
1033 | "expr": "process_memory_pss_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1034 | "format": "time_series", | ||
1035 | "intervalFactor": 2, | ||
1036 | "legendFormat": "pss", | ||
1037 | "refId": "F", | ||
1038 | "step": 2400 | ||
1039 | }, | ||
1040 | { | ||
1041 | "expr": "process_memory_swap_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1042 | "format": "time_series", | ||
1043 | "intervalFactor": 2, | ||
1044 | "legendFormat": "swap", | ||
1045 | "refId": "G", | ||
1046 | "step": 2400 | ||
1047 | }, | ||
1048 | { | ||
1049 | "expr": "process_memory_swappss_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1050 | "format": "time_series", | ||
1051 | "intervalFactor": 2, | ||
1052 | "legendFormat": "swappss", | ||
1053 | "refId": "H", | ||
1054 | "step": 2400 | ||
1055 | }, | ||
1056 | { | ||
1057 | "expr": "process_memory_pss_bytes{application=\"$application\", instance=\"$instance\"} + process_memory_swap_bytes{application=\"$application\", instance=\"$instance\"}", | ||
1058 | "format": "time_series", | ||
1059 | "intervalFactor": 2, | ||
1060 | "legendFormat": "phys (pss+swap)", | ||
1061 | "refId": "I", | ||
1062 | "step": 2400 | ||
1063 | } | ||
1064 | ], | ||
1065 | "thresholds": [], | ||
1066 | "timeFrom": null, | ||
1067 | "timeRegions": [], | ||
1068 | "timeShift": null, | ||
1069 | "title": "JVM Total", | ||
1070 | "tooltip": { | ||
1071 | "msResolution": false, | ||
1072 | "shared": true, | ||
1073 | "sort": 0, | ||
1074 | "value_type": "cumulative" | ||
1075 | }, | ||
1076 | "type": "graph", | ||
1077 | "x-axis": true, | ||
1078 | "xaxis": { | ||
1079 | "buckets": null, | ||
1080 | "mode": "time", | ||
1081 | "name": null, | ||
1082 | "show": true, | ||
1083 | "values": [] | ||
1084 | }, | ||
1085 | "y-axis": true, | ||
1086 | "y_formats": ["mbytes", "short"], | ||
1087 | "yaxes": [ | ||
1088 | { | ||
1089 | "format": "bytes", | ||
1090 | "label": "", | ||
1091 | "logBase": 1, | ||
1092 | "max": null, | ||
1093 | "min": 0, | ||
1094 | "show": true | ||
1095 | }, | ||
1096 | { | ||
1097 | "format": "short", | ||
1098 | "label": null, | ||
1099 | "logBase": 1, | ||
1100 | "max": null, | ||
1101 | "min": null, | ||
1102 | "show": true | ||
1103 | } | ||
1104 | ], | ||
1105 | "yaxis": { | ||
1106 | "align": false, | ||
1107 | "alignLevel": null | ||
1108 | } | ||
1109 | }, | ||
1110 | { | ||
1111 | "collapsed": false, | ||
1112 | "gridPos": { | ||
1113 | "h": 1, | ||
1114 | "w": 24, | ||
1115 | "x": 0, | ||
1116 | "y": 23 | ||
1117 | }, | ||
1118 | "id": 128, | ||
1119 | "panels": [], | ||
1120 | "repeat": null, | ||
1121 | "title": "JVM Misc", | ||
1122 | "type": "row" | ||
1123 | }, | ||
1124 | { | ||
1125 | "aliasColors": {}, | ||
1126 | "bars": false, | ||
1127 | "dashLength": 10, | ||
1128 | "dashes": false, | ||
1129 | "datasource": "Prometheus", | ||
1130 | "editable": true, | ||
1131 | "error": false, | ||
1132 | "fill": 1, | ||
1133 | "grid": { | ||
1134 | "leftLogBase": 1, | ||
1135 | "leftMax": null, | ||
1136 | "leftMin": null, | ||
1137 | "rightLogBase": 1, | ||
1138 | "rightMax": null, | ||
1139 | "rightMin": null | ||
1140 | }, | ||
1141 | "gridPos": { | ||
1142 | "h": 7, | ||
1143 | "w": 6, | ||
1144 | "x": 0, | ||
1145 | "y": 24 | ||
1146 | }, | ||
1147 | "id": 106, | ||
1148 | "legend": { | ||
1149 | "avg": false, | ||
1150 | "current": true, | ||
1151 | "max": true, | ||
1152 | "min": false, | ||
1153 | "show": true, | ||
1154 | "total": false, | ||
1155 | "values": true | ||
1156 | }, | ||
1157 | "lines": true, | ||
1158 | "linewidth": 1, | ||
1159 | "links": [], | ||
1160 | "nullPointMode": "null", | ||
1161 | "paceLength": 10, | ||
1162 | "percentage": false, | ||
1163 | "pointradius": 5, | ||
1164 | "points": false, | ||
1165 | "renderer": "flot", | ||
1166 | "seriesOverrides": [], | ||
1167 | "spaceLength": 10, | ||
1168 | "stack": false, | ||
1169 | "steppedLine": false, | ||
1170 | "targets": [ | ||
1171 | { | ||
1172 | "expr": "system_cpu_usage{application=\"$application\", instance=\"$instance\"}", | ||
1173 | "format": "time_series", | ||
1174 | "hide": false, | ||
1175 | "intervalFactor": 1, | ||
1176 | "legendFormat": "system", | ||
1177 | "metric": "", | ||
1178 | "refId": "A", | ||
1179 | "step": 2400 | ||
1180 | }, | ||
1181 | { | ||
1182 | "expr": "process_cpu_usage{application=\"$application\", instance=\"$instance\"}", | ||
1183 | "format": "time_series", | ||
1184 | "hide": false, | ||
1185 | "intervalFactor": 1, | ||
1186 | "legendFormat": "process", | ||
1187 | "refId": "B" | ||
1188 | }, | ||
1189 | { | ||
1190 | "expr": "avg_over_time(process_cpu_usage{application=\"$application\", instance=\"$instance\"}[1h])", | ||
1191 | "format": "time_series", | ||
1192 | "hide": false, | ||
1193 | "intervalFactor": 1, | ||
1194 | "legendFormat": "process-1h", | ||
1195 | "refId": "C" | ||
1196 | } | ||
1197 | ], | ||
1198 | "thresholds": [], | ||
1199 | "timeFrom": null, | ||
1200 | "timeRegions": [], | ||
1201 | "timeShift": null, | ||
1202 | "title": "CPU", | ||
1203 | "tooltip": { | ||
1204 | "msResolution": false, | ||
1205 | "shared": true, | ||
1206 | "sort": 0, | ||
1207 | "value_type": "cumulative" | ||
1208 | }, | ||
1209 | "type": "graph", | ||
1210 | "x-axis": true, | ||
1211 | "xaxis": { | ||
1212 | "buckets": null, | ||
1213 | "mode": "time", | ||
1214 | "name": null, | ||
1215 | "show": true, | ||
1216 | "values": [] | ||
1217 | }, | ||
1218 | "y-axis": true, | ||
1219 | "y_formats": ["short", "short"], | ||
1220 | "yaxes": [ | ||
1221 | { | ||
1222 | "decimals": 1, | ||
1223 | "format": "percentunit", | ||
1224 | "label": "", | ||
1225 | "logBase": 1, | ||
1226 | "max": "1", | ||
1227 | "min": 0, | ||
1228 | "show": true | ||
1229 | }, | ||
1230 | { | ||
1231 | "format": "short", | ||
1232 | "label": null, | ||
1233 | "logBase": 1, | ||
1234 | "max": null, | ||
1235 | "min": null, | ||
1236 | "show": true | ||
1237 | } | ||
1238 | ], | ||
1239 | "yaxis": { | ||
1240 | "align": false, | ||
1241 | "alignLevel": null | ||
1242 | } | ||
1243 | }, | ||
1244 | { | ||
1245 | "aliasColors": {}, | ||
1246 | "bars": false, | ||
1247 | "dashLength": 10, | ||
1248 | "dashes": false, | ||
1249 | "datasource": "Prometheus", | ||
1250 | "editable": true, | ||
1251 | "error": false, | ||
1252 | "fill": 1, | ||
1253 | "grid": { | ||
1254 | "leftLogBase": 1, | ||
1255 | "leftMax": null, | ||
1256 | "leftMin": null, | ||
1257 | "rightLogBase": 1, | ||
1258 | "rightMax": null, | ||
1259 | "rightMin": null | ||
1260 | }, | ||
1261 | "gridPos": { | ||
1262 | "h": 7, | ||
1263 | "w": 6, | ||
1264 | "x": 6, | ||
1265 | "y": 24 | ||
1266 | }, | ||
1267 | "id": 93, | ||
1268 | "legend": { | ||
1269 | "avg": false, | ||
1270 | "current": true, | ||
1271 | "max": true, | ||
1272 | "min": false, | ||
1273 | "show": true, | ||
1274 | "total": false, | ||
1275 | "values": true | ||
1276 | }, | ||
1277 | "lines": true, | ||
1278 | "linewidth": 1, | ||
1279 | "links": [], | ||
1280 | "nullPointMode": "null", | ||
1281 | "paceLength": 10, | ||
1282 | "percentage": false, | ||
1283 | "pointradius": 5, | ||
1284 | "points": false, | ||
1285 | "renderer": "flot", | ||
1286 | "seriesOverrides": [], | ||
1287 | "spaceLength": 10, | ||
1288 | "stack": false, | ||
1289 | "steppedLine": false, | ||
1290 | "targets": [ | ||
1291 | { | ||
1292 | "expr": "system_load_average_1m{application=\"$application\", instance=\"$instance\"}", | ||
1293 | "format": "time_series", | ||
1294 | "intervalFactor": 2, | ||
1295 | "legendFormat": "system-1m", | ||
1296 | "metric": "", | ||
1297 | "refId": "A", | ||
1298 | "step": 2400 | ||
1299 | }, | ||
1300 | { | ||
1301 | "expr": "", | ||
1302 | "format": "time_series", | ||
1303 | "intervalFactor": 2, | ||
1304 | "refId": "B" | ||
1305 | }, | ||
1306 | { | ||
1307 | "expr": "system_cpu_count{application=\"$application\", instance=\"$instance\"}", | ||
1308 | "format": "time_series", | ||
1309 | "intervalFactor": 2, | ||
1310 | "legendFormat": "cpu", | ||
1311 | "refId": "C" | ||
1312 | } | ||
1313 | ], | ||
1314 | "thresholds": [], | ||
1315 | "timeFrom": null, | ||
1316 | "timeRegions": [], | ||
1317 | "timeShift": null, | ||
1318 | "title": "Load", | ||
1319 | "tooltip": { | ||
1320 | "msResolution": false, | ||
1321 | "shared": true, | ||
1322 | "sort": 0, | ||
1323 | "value_type": "cumulative" | ||
1324 | }, | ||
1325 | "type": "graph", | ||
1326 | "x-axis": true, | ||
1327 | "xaxis": { | ||
1328 | "buckets": null, | ||
1329 | "mode": "time", | ||
1330 | "name": null, | ||
1331 | "show": true, | ||
1332 | "values": [] | ||
1333 | }, | ||
1334 | "y-axis": true, | ||
1335 | "y_formats": ["short", "short"], | ||
1336 | "yaxes": [ | ||
1337 | { | ||
1338 | "decimals": 1, | ||
1339 | "format": "short", | ||
1340 | "label": "", | ||
1341 | "logBase": 1, | ||
1342 | "max": null, | ||
1343 | "min": 0, | ||
1344 | "show": true | ||
1345 | }, | ||
1346 | { | ||
1347 | "format": "short", | ||
1348 | "label": null, | ||
1349 | "logBase": 1, | ||
1350 | "max": null, | ||
1351 | "min": null, | ||
1352 | "show": true | ||
1353 | } | ||
1354 | ], | ||
1355 | "yaxis": { | ||
1356 | "align": false, | ||
1357 | "alignLevel": null | ||
1358 | } | ||
1359 | }, | ||
1360 | { | ||
1361 | "aliasColors": {}, | ||
1362 | "bars": false, | ||
1363 | "dashLength": 10, | ||
1364 | "dashes": false, | ||
1365 | "datasource": "Prometheus", | ||
1366 | "editable": true, | ||
1367 | "error": false, | ||
1368 | "fill": 1, | ||
1369 | "grid": { | ||
1370 | "leftLogBase": 1, | ||
1371 | "leftMax": null, | ||
1372 | "leftMin": null, | ||
1373 | "rightLogBase": 1, | ||
1374 | "rightMax": null, | ||
1375 | "rightMin": null | ||
1376 | }, | ||
1377 | "gridPos": { | ||
1378 | "h": 7, | ||
1379 | "w": 6, | ||
1380 | "x": 12, | ||
1381 | "y": 24 | ||
1382 | }, | ||
1383 | "id": 32, | ||
1384 | "legend": { | ||
1385 | "avg": false, | ||
1386 | "current": true, | ||
1387 | "max": true, | ||
1388 | "min": false, | ||
1389 | "show": true, | ||
1390 | "total": false, | ||
1391 | "values": true | ||
1392 | }, | ||
1393 | "lines": true, | ||
1394 | "linewidth": 1, | ||
1395 | "links": [], | ||
1396 | "nullPointMode": "null", | ||
1397 | "paceLength": 10, | ||
1398 | "percentage": false, | ||
1399 | "pointradius": 5, | ||
1400 | "points": false, | ||
1401 | "renderer": "flot", | ||
1402 | "seriesOverrides": [], | ||
1403 | "spaceLength": 10, | ||
1404 | "stack": false, | ||
1405 | "steppedLine": false, | ||
1406 | "targets": [ | ||
1407 | { | ||
1408 | "expr": "jvm_threads_live{application=\"$application\", instance=\"$instance\"} or jvm_threads_live_threads{application=\"$application\", instance=\"$instance\"}", | ||
1409 | "format": "time_series", | ||
1410 | "intervalFactor": 2, | ||
1411 | "legendFormat": "live", | ||
1412 | "metric": "", | ||
1413 | "refId": "A", | ||
1414 | "step": 2400 | ||
1415 | }, | ||
1416 | { | ||
1417 | "expr": "jvm_threads_daemon{application=\"$application\", instance=\"$instance\"} or jvm_threads_daemon_threads{application=\"$application\", instance=\"$instance\"}", | ||
1418 | "format": "time_series", | ||
1419 | "intervalFactor": 2, | ||
1420 | "legendFormat": "daemon", | ||
1421 | "metric": "", | ||
1422 | "refId": "B", | ||
1423 | "step": 2400 | ||
1424 | }, | ||
1425 | { | ||
1426 | "expr": "jvm_threads_peak{application=\"$application\", instance=\"$instance\"} or jvm_threads_peak_threads{application=\"$application\", instance=\"$instance\"}", | ||
1427 | "format": "time_series", | ||
1428 | "intervalFactor": 2, | ||
1429 | "legendFormat": "peak", | ||
1430 | "refId": "C", | ||
1431 | "step": 2400 | ||
1432 | }, | ||
1433 | { | ||
1434 | "expr": "process_threads{application=\"$application\", instance=\"$instance\"}", | ||
1435 | "format": "time_series", | ||
1436 | "interval": "", | ||
1437 | "intervalFactor": 2, | ||
1438 | "legendFormat": "process", | ||
1439 | "refId": "D", | ||
1440 | "step": 2400 | ||
1441 | } | ||
1442 | ], | ||
1443 | "thresholds": [], | ||
1444 | "timeFrom": null, | ||
1445 | "timeRegions": [], | ||
1446 | "timeShift": null, | ||
1447 | "title": "Threads", | ||
1448 | "tooltip": { | ||
1449 | "msResolution": false, | ||
1450 | "shared": true, | ||
1451 | "sort": 0, | ||
1452 | "value_type": "cumulative" | ||
1453 | }, | ||
1454 | "type": "graph", | ||
1455 | "x-axis": true, | ||
1456 | "xaxis": { | ||
1457 | "buckets": null, | ||
1458 | "mode": "time", | ||
1459 | "name": null, | ||
1460 | "show": true, | ||
1461 | "values": [] | ||
1462 | }, | ||
1463 | "y-axis": true, | ||
1464 | "y_formats": ["short", "short"], | ||
1465 | "yaxes": [ | ||
1466 | { | ||
1467 | "decimals": 0, | ||
1468 | "format": "short", | ||
1469 | "label": null, | ||
1470 | "logBase": 1, | ||
1471 | "max": null, | ||
1472 | "min": 0, | ||
1473 | "show": true | ||
1474 | }, | ||
1475 | { | ||
1476 | "format": "short", | ||
1477 | "label": null, | ||
1478 | "logBase": 1, | ||
1479 | "max": null, | ||
1480 | "min": null, | ||
1481 | "show": true | ||
1482 | } | ||
1483 | ], | ||
1484 | "yaxis": { | ||
1485 | "align": false, | ||
1486 | "alignLevel": null | ||
1487 | } | ||
1488 | }, | ||
1489 | { | ||
1490 | "aliasColors": { | ||
1491 | "blocked": "#bf1b00", | ||
1492 | "new": "#fce2de", | ||
1493 | "runnable": "#7eb26d", | ||
1494 | "terminated": "#511749", | ||
1495 | "timed-waiting": "#c15c17", | ||
1496 | "waiting": "#eab839" | ||
1497 | }, | ||
1498 | "bars": false, | ||
1499 | "dashLength": 10, | ||
1500 | "dashes": false, | ||
1501 | "datasource": "Prometheus", | ||
1502 | "fill": 1, | ||
1503 | "gridPos": { | ||
1504 | "h": 7, | ||
1505 | "w": 6, | ||
1506 | "x": 18, | ||
1507 | "y": 24 | ||
1508 | }, | ||
1509 | "id": 124, | ||
1510 | "legend": { | ||
1511 | "alignAsTable": false, | ||
1512 | "avg": false, | ||
1513 | "current": true, | ||
1514 | "max": true, | ||
1515 | "min": false, | ||
1516 | "rightSide": false, | ||
1517 | "show": true, | ||
1518 | "total": false, | ||
1519 | "values": true | ||
1520 | }, | ||
1521 | "lines": true, | ||
1522 | "linewidth": 1, | ||
1523 | "links": [], | ||
1524 | "nullPointMode": "null", | ||
1525 | "paceLength": 10, | ||
1526 | "percentage": false, | ||
1527 | "pointradius": 5, | ||
1528 | "points": false, | ||
1529 | "renderer": "flot", | ||
1530 | "seriesOverrides": [], | ||
1531 | "spaceLength": 10, | ||
1532 | "stack": false, | ||
1533 | "steppedLine": false, | ||
1534 | "targets": [ | ||
1535 | { | ||
1536 | "expr": "jvm_threads_states_threads{application=\"$application\", instance=\"$instance\"}", | ||
1537 | "format": "time_series", | ||
1538 | "intervalFactor": 2, | ||
1539 | "legendFormat": "{{state}}", | ||
1540 | "refId": "A" | ||
1541 | } | ||
1542 | ], | ||
1543 | "thresholds": [], | ||
1544 | "timeFrom": null, | ||
1545 | "timeRegions": [], | ||
1546 | "timeShift": null, | ||
1547 | "title": "Thread States", | ||
1548 | "tooltip": { | ||
1549 | "shared": true, | ||
1550 | "sort": 0, | ||
1551 | "value_type": "individual" | ||
1552 | }, | ||
1553 | "type": "graph", | ||
1554 | "xaxis": { | ||
1555 | "buckets": null, | ||
1556 | "mode": "time", | ||
1557 | "name": null, | ||
1558 | "show": true, | ||
1559 | "values": [] | ||
1560 | }, | ||
1561 | "yaxes": [ | ||
1562 | { | ||
1563 | "format": "short", | ||
1564 | "label": null, | ||
1565 | "logBase": 1, | ||
1566 | "max": null, | ||
1567 | "min": null, | ||
1568 | "show": true | ||
1569 | }, | ||
1570 | { | ||
1571 | "format": "short", | ||
1572 | "label": null, | ||
1573 | "logBase": 1, | ||
1574 | "max": null, | ||
1575 | "min": null, | ||
1576 | "show": true | ||
1577 | } | ||
1578 | ], | ||
1579 | "yaxis": { | ||
1580 | "align": false, | ||
1581 | "alignLevel": null | ||
1582 | } | ||
1583 | }, | ||
1584 | { | ||
1585 | "aliasColors": { | ||
1586 | "debug": "#1F78C1", | ||
1587 | "error": "#BF1B00", | ||
1588 | "info": "#508642", | ||
1589 | "trace": "#6ED0E0", | ||
1590 | "warn": "#EAB839" | ||
1591 | }, | ||
1592 | "bars": false, | ||
1593 | "dashLength": 10, | ||
1594 | "dashes": false, | ||
1595 | "datasource": "Prometheus", | ||
1596 | "editable": true, | ||
1597 | "error": false, | ||
1598 | "fill": 1, | ||
1599 | "grid": { | ||
1600 | "leftLogBase": 1, | ||
1601 | "leftMax": null, | ||
1602 | "leftMin": null, | ||
1603 | "rightLogBase": 1, | ||
1604 | "rightMax": null, | ||
1605 | "rightMin": null | ||
1606 | }, | ||
1607 | "gridPos": { | ||
1608 | "h": 7, | ||
1609 | "w": 18, | ||
1610 | "x": 0, | ||
1611 | "y": 31 | ||
1612 | }, | ||
1613 | "height": "", | ||
1614 | "id": 91, | ||
1615 | "legend": { | ||
1616 | "alignAsTable": false, | ||
1617 | "avg": false, | ||
1618 | "current": true, | ||
1619 | "hideEmpty": false, | ||
1620 | "hideZero": false, | ||
1621 | "max": true, | ||
1622 | "min": false, | ||
1623 | "rightSide": false, | ||
1624 | "show": true, | ||
1625 | "total": false, | ||
1626 | "values": true | ||
1627 | }, | ||
1628 | "lines": true, | ||
1629 | "linewidth": 1, | ||
1630 | "links": [], | ||
1631 | "nullPointMode": "null", | ||
1632 | "paceLength": 10, | ||
1633 | "percentage": true, | ||
1634 | "pointradius": 5, | ||
1635 | "points": false, | ||
1636 | "renderer": "flot", | ||
1637 | "seriesOverrides": [ | ||
1638 | { | ||
1639 | "alias": "error", | ||
1640 | "yaxis": 1 | ||
1641 | }, | ||
1642 | { | ||
1643 | "alias": "warn", | ||
1644 | "yaxis": 1 | ||
1645 | } | ||
1646 | ], | ||
1647 | "spaceLength": 10, | ||
1648 | "stack": false, | ||
1649 | "steppedLine": false, | ||
1650 | "targets": [ | ||
1651 | { | ||
1652 | "expr": "increase(logback_events_total{application=\"$application\", instance=\"$instance\"}[1m])", | ||
1653 | "format": "time_series", | ||
1654 | "interval": "", | ||
1655 | "intervalFactor": 2, | ||
1656 | "legendFormat": "{{level}}", | ||
1657 | "metric": "", | ||
1658 | "refId": "A", | ||
1659 | "step": 1200 | ||
1660 | } | ||
1661 | ], | ||
1662 | "thresholds": [], | ||
1663 | "timeFrom": null, | ||
1664 | "timeRegions": [], | ||
1665 | "timeShift": null, | ||
1666 | "title": "Log Events (1m)", | ||
1667 | "tooltip": { | ||
1668 | "msResolution": false, | ||
1669 | "shared": true, | ||
1670 | "sort": 0, | ||
1671 | "value_type": "individual" | ||
1672 | }, | ||
1673 | "type": "graph", | ||
1674 | "x-axis": true, | ||
1675 | "xaxis": { | ||
1676 | "buckets": null, | ||
1677 | "mode": "time", | ||
1678 | "name": null, | ||
1679 | "show": true, | ||
1680 | "values": [] | ||
1681 | }, | ||
1682 | "y-axis": true, | ||
1683 | "y_formats": ["short", "short"], | ||
1684 | "yaxes": [ | ||
1685 | { | ||
1686 | "decimals": 0, | ||
1687 | "format": "short", | ||
1688 | "label": null, | ||
1689 | "logBase": 1, | ||
1690 | "max": null, | ||
1691 | "min": "0", | ||
1692 | "show": true | ||
1693 | }, | ||
1694 | { | ||
1695 | "format": "short", | ||
1696 | "label": null, | ||
1697 | "logBase": 1, | ||
1698 | "max": null, | ||
1699 | "min": null, | ||
1700 | "show": true | ||
1701 | } | ||
1702 | ], | ||
1703 | "yaxis": { | ||
1704 | "align": false, | ||
1705 | "alignLevel": null | ||
1706 | } | ||
1707 | }, | ||
1708 | { | ||
1709 | "aliasColors": {}, | ||
1710 | "bars": false, | ||
1711 | "dashLength": 10, | ||
1712 | "dashes": false, | ||
1713 | "datasource": "Prometheus", | ||
1714 | "editable": true, | ||
1715 | "error": false, | ||
1716 | "fill": 1, | ||
1717 | "grid": { | ||
1718 | "leftLogBase": 1, | ||
1719 | "leftMax": null, | ||
1720 | "leftMin": null, | ||
1721 | "rightLogBase": 1, | ||
1722 | "rightMax": null, | ||
1723 | "rightMin": null | ||
1724 | }, | ||
1725 | "gridPos": { | ||
1726 | "h": 7, | ||
1727 | "w": 6, | ||
1728 | "x": 18, | ||
1729 | "y": 31 | ||
1730 | }, | ||
1731 | "id": 61, | ||
1732 | "legend": { | ||
1733 | "avg": false, | ||
1734 | "current": true, | ||
1735 | "max": true, | ||
1736 | "min": false, | ||
1737 | "show": true, | ||
1738 | "total": false, | ||
1739 | "values": true | ||
1740 | }, | ||
1741 | "lines": true, | ||
1742 | "linewidth": 1, | ||
1743 | "links": [], | ||
1744 | "nullPointMode": "null", | ||
1745 | "paceLength": 10, | ||
1746 | "percentage": false, | ||
1747 | "pointradius": 5, | ||
1748 | "points": false, | ||
1749 | "renderer": "flot", | ||
1750 | "seriesOverrides": [], | ||
1751 | "spaceLength": 10, | ||
1752 | "stack": false, | ||
1753 | "steppedLine": false, | ||
1754 | "targets": [ | ||
1755 | { | ||
1756 | "expr": "process_open_fds{application=\"$application\", instance=\"$instance\"}", | ||
1757 | "format": "time_series", | ||
1758 | "hide": false, | ||
1759 | "intervalFactor": 2, | ||
1760 | "legendFormat": "open", | ||
1761 | "metric": "", | ||
1762 | "refId": "A", | ||
1763 | "step": 2400 | ||
1764 | }, | ||
1765 | { | ||
1766 | "expr": "process_max_fds{application=\"$application\", instance=\"$instance\"}", | ||
1767 | "format": "time_series", | ||
1768 | "hide": false, | ||
1769 | "intervalFactor": 2, | ||
1770 | "legendFormat": "max", | ||
1771 | "metric": "", | ||
1772 | "refId": "B", | ||
1773 | "step": 2400 | ||
1774 | }, | ||
1775 | { | ||
1776 | "expr": "process_files_open{application=\"$application\", instance=\"$instance\"} or process_files_open_files{application=\"$application\", instance=\"$instance\"}", | ||
1777 | "format": "time_series", | ||
1778 | "intervalFactor": 2, | ||
1779 | "legendFormat": "open", | ||
1780 | "refId": "C" | ||
1781 | }, | ||
1782 | { | ||
1783 | "expr": "process_files_max{application=\"$application\", instance=\"$instance\"} or process_files_max_files{application=\"$application\", instance=\"$instance\"}", | ||
1784 | "format": "time_series", | ||
1785 | "intervalFactor": 2, | ||
1786 | "legendFormat": "max", | ||
1787 | "refId": "D" | ||
1788 | } | ||
1789 | ], | ||
1790 | "thresholds": [], | ||
1791 | "timeFrom": null, | ||
1792 | "timeRegions": [], | ||
1793 | "timeShift": null, | ||
1794 | "title": "File Descriptors", | ||
1795 | "tooltip": { | ||
1796 | "msResolution": false, | ||
1797 | "shared": true, | ||
1798 | "sort": 0, | ||
1799 | "value_type": "cumulative" | ||
1800 | }, | ||
1801 | "type": "graph", | ||
1802 | "x-axis": true, | ||
1803 | "xaxis": { | ||
1804 | "buckets": null, | ||
1805 | "mode": "time", | ||
1806 | "name": null, | ||
1807 | "show": true, | ||
1808 | "values": [] | ||
1809 | }, | ||
1810 | "y-axis": true, | ||
1811 | "y_formats": ["short", "short"], | ||
1812 | "yaxes": [ | ||
1813 | { | ||
1814 | "decimals": 0, | ||
1815 | "format": "short", | ||
1816 | "label": null, | ||
1817 | "logBase": 10, | ||
1818 | "max": null, | ||
1819 | "min": 0, | ||
1820 | "show": true | ||
1821 | }, | ||
1822 | { | ||
1823 | "format": "short", | ||
1824 | "label": null, | ||
1825 | "logBase": 1, | ||
1826 | "max": null, | ||
1827 | "min": null, | ||
1828 | "show": true | ||
1829 | } | ||
1830 | ], | ||
1831 | "yaxis": { | ||
1832 | "align": false, | ||
1833 | "alignLevel": null | ||
1834 | } | ||
1835 | }, | ||
1836 | { | ||
1837 | "collapsed": false, | ||
1838 | "gridPos": { | ||
1839 | "h": 1, | ||
1840 | "w": 24, | ||
1841 | "x": 0, | ||
1842 | "y": 38 | ||
1843 | }, | ||
1844 | "id": 129, | ||
1845 | "panels": [], | ||
1846 | "repeat": "persistence_counts", | ||
1847 | "title": "JVM Memory Pools (Heap)", | ||
1848 | "type": "row" | ||
1849 | }, | ||
1850 | { | ||
1851 | "aliasColors": {}, | ||
1852 | "bars": false, | ||
1853 | "dashLength": 10, | ||
1854 | "dashes": false, | ||
1855 | "datasource": "Prometheus", | ||
1856 | "editable": true, | ||
1857 | "error": false, | ||
1858 | "fill": 1, | ||
1859 | "grid": { | ||
1860 | "leftLogBase": 1, | ||
1861 | "leftMax": null, | ||
1862 | "leftMin": null, | ||
1863 | "rightLogBase": 1, | ||
1864 | "rightMax": null, | ||
1865 | "rightMin": null | ||
1866 | }, | ||
1867 | "gridPos": { | ||
1868 | "h": 7, | ||
1869 | "w": 8, | ||
1870 | "x": 0, | ||
1871 | "y": 39 | ||
1872 | }, | ||
1873 | "id": 3, | ||
1874 | "legend": { | ||
1875 | "alignAsTable": false, | ||
1876 | "avg": false, | ||
1877 | "current": true, | ||
1878 | "max": true, | ||
1879 | "min": false, | ||
1880 | "rightSide": false, | ||
1881 | "show": true, | ||
1882 | "total": false, | ||
1883 | "values": true | ||
1884 | }, | ||
1885 | "lines": true, | ||
1886 | "linewidth": 1, | ||
1887 | "links": [], | ||
1888 | "maxPerRow": 3, | ||
1889 | "nullPointMode": "null", | ||
1890 | "paceLength": 10, | ||
1891 | "percentage": false, | ||
1892 | "pointradius": 5, | ||
1893 | "points": false, | ||
1894 | "renderer": "flot", | ||
1895 | "repeat": "jvm_memory_pool_heap", | ||
1896 | "scopedVars": { | ||
1897 | "jvm_memory_pool_heap": { | ||
1898 | "selected": false, | ||
1899 | "text": "PS Eden Space", | ||
1900 | "value": "PS Eden Space" | ||
1901 | } | ||
1902 | }, | ||
1903 | "seriesOverrides": [], | ||
1904 | "spaceLength": 10, | ||
1905 | "stack": false, | ||
1906 | "steppedLine": false, | ||
1907 | "targets": [ | ||
1908 | { | ||
1909 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
1910 | "format": "time_series", | ||
1911 | "hide": false, | ||
1912 | "interval": "", | ||
1913 | "intervalFactor": 2, | ||
1914 | "legendFormat": "used", | ||
1915 | "metric": "", | ||
1916 | "refId": "A", | ||
1917 | "step": 1800 | ||
1918 | }, | ||
1919 | { | ||
1920 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
1921 | "format": "time_series", | ||
1922 | "hide": false, | ||
1923 | "interval": "", | ||
1924 | "intervalFactor": 2, | ||
1925 | "legendFormat": "commited", | ||
1926 | "metric": "", | ||
1927 | "refId": "B", | ||
1928 | "step": 1800 | ||
1929 | }, | ||
1930 | { | ||
1931 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
1932 | "format": "time_series", | ||
1933 | "hide": false, | ||
1934 | "interval": "", | ||
1935 | "intervalFactor": 2, | ||
1936 | "legendFormat": "max", | ||
1937 | "metric": "", | ||
1938 | "refId": "C", | ||
1939 | "step": 1800 | ||
1940 | } | ||
1941 | ], | ||
1942 | "thresholds": [], | ||
1943 | "timeFrom": null, | ||
1944 | "timeRegions": [], | ||
1945 | "timeShift": null, | ||
1946 | "title": "$jvm_memory_pool_heap", | ||
1947 | "tooltip": { | ||
1948 | "msResolution": false, | ||
1949 | "shared": true, | ||
1950 | "sort": 0, | ||
1951 | "value_type": "cumulative" | ||
1952 | }, | ||
1953 | "type": "graph", | ||
1954 | "x-axis": true, | ||
1955 | "xaxis": { | ||
1956 | "buckets": null, | ||
1957 | "mode": "time", | ||
1958 | "name": null, | ||
1959 | "show": true, | ||
1960 | "values": [] | ||
1961 | }, | ||
1962 | "y-axis": true, | ||
1963 | "y_formats": ["mbytes", "short"], | ||
1964 | "yaxes": [ | ||
1965 | { | ||
1966 | "format": "bytes", | ||
1967 | "label": null, | ||
1968 | "logBase": 1, | ||
1969 | "max": null, | ||
1970 | "min": 0, | ||
1971 | "show": true | ||
1972 | }, | ||
1973 | { | ||
1974 | "format": "short", | ||
1975 | "label": null, | ||
1976 | "logBase": 1, | ||
1977 | "max": null, | ||
1978 | "min": null, | ||
1979 | "show": true | ||
1980 | } | ||
1981 | ], | ||
1982 | "yaxis": { | ||
1983 | "align": false, | ||
1984 | "alignLevel": null | ||
1985 | } | ||
1986 | }, | ||
1987 | { | ||
1988 | "aliasColors": {}, | ||
1989 | "bars": false, | ||
1990 | "dashLength": 10, | ||
1991 | "dashes": false, | ||
1992 | "datasource": "Prometheus", | ||
1993 | "editable": true, | ||
1994 | "error": false, | ||
1995 | "fill": 1, | ||
1996 | "grid": { | ||
1997 | "leftLogBase": 1, | ||
1998 | "leftMax": null, | ||
1999 | "leftMin": null, | ||
2000 | "rightLogBase": 1, | ||
2001 | "rightMax": null, | ||
2002 | "rightMin": null | ||
2003 | }, | ||
2004 | "gridPos": { | ||
2005 | "h": 7, | ||
2006 | "w": 8, | ||
2007 | "x": 8, | ||
2008 | "y": 39 | ||
2009 | }, | ||
2010 | "id": 134, | ||
2011 | "legend": { | ||
2012 | "alignAsTable": false, | ||
2013 | "avg": false, | ||
2014 | "current": true, | ||
2015 | "max": true, | ||
2016 | "min": false, | ||
2017 | "rightSide": false, | ||
2018 | "show": true, | ||
2019 | "total": false, | ||
2020 | "values": true | ||
2021 | }, | ||
2022 | "lines": true, | ||
2023 | "linewidth": 1, | ||
2024 | "links": [], | ||
2025 | "maxPerRow": 3, | ||
2026 | "nullPointMode": "null", | ||
2027 | "paceLength": 10, | ||
2028 | "percentage": false, | ||
2029 | "pointradius": 5, | ||
2030 | "points": false, | ||
2031 | "renderer": "flot", | ||
2032 | "repeat": null, | ||
2033 | "repeatIteration": 1553765841423, | ||
2034 | "repeatPanelId": 3, | ||
2035 | "scopedVars": { | ||
2036 | "jvm_memory_pool_heap": { | ||
2037 | "selected": false, | ||
2038 | "text": "PS Old Gen", | ||
2039 | "value": "PS Old Gen" | ||
2040 | } | ||
2041 | }, | ||
2042 | "seriesOverrides": [], | ||
2043 | "spaceLength": 10, | ||
2044 | "stack": false, | ||
2045 | "steppedLine": false, | ||
2046 | "targets": [ | ||
2047 | { | ||
2048 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2049 | "format": "time_series", | ||
2050 | "hide": false, | ||
2051 | "interval": "", | ||
2052 | "intervalFactor": 2, | ||
2053 | "legendFormat": "used", | ||
2054 | "metric": "", | ||
2055 | "refId": "A", | ||
2056 | "step": 1800 | ||
2057 | }, | ||
2058 | { | ||
2059 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2060 | "format": "time_series", | ||
2061 | "hide": false, | ||
2062 | "interval": "", | ||
2063 | "intervalFactor": 2, | ||
2064 | "legendFormat": "commited", | ||
2065 | "metric": "", | ||
2066 | "refId": "B", | ||
2067 | "step": 1800 | ||
2068 | }, | ||
2069 | { | ||
2070 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2071 | "format": "time_series", | ||
2072 | "hide": false, | ||
2073 | "interval": "", | ||
2074 | "intervalFactor": 2, | ||
2075 | "legendFormat": "max", | ||
2076 | "metric": "", | ||
2077 | "refId": "C", | ||
2078 | "step": 1800 | ||
2079 | } | ||
2080 | ], | ||
2081 | "thresholds": [], | ||
2082 | "timeFrom": null, | ||
2083 | "timeRegions": [], | ||
2084 | "timeShift": null, | ||
2085 | "title": "$jvm_memory_pool_heap", | ||
2086 | "tooltip": { | ||
2087 | "msResolution": false, | ||
2088 | "shared": true, | ||
2089 | "sort": 0, | ||
2090 | "value_type": "cumulative" | ||
2091 | }, | ||
2092 | "type": "graph", | ||
2093 | "x-axis": true, | ||
2094 | "xaxis": { | ||
2095 | "buckets": null, | ||
2096 | "mode": "time", | ||
2097 | "name": null, | ||
2098 | "show": true, | ||
2099 | "values": [] | ||
2100 | }, | ||
2101 | "y-axis": true, | ||
2102 | "y_formats": ["mbytes", "short"], | ||
2103 | "yaxes": [ | ||
2104 | { | ||
2105 | "format": "bytes", | ||
2106 | "label": null, | ||
2107 | "logBase": 1, | ||
2108 | "max": null, | ||
2109 | "min": 0, | ||
2110 | "show": true | ||
2111 | }, | ||
2112 | { | ||
2113 | "format": "short", | ||
2114 | "label": null, | ||
2115 | "logBase": 1, | ||
2116 | "max": null, | ||
2117 | "min": null, | ||
2118 | "show": true | ||
2119 | } | ||
2120 | ], | ||
2121 | "yaxis": { | ||
2122 | "align": false, | ||
2123 | "alignLevel": null | ||
2124 | } | ||
2125 | }, | ||
2126 | { | ||
2127 | "aliasColors": {}, | ||
2128 | "bars": false, | ||
2129 | "dashLength": 10, | ||
2130 | "dashes": false, | ||
2131 | "datasource": "Prometheus", | ||
2132 | "editable": true, | ||
2133 | "error": false, | ||
2134 | "fill": 1, | ||
2135 | "grid": { | ||
2136 | "leftLogBase": 1, | ||
2137 | "leftMax": null, | ||
2138 | "leftMin": null, | ||
2139 | "rightLogBase": 1, | ||
2140 | "rightMax": null, | ||
2141 | "rightMin": null | ||
2142 | }, | ||
2143 | "gridPos": { | ||
2144 | "h": 7, | ||
2145 | "w": 8, | ||
2146 | "x": 16, | ||
2147 | "y": 39 | ||
2148 | }, | ||
2149 | "id": 135, | ||
2150 | "legend": { | ||
2151 | "alignAsTable": false, | ||
2152 | "avg": false, | ||
2153 | "current": true, | ||
2154 | "max": true, | ||
2155 | "min": false, | ||
2156 | "rightSide": false, | ||
2157 | "show": true, | ||
2158 | "total": false, | ||
2159 | "values": true | ||
2160 | }, | ||
2161 | "lines": true, | ||
2162 | "linewidth": 1, | ||
2163 | "links": [], | ||
2164 | "maxPerRow": 3, | ||
2165 | "nullPointMode": "null", | ||
2166 | "paceLength": 10, | ||
2167 | "percentage": false, | ||
2168 | "pointradius": 5, | ||
2169 | "points": false, | ||
2170 | "renderer": "flot", | ||
2171 | "repeat": null, | ||
2172 | "repeatIteration": 1553765841423, | ||
2173 | "repeatPanelId": 3, | ||
2174 | "scopedVars": { | ||
2175 | "jvm_memory_pool_heap": { | ||
2176 | "selected": false, | ||
2177 | "text": "PS Survivor Space", | ||
2178 | "value": "PS Survivor Space" | ||
2179 | } | ||
2180 | }, | ||
2181 | "seriesOverrides": [], | ||
2182 | "spaceLength": 10, | ||
2183 | "stack": false, | ||
2184 | "steppedLine": false, | ||
2185 | "targets": [ | ||
2186 | { | ||
2187 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2188 | "format": "time_series", | ||
2189 | "hide": false, | ||
2190 | "interval": "", | ||
2191 | "intervalFactor": 2, | ||
2192 | "legendFormat": "used", | ||
2193 | "metric": "", | ||
2194 | "refId": "A", | ||
2195 | "step": 1800 | ||
2196 | }, | ||
2197 | { | ||
2198 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2199 | "format": "time_series", | ||
2200 | "hide": false, | ||
2201 | "interval": "", | ||
2202 | "intervalFactor": 2, | ||
2203 | "legendFormat": "commited", | ||
2204 | "metric": "", | ||
2205 | "refId": "B", | ||
2206 | "step": 1800 | ||
2207 | }, | ||
2208 | { | ||
2209 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_heap\"}", | ||
2210 | "format": "time_series", | ||
2211 | "hide": false, | ||
2212 | "interval": "", | ||
2213 | "intervalFactor": 2, | ||
2214 | "legendFormat": "max", | ||
2215 | "metric": "", | ||
2216 | "refId": "C", | ||
2217 | "step": 1800 | ||
2218 | } | ||
2219 | ], | ||
2220 | "thresholds": [], | ||
2221 | "timeFrom": null, | ||
2222 | "timeRegions": [], | ||
2223 | "timeShift": null, | ||
2224 | "title": "$jvm_memory_pool_heap", | ||
2225 | "tooltip": { | ||
2226 | "msResolution": false, | ||
2227 | "shared": true, | ||
2228 | "sort": 0, | ||
2229 | "value_type": "cumulative" | ||
2230 | }, | ||
2231 | "type": "graph", | ||
2232 | "x-axis": true, | ||
2233 | "xaxis": { | ||
2234 | "buckets": null, | ||
2235 | "mode": "time", | ||
2236 | "name": null, | ||
2237 | "show": true, | ||
2238 | "values": [] | ||
2239 | }, | ||
2240 | "y-axis": true, | ||
2241 | "y_formats": ["mbytes", "short"], | ||
2242 | "yaxes": [ | ||
2243 | { | ||
2244 | "format": "bytes", | ||
2245 | "label": null, | ||
2246 | "logBase": 1, | ||
2247 | "max": null, | ||
2248 | "min": 0, | ||
2249 | "show": true | ||
2250 | }, | ||
2251 | { | ||
2252 | "format": "short", | ||
2253 | "label": null, | ||
2254 | "logBase": 1, | ||
2255 | "max": null, | ||
2256 | "min": null, | ||
2257 | "show": true | ||
2258 | } | ||
2259 | ], | ||
2260 | "yaxis": { | ||
2261 | "align": false, | ||
2262 | "alignLevel": null | ||
2263 | } | ||
2264 | }, | ||
2265 | { | ||
2266 | "collapsed": false, | ||
2267 | "gridPos": { | ||
2268 | "h": 1, | ||
2269 | "w": 24, | ||
2270 | "x": 0, | ||
2271 | "y": 46 | ||
2272 | }, | ||
2273 | "id": 130, | ||
2274 | "panels": [], | ||
2275 | "repeat": null, | ||
2276 | "title": "JVM Memory Pools (Non-Heap)", | ||
2277 | "type": "row" | ||
2278 | }, | ||
2279 | { | ||
2280 | "aliasColors": {}, | ||
2281 | "bars": false, | ||
2282 | "dashLength": 10, | ||
2283 | "dashes": false, | ||
2284 | "datasource": "Prometheus", | ||
2285 | "editable": true, | ||
2286 | "error": false, | ||
2287 | "fill": 1, | ||
2288 | "grid": { | ||
2289 | "leftLogBase": 1, | ||
2290 | "leftMax": null, | ||
2291 | "leftMin": null, | ||
2292 | "rightLogBase": 1, | ||
2293 | "rightMax": null, | ||
2294 | "rightMin": null | ||
2295 | }, | ||
2296 | "gridPos": { | ||
2297 | "h": 7, | ||
2298 | "w": 8, | ||
2299 | "x": 0, | ||
2300 | "y": 47 | ||
2301 | }, | ||
2302 | "id": 78, | ||
2303 | "legend": { | ||
2304 | "alignAsTable": false, | ||
2305 | "avg": false, | ||
2306 | "current": true, | ||
2307 | "max": true, | ||
2308 | "min": false, | ||
2309 | "rightSide": false, | ||
2310 | "show": true, | ||
2311 | "total": false, | ||
2312 | "values": true | ||
2313 | }, | ||
2314 | "lines": true, | ||
2315 | "linewidth": 1, | ||
2316 | "links": [], | ||
2317 | "maxPerRow": 3, | ||
2318 | "nullPointMode": "null", | ||
2319 | "paceLength": 10, | ||
2320 | "percentage": false, | ||
2321 | "pointradius": 5, | ||
2322 | "points": false, | ||
2323 | "renderer": "flot", | ||
2324 | "repeat": "jvm_memory_pool_nonheap", | ||
2325 | "scopedVars": { | ||
2326 | "jvm_memory_pool_nonheap": { | ||
2327 | "selected": false, | ||
2328 | "text": "Metaspace", | ||
2329 | "value": "Metaspace" | ||
2330 | } | ||
2331 | }, | ||
2332 | "seriesOverrides": [], | ||
2333 | "spaceLength": 10, | ||
2334 | "stack": false, | ||
2335 | "steppedLine": false, | ||
2336 | "targets": [ | ||
2337 | { | ||
2338 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2339 | "format": "time_series", | ||
2340 | "hide": false, | ||
2341 | "interval": "", | ||
2342 | "intervalFactor": 2, | ||
2343 | "legendFormat": "used", | ||
2344 | "metric": "", | ||
2345 | "refId": "A", | ||
2346 | "step": 1800 | ||
2347 | }, | ||
2348 | { | ||
2349 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2350 | "format": "time_series", | ||
2351 | "hide": false, | ||
2352 | "interval": "", | ||
2353 | "intervalFactor": 2, | ||
2354 | "legendFormat": "commited", | ||
2355 | "metric": "", | ||
2356 | "refId": "B", | ||
2357 | "step": 1800 | ||
2358 | }, | ||
2359 | { | ||
2360 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2361 | "format": "time_series", | ||
2362 | "hide": false, | ||
2363 | "interval": "", | ||
2364 | "intervalFactor": 2, | ||
2365 | "legendFormat": "max", | ||
2366 | "metric": "", | ||
2367 | "refId": "C", | ||
2368 | "step": 1800 | ||
2369 | } | ||
2370 | ], | ||
2371 | "thresholds": [], | ||
2372 | "timeFrom": null, | ||
2373 | "timeRegions": [], | ||
2374 | "timeShift": null, | ||
2375 | "title": "$jvm_memory_pool_nonheap", | ||
2376 | "tooltip": { | ||
2377 | "msResolution": false, | ||
2378 | "shared": true, | ||
2379 | "sort": 0, | ||
2380 | "value_type": "cumulative" | ||
2381 | }, | ||
2382 | "type": "graph", | ||
2383 | "x-axis": true, | ||
2384 | "xaxis": { | ||
2385 | "buckets": null, | ||
2386 | "mode": "time", | ||
2387 | "name": null, | ||
2388 | "show": true, | ||
2389 | "values": [] | ||
2390 | }, | ||
2391 | "y-axis": true, | ||
2392 | "y_formats": ["mbytes", "short"], | ||
2393 | "yaxes": [ | ||
2394 | { | ||
2395 | "format": "bytes", | ||
2396 | "label": null, | ||
2397 | "logBase": 1, | ||
2398 | "max": null, | ||
2399 | "min": 0, | ||
2400 | "show": true | ||
2401 | }, | ||
2402 | { | ||
2403 | "format": "short", | ||
2404 | "label": null, | ||
2405 | "logBase": 1, | ||
2406 | "max": null, | ||
2407 | "min": null, | ||
2408 | "show": true | ||
2409 | } | ||
2410 | ], | ||
2411 | "yaxis": { | ||
2412 | "align": false, | ||
2413 | "alignLevel": null | ||
2414 | } | ||
2415 | }, | ||
2416 | { | ||
2417 | "aliasColors": {}, | ||
2418 | "bars": false, | ||
2419 | "dashLength": 10, | ||
2420 | "dashes": false, | ||
2421 | "datasource": "Prometheus", | ||
2422 | "editable": true, | ||
2423 | "error": false, | ||
2424 | "fill": 1, | ||
2425 | "grid": { | ||
2426 | "leftLogBase": 1, | ||
2427 | "leftMax": null, | ||
2428 | "leftMin": null, | ||
2429 | "rightLogBase": 1, | ||
2430 | "rightMax": null, | ||
2431 | "rightMin": null | ||
2432 | }, | ||
2433 | "gridPos": { | ||
2434 | "h": 7, | ||
2435 | "w": 8, | ||
2436 | "x": 8, | ||
2437 | "y": 47 | ||
2438 | }, | ||
2439 | "id": 136, | ||
2440 | "legend": { | ||
2441 | "alignAsTable": false, | ||
2442 | "avg": false, | ||
2443 | "current": true, | ||
2444 | "max": true, | ||
2445 | "min": false, | ||
2446 | "rightSide": false, | ||
2447 | "show": true, | ||
2448 | "total": false, | ||
2449 | "values": true | ||
2450 | }, | ||
2451 | "lines": true, | ||
2452 | "linewidth": 1, | ||
2453 | "links": [], | ||
2454 | "maxPerRow": 3, | ||
2455 | "nullPointMode": "null", | ||
2456 | "paceLength": 10, | ||
2457 | "percentage": false, | ||
2458 | "pointradius": 5, | ||
2459 | "points": false, | ||
2460 | "renderer": "flot", | ||
2461 | "repeat": null, | ||
2462 | "repeatIteration": 1553765841423, | ||
2463 | "repeatPanelId": 78, | ||
2464 | "scopedVars": { | ||
2465 | "jvm_memory_pool_nonheap": { | ||
2466 | "selected": false, | ||
2467 | "text": "Compressed Class Space", | ||
2468 | "value": "Compressed Class Space" | ||
2469 | } | ||
2470 | }, | ||
2471 | "seriesOverrides": [], | ||
2472 | "spaceLength": 10, | ||
2473 | "stack": false, | ||
2474 | "steppedLine": false, | ||
2475 | "targets": [ | ||
2476 | { | ||
2477 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2478 | "format": "time_series", | ||
2479 | "hide": false, | ||
2480 | "interval": "", | ||
2481 | "intervalFactor": 2, | ||
2482 | "legendFormat": "used", | ||
2483 | "metric": "", | ||
2484 | "refId": "A", | ||
2485 | "step": 1800 | ||
2486 | }, | ||
2487 | { | ||
2488 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2489 | "format": "time_series", | ||
2490 | "hide": false, | ||
2491 | "interval": "", | ||
2492 | "intervalFactor": 2, | ||
2493 | "legendFormat": "commited", | ||
2494 | "metric": "", | ||
2495 | "refId": "B", | ||
2496 | "step": 1800 | ||
2497 | }, | ||
2498 | { | ||
2499 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2500 | "format": "time_series", | ||
2501 | "hide": false, | ||
2502 | "interval": "", | ||
2503 | "intervalFactor": 2, | ||
2504 | "legendFormat": "max", | ||
2505 | "metric": "", | ||
2506 | "refId": "C", | ||
2507 | "step": 1800 | ||
2508 | } | ||
2509 | ], | ||
2510 | "thresholds": [], | ||
2511 | "timeFrom": null, | ||
2512 | "timeRegions": [], | ||
2513 | "timeShift": null, | ||
2514 | "title": "$jvm_memory_pool_nonheap", | ||
2515 | "tooltip": { | ||
2516 | "msResolution": false, | ||
2517 | "shared": true, | ||
2518 | "sort": 0, | ||
2519 | "value_type": "cumulative" | ||
2520 | }, | ||
2521 | "type": "graph", | ||
2522 | "x-axis": true, | ||
2523 | "xaxis": { | ||
2524 | "buckets": null, | ||
2525 | "mode": "time", | ||
2526 | "name": null, | ||
2527 | "show": true, | ||
2528 | "values": [] | ||
2529 | }, | ||
2530 | "y-axis": true, | ||
2531 | "y_formats": ["mbytes", "short"], | ||
2532 | "yaxes": [ | ||
2533 | { | ||
2534 | "format": "bytes", | ||
2535 | "label": null, | ||
2536 | "logBase": 1, | ||
2537 | "max": null, | ||
2538 | "min": 0, | ||
2539 | "show": true | ||
2540 | }, | ||
2541 | { | ||
2542 | "format": "short", | ||
2543 | "label": null, | ||
2544 | "logBase": 1, | ||
2545 | "max": null, | ||
2546 | "min": null, | ||
2547 | "show": true | ||
2548 | } | ||
2549 | ], | ||
2550 | "yaxis": { | ||
2551 | "align": false, | ||
2552 | "alignLevel": null | ||
2553 | } | ||
2554 | }, | ||
2555 | { | ||
2556 | "aliasColors": {}, | ||
2557 | "bars": false, | ||
2558 | "dashLength": 10, | ||
2559 | "dashes": false, | ||
2560 | "datasource": "Prometheus", | ||
2561 | "editable": true, | ||
2562 | "error": false, | ||
2563 | "fill": 1, | ||
2564 | "grid": { | ||
2565 | "leftLogBase": 1, | ||
2566 | "leftMax": null, | ||
2567 | "leftMin": null, | ||
2568 | "rightLogBase": 1, | ||
2569 | "rightMax": null, | ||
2570 | "rightMin": null | ||
2571 | }, | ||
2572 | "gridPos": { | ||
2573 | "h": 7, | ||
2574 | "w": 8, | ||
2575 | "x": 16, | ||
2576 | "y": 47 | ||
2577 | }, | ||
2578 | "id": 137, | ||
2579 | "legend": { | ||
2580 | "alignAsTable": false, | ||
2581 | "avg": false, | ||
2582 | "current": true, | ||
2583 | "max": true, | ||
2584 | "min": false, | ||
2585 | "rightSide": false, | ||
2586 | "show": true, | ||
2587 | "total": false, | ||
2588 | "values": true | ||
2589 | }, | ||
2590 | "lines": true, | ||
2591 | "linewidth": 1, | ||
2592 | "links": [], | ||
2593 | "maxPerRow": 3, | ||
2594 | "nullPointMode": "null", | ||
2595 | "paceLength": 10, | ||
2596 | "percentage": false, | ||
2597 | "pointradius": 5, | ||
2598 | "points": false, | ||
2599 | "renderer": "flot", | ||
2600 | "repeat": null, | ||
2601 | "repeatIteration": 1553765841423, | ||
2602 | "repeatPanelId": 78, | ||
2603 | "scopedVars": { | ||
2604 | "jvm_memory_pool_nonheap": { | ||
2605 | "selected": false, | ||
2606 | "text": "Code Cache", | ||
2607 | "value": "Code Cache" | ||
2608 | } | ||
2609 | }, | ||
2610 | "seriesOverrides": [], | ||
2611 | "spaceLength": 10, | ||
2612 | "stack": false, | ||
2613 | "steppedLine": false, | ||
2614 | "targets": [ | ||
2615 | { | ||
2616 | "expr": "jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2617 | "format": "time_series", | ||
2618 | "hide": false, | ||
2619 | "interval": "", | ||
2620 | "intervalFactor": 2, | ||
2621 | "legendFormat": "used", | ||
2622 | "metric": "", | ||
2623 | "refId": "A", | ||
2624 | "step": 1800 | ||
2625 | }, | ||
2626 | { | ||
2627 | "expr": "jvm_memory_committed_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2628 | "format": "time_series", | ||
2629 | "hide": false, | ||
2630 | "interval": "", | ||
2631 | "intervalFactor": 2, | ||
2632 | "legendFormat": "commited", | ||
2633 | "metric": "", | ||
2634 | "refId": "B", | ||
2635 | "step": 1800 | ||
2636 | }, | ||
2637 | { | ||
2638 | "expr": "jvm_memory_max_bytes{application=\"$application\", instance=\"$instance\", id=\"$jvm_memory_pool_nonheap\"}", | ||
2639 | "format": "time_series", | ||
2640 | "hide": false, | ||
2641 | "interval": "", | ||
2642 | "intervalFactor": 2, | ||
2643 | "legendFormat": "max", | ||
2644 | "metric": "", | ||
2645 | "refId": "C", | ||
2646 | "step": 1800 | ||
2647 | } | ||
2648 | ], | ||
2649 | "thresholds": [], | ||
2650 | "timeFrom": null, | ||
2651 | "timeRegions": [], | ||
2652 | "timeShift": null, | ||
2653 | "title": "$jvm_memory_pool_nonheap", | ||
2654 | "tooltip": { | ||
2655 | "msResolution": false, | ||
2656 | "shared": true, | ||
2657 | "sort": 0, | ||
2658 | "value_type": "cumulative" | ||
2659 | }, | ||
2660 | "type": "graph", | ||
2661 | "x-axis": true, | ||
2662 | "xaxis": { | ||
2663 | "buckets": null, | ||
2664 | "mode": "time", | ||
2665 | "name": null, | ||
2666 | "show": true, | ||
2667 | "values": [] | ||
2668 | }, | ||
2669 | "y-axis": true, | ||
2670 | "y_formats": ["mbytes", "short"], | ||
2671 | "yaxes": [ | ||
2672 | { | ||
2673 | "format": "bytes", | ||
2674 | "label": null, | ||
2675 | "logBase": 1, | ||
2676 | "max": null, | ||
2677 | "min": 0, | ||
2678 | "show": true | ||
2679 | }, | ||
2680 | { | ||
2681 | "format": "short", | ||
2682 | "label": null, | ||
2683 | "logBase": 1, | ||
2684 | "max": null, | ||
2685 | "min": null, | ||
2686 | "show": true | ||
2687 | } | ||
2688 | ], | ||
2689 | "yaxis": { | ||
2690 | "align": false, | ||
2691 | "alignLevel": null | ||
2692 | } | ||
2693 | }, | ||
2694 | { | ||
2695 | "collapsed": false, | ||
2696 | "gridPos": { | ||
2697 | "h": 1, | ||
2698 | "w": 24, | ||
2699 | "x": 0, | ||
2700 | "y": 54 | ||
2701 | }, | ||
2702 | "id": 131, | ||
2703 | "panels": [], | ||
2704 | "repeat": null, | ||
2705 | "title": "Garbage Collection", | ||
2706 | "type": "row" | ||
2707 | }, | ||
2708 | { | ||
2709 | "aliasColors": {}, | ||
2710 | "bars": false, | ||
2711 | "dashLength": 10, | ||
2712 | "dashes": false, | ||
2713 | "datasource": "Prometheus", | ||
2714 | "fill": 1, | ||
2715 | "gridPos": { | ||
2716 | "h": 7, | ||
2717 | "w": 8, | ||
2718 | "x": 0, | ||
2719 | "y": 55 | ||
2720 | }, | ||
2721 | "id": 98, | ||
2722 | "legend": { | ||
2723 | "avg": false, | ||
2724 | "current": false, | ||
2725 | "max": false, | ||
2726 | "min": false, | ||
2727 | "show": true, | ||
2728 | "total": false, | ||
2729 | "values": false | ||
2730 | }, | ||
2731 | "lines": true, | ||
2732 | "linewidth": 1, | ||
2733 | "links": [], | ||
2734 | "nullPointMode": "null", | ||
2735 | "paceLength": 10, | ||
2736 | "percentage": false, | ||
2737 | "pointradius": 5, | ||
2738 | "points": false, | ||
2739 | "renderer": "flot", | ||
2740 | "seriesOverrides": [], | ||
2741 | "spaceLength": 10, | ||
2742 | "stack": false, | ||
2743 | "steppedLine": false, | ||
2744 | "targets": [ | ||
2745 | { | ||
2746 | "expr": "rate(jvm_gc_pause_seconds_count{application=\"$application\", instance=\"$instance\"}[1m])", | ||
2747 | "format": "time_series", | ||
2748 | "hide": false, | ||
2749 | "intervalFactor": 2, | ||
2750 | "legendFormat": "{{action}} ({{cause}})", | ||
2751 | "refId": "A" | ||
2752 | } | ||
2753 | ], | ||
2754 | "thresholds": [], | ||
2755 | "timeFrom": null, | ||
2756 | "timeRegions": [], | ||
2757 | "timeShift": null, | ||
2758 | "title": "Collections", | ||
2759 | "tooltip": { | ||
2760 | "shared": true, | ||
2761 | "sort": 0, | ||
2762 | "value_type": "individual" | ||
2763 | }, | ||
2764 | "type": "graph", | ||
2765 | "xaxis": { | ||
2766 | "buckets": null, | ||
2767 | "mode": "time", | ||
2768 | "name": null, | ||
2769 | "show": true, | ||
2770 | "values": [] | ||
2771 | }, | ||
2772 | "yaxes": [ | ||
2773 | { | ||
2774 | "format": "ops", | ||
2775 | "label": null, | ||
2776 | "logBase": 1, | ||
2777 | "max": null, | ||
2778 | "min": "0", | ||
2779 | "show": true | ||
2780 | }, | ||
2781 | { | ||
2782 | "format": "short", | ||
2783 | "label": "", | ||
2784 | "logBase": 1, | ||
2785 | "max": null, | ||
2786 | "min": null, | ||
2787 | "show": true | ||
2788 | } | ||
2789 | ], | ||
2790 | "yaxis": { | ||
2791 | "align": false, | ||
2792 | "alignLevel": null | ||
2793 | } | ||
2794 | }, | ||
2795 | { | ||
2796 | "aliasColors": {}, | ||
2797 | "bars": false, | ||
2798 | "dashLength": 10, | ||
2799 | "dashes": false, | ||
2800 | "datasource": "Prometheus", | ||
2801 | "fill": 1, | ||
2802 | "gridPos": { | ||
2803 | "h": 7, | ||
2804 | "w": 8, | ||
2805 | "x": 8, | ||
2806 | "y": 55 | ||
2807 | }, | ||
2808 | "id": 101, | ||
2809 | "legend": { | ||
2810 | "avg": false, | ||
2811 | "current": false, | ||
2812 | "max": false, | ||
2813 | "min": false, | ||
2814 | "show": true, | ||
2815 | "total": false, | ||
2816 | "values": false | ||
2817 | }, | ||
2818 | "lines": true, | ||
2819 | "linewidth": 1, | ||
2820 | "links": [], | ||
2821 | "nullPointMode": "null", | ||
2822 | "paceLength": 10, | ||
2823 | "percentage": false, | ||
2824 | "pointradius": 5, | ||
2825 | "points": false, | ||
2826 | "renderer": "flot", | ||
2827 | "seriesOverrides": [], | ||
2828 | "spaceLength": 10, | ||
2829 | "stack": false, | ||
2830 | "steppedLine": false, | ||
2831 | "targets": [ | ||
2832 | { | ||
2833 | "expr": "rate(jvm_gc_pause_seconds_sum{application=\"$application\", instance=\"$instance\"}[1m])/rate(jvm_gc_pause_seconds_count{application=\"$application\", instance=\"$instance\"}[1m])", | ||
2834 | "format": "time_series", | ||
2835 | "hide": false, | ||
2836 | "instant": false, | ||
2837 | "intervalFactor": 1, | ||
2838 | "legendFormat": "avg {{action}} ({{cause}})", | ||
2839 | "refId": "A" | ||
2840 | }, | ||
2841 | { | ||
2842 | "expr": "jvm_gc_pause_seconds_max{application=\"$application\", instance=\"$instance\"}", | ||
2843 | "format": "time_series", | ||
2844 | "hide": false, | ||
2845 | "instant": false, | ||
2846 | "intervalFactor": 1, | ||
2847 | "legendFormat": "max {{action}} ({{cause}})", | ||
2848 | "refId": "B" | ||
2849 | } | ||
2850 | ], | ||
2851 | "thresholds": [], | ||
2852 | "timeFrom": null, | ||
2853 | "timeRegions": [], | ||
2854 | "timeShift": null, | ||
2855 | "title": "Pause Durations", | ||
2856 | "tooltip": { | ||
2857 | "shared": true, | ||
2858 | "sort": 0, | ||
2859 | "value_type": "individual" | ||
2860 | }, | ||
2861 | "type": "graph", | ||
2862 | "xaxis": { | ||
2863 | "buckets": null, | ||
2864 | "mode": "time", | ||
2865 | "name": null, | ||
2866 | "show": true, | ||
2867 | "values": [] | ||
2868 | }, | ||
2869 | "yaxes": [ | ||
2870 | { | ||
2871 | "format": "s", | ||
2872 | "label": null, | ||
2873 | "logBase": 1, | ||
2874 | "max": null, | ||
2875 | "min": "0", | ||
2876 | "show": true | ||
2877 | }, | ||
2878 | { | ||
2879 | "format": "short", | ||
2880 | "label": "", | ||
2881 | "logBase": 1, | ||
2882 | "max": null, | ||
2883 | "min": null, | ||
2884 | "show": true | ||
2885 | } | ||
2886 | ], | ||
2887 | "yaxis": { | ||
2888 | "align": false, | ||
2889 | "alignLevel": null | ||
2890 | } | ||
2891 | }, | ||
2892 | { | ||
2893 | "aliasColors": {}, | ||
2894 | "bars": false, | ||
2895 | "dashLength": 10, | ||
2896 | "dashes": false, | ||
2897 | "datasource": "Prometheus", | ||
2898 | "fill": 1, | ||
2899 | "gridPos": { | ||
2900 | "h": 7, | ||
2901 | "w": 8, | ||
2902 | "x": 16, | ||
2903 | "y": 55 | ||
2904 | }, | ||
2905 | "id": 99, | ||
2906 | "legend": { | ||
2907 | "avg": false, | ||
2908 | "current": false, | ||
2909 | "max": false, | ||
2910 | "min": false, | ||
2911 | "show": true, | ||
2912 | "total": false, | ||
2913 | "values": false | ||
2914 | }, | ||
2915 | "lines": true, | ||
2916 | "linewidth": 1, | ||
2917 | "links": [], | ||
2918 | "nullPointMode": "null", | ||
2919 | "paceLength": 10, | ||
2920 | "percentage": false, | ||
2921 | "pointradius": 5, | ||
2922 | "points": false, | ||
2923 | "renderer": "flot", | ||
2924 | "seriesOverrides": [], | ||
2925 | "spaceLength": 10, | ||
2926 | "stack": false, | ||
2927 | "steppedLine": false, | ||
2928 | "targets": [ | ||
2929 | { | ||
2930 | "expr": "rate(jvm_gc_memory_allocated_bytes_total{application=\"$application\", instance=\"$instance\"}[1m])", | ||
2931 | "format": "time_series", | ||
2932 | "interval": "", | ||
2933 | "intervalFactor": 1, | ||
2934 | "legendFormat": "allocated", | ||
2935 | "refId": "A" | ||
2936 | }, | ||
2937 | { | ||
2938 | "expr": "rate(jvm_gc_memory_promoted_bytes_total{application=\"$application\", instance=\"$instance\"}[1m])", | ||
2939 | "format": "time_series", | ||
2940 | "interval": "", | ||
2941 | "intervalFactor": 1, | ||
2942 | "legendFormat": "promoted", | ||
2943 | "refId": "B" | ||
2944 | } | ||
2945 | ], | ||
2946 | "thresholds": [], | ||
2947 | "timeFrom": null, | ||
2948 | "timeRegions": [], | ||
2949 | "timeShift": null, | ||
2950 | "title": "Allocated/Promoted", | ||
2951 | "tooltip": { | ||
2952 | "shared": true, | ||
2953 | "sort": 0, | ||
2954 | "value_type": "individual" | ||
2955 | }, | ||
2956 | "type": "graph", | ||
2957 | "xaxis": { | ||
2958 | "buckets": null, | ||
2959 | "mode": "time", | ||
2960 | "name": null, | ||
2961 | "show": true, | ||
2962 | "values": [] | ||
2963 | }, | ||
2964 | "yaxes": [ | ||
2965 | { | ||
2966 | "format": "bytes", | ||
2967 | "label": null, | ||
2968 | "logBase": 1, | ||
2969 | "max": null, | ||
2970 | "min": "0", | ||
2971 | "show": true | ||
2972 | }, | ||
2973 | { | ||
2974 | "format": "short", | ||
2975 | "label": null, | ||
2976 | "logBase": 1, | ||
2977 | "max": null, | ||
2978 | "min": null, | ||
2979 | "show": true | ||
2980 | } | ||
2981 | ], | ||
2982 | "yaxis": { | ||
2983 | "align": false, | ||
2984 | "alignLevel": null | ||
2985 | } | ||
2986 | }, | ||
2987 | { | ||
2988 | "collapsed": false, | ||
2989 | "gridPos": { | ||
2990 | "h": 1, | ||
2991 | "w": 24, | ||
2992 | "x": 0, | ||
2993 | "y": 62 | ||
2994 | }, | ||
2995 | "id": 132, | ||
2996 | "panels": [], | ||
2997 | "repeat": null, | ||
2998 | "title": "Classloading", | ||
2999 | "type": "row" | ||
3000 | }, | ||
3001 | { | ||
3002 | "aliasColors": {}, | ||
3003 | "bars": false, | ||
3004 | "dashLength": 10, | ||
3005 | "dashes": false, | ||
3006 | "datasource": "Prometheus", | ||
3007 | "editable": true, | ||
3008 | "error": false, | ||
3009 | "fill": 1, | ||
3010 | "grid": { | ||
3011 | "leftLogBase": 1, | ||
3012 | "leftMax": null, | ||
3013 | "leftMin": null, | ||
3014 | "rightLogBase": 1, | ||
3015 | "rightMax": null, | ||
3016 | "rightMin": null | ||
3017 | }, | ||
3018 | "gridPos": { | ||
3019 | "h": 7, | ||
3020 | "w": 12, | ||
3021 | "x": 0, | ||
3022 | "y": 63 | ||
3023 | }, | ||
3024 | "id": 37, | ||
3025 | "legend": { | ||
3026 | "avg": false, | ||
3027 | "current": false, | ||
3028 | "max": false, | ||
3029 | "min": false, | ||
3030 | "show": true, | ||
3031 | "total": false, | ||
3032 | "values": false | ||
3033 | }, | ||
3034 | "lines": true, | ||
3035 | "linewidth": 1, | ||
3036 | "links": [], | ||
3037 | "nullPointMode": "null", | ||
3038 | "paceLength": 10, | ||
3039 | "percentage": false, | ||
3040 | "pointradius": 5, | ||
3041 | "points": false, | ||
3042 | "renderer": "flot", | ||
3043 | "seriesOverrides": [], | ||
3044 | "spaceLength": 10, | ||
3045 | "stack": false, | ||
3046 | "steppedLine": false, | ||
3047 | "targets": [ | ||
3048 | { | ||
3049 | "expr": "jvm_classes_loaded{application=\"$application\", instance=\"$instance\"} or jvm_classes_loaded_classes{application=\"$application\", instance=\"$instance\"}", | ||
3050 | "format": "time_series", | ||
3051 | "intervalFactor": 2, | ||
3052 | "legendFormat": "loaded", | ||
3053 | "metric": "", | ||
3054 | "refId": "A", | ||
3055 | "step": 1200 | ||
3056 | } | ||
3057 | ], | ||
3058 | "thresholds": [], | ||
3059 | "timeFrom": null, | ||
3060 | "timeRegions": [], | ||
3061 | "timeShift": null, | ||
3062 | "title": "Classes loaded", | ||
3063 | "tooltip": { | ||
3064 | "msResolution": false, | ||
3065 | "shared": true, | ||
3066 | "sort": 0, | ||
3067 | "value_type": "cumulative" | ||
3068 | }, | ||
3069 | "type": "graph", | ||
3070 | "x-axis": true, | ||
3071 | "xaxis": { | ||
3072 | "buckets": null, | ||
3073 | "mode": "time", | ||
3074 | "name": null, | ||
3075 | "show": true, | ||
3076 | "values": [] | ||
3077 | }, | ||
3078 | "y-axis": true, | ||
3079 | "y_formats": ["short", "short"], | ||
3080 | "yaxes": [ | ||
3081 | { | ||
3082 | "format": "short", | ||
3083 | "label": null, | ||
3084 | "logBase": 1, | ||
3085 | "max": null, | ||
3086 | "min": 0, | ||
3087 | "show": true | ||
3088 | }, | ||
3089 | { | ||
3090 | "format": "short", | ||
3091 | "label": null, | ||
3092 | "logBase": 1, | ||
3093 | "max": null, | ||
3094 | "min": null, | ||
3095 | "show": true | ||
3096 | } | ||
3097 | ], | ||
3098 | "yaxis": { | ||
3099 | "align": false, | ||
3100 | "alignLevel": null | ||
3101 | } | ||
3102 | }, | ||
3103 | { | ||
3104 | "aliasColors": {}, | ||
3105 | "bars": false, | ||
3106 | "dashLength": 10, | ||
3107 | "dashes": false, | ||
3108 | "datasource": "Prometheus", | ||
3109 | "editable": true, | ||
3110 | "error": false, | ||
3111 | "fill": 1, | ||
3112 | "grid": { | ||
3113 | "leftLogBase": 1, | ||
3114 | "leftMax": null, | ||
3115 | "leftMin": null, | ||
3116 | "rightLogBase": 1, | ||
3117 | "rightMax": null, | ||
3118 | "rightMin": null | ||
3119 | }, | ||
3120 | "gridPos": { | ||
3121 | "h": 7, | ||
3122 | "w": 12, | ||
3123 | "x": 12, | ||
3124 | "y": 63 | ||
3125 | }, | ||
3126 | "id": 38, | ||
3127 | "legend": { | ||
3128 | "avg": false, | ||
3129 | "current": false, | ||
3130 | "max": false, | ||
3131 | "min": false, | ||
3132 | "show": true, | ||
3133 | "total": false, | ||
3134 | "values": false | ||
3135 | }, | ||
3136 | "lines": true, | ||
3137 | "linewidth": 1, | ||
3138 | "links": [], | ||
3139 | "nullPointMode": "null", | ||
3140 | "paceLength": 10, | ||
3141 | "percentage": false, | ||
3142 | "pointradius": 5, | ||
3143 | "points": false, | ||
3144 | "renderer": "flot", | ||
3145 | "seriesOverrides": [], | ||
3146 | "spaceLength": 10, | ||
3147 | "stack": false, | ||
3148 | "steppedLine": false, | ||
3149 | "targets": [ | ||
3150 | { | ||
3151 | "expr": "delta(jvm_classes_loaded{application=\"$application\",instance=\"$instance\"}[5m]) or delta(jvm_classes_loaded_classes{application=\"$application\",instance=\"$instance\"}[5m])", | ||
3152 | "format": "time_series", | ||
3153 | "hide": false, | ||
3154 | "interval": "", | ||
3155 | "intervalFactor": 2, | ||
3156 | "legendFormat": "delta", | ||
3157 | "metric": "", | ||
3158 | "refId": "A", | ||
3159 | "step": 1200 | ||
3160 | } | ||
3161 | ], | ||
3162 | "thresholds": [], | ||
3163 | "timeFrom": null, | ||
3164 | "timeRegions": [], | ||
3165 | "timeShift": null, | ||
3166 | "title": "Class delta (5m)", | ||
3167 | "tooltip": { | ||
3168 | "msResolution": false, | ||
3169 | "shared": true, | ||
3170 | "sort": 0, | ||
3171 | "value_type": "cumulative" | ||
3172 | }, | ||
3173 | "type": "graph", | ||
3174 | "x-axis": true, | ||
3175 | "xaxis": { | ||
3176 | "buckets": null, | ||
3177 | "mode": "time", | ||
3178 | "name": null, | ||
3179 | "show": true, | ||
3180 | "values": [] | ||
3181 | }, | ||
3182 | "y-axis": true, | ||
3183 | "y_formats": ["ops", "short"], | ||
3184 | "yaxes": [ | ||
3185 | { | ||
3186 | "decimals": null, | ||
3187 | "format": "short", | ||
3188 | "label": "", | ||
3189 | "logBase": 1, | ||
3190 | "max": null, | ||
3191 | "min": null, | ||
3192 | "show": true | ||
3193 | }, | ||
3194 | { | ||
3195 | "format": "short", | ||
3196 | "label": null, | ||
3197 | "logBase": 1, | ||
3198 | "max": null, | ||
3199 | "min": null, | ||
3200 | "show": true | ||
3201 | } | ||
3202 | ], | ||
3203 | "yaxis": { | ||
3204 | "align": false, | ||
3205 | "alignLevel": null | ||
3206 | } | ||
3207 | }, | ||
3208 | { | ||
3209 | "collapsed": false, | ||
3210 | "gridPos": { | ||
3211 | "h": 1, | ||
3212 | "w": 24, | ||
3213 | "x": 0, | ||
3214 | "y": 70 | ||
3215 | }, | ||
3216 | "id": 133, | ||
3217 | "panels": [], | ||
3218 | "repeat": null, | ||
3219 | "title": "Buffer Pools", | ||
3220 | "type": "row" | ||
3221 | }, | ||
3222 | { | ||
3223 | "aliasColors": {}, | ||
3224 | "bars": false, | ||
3225 | "dashLength": 10, | ||
3226 | "dashes": false, | ||
3227 | "datasource": "Prometheus", | ||
3228 | "editable": true, | ||
3229 | "error": false, | ||
3230 | "fill": 1, | ||
3231 | "grid": { | ||
3232 | "leftLogBase": 1, | ||
3233 | "leftMax": null, | ||
3234 | "leftMin": null, | ||
3235 | "rightLogBase": 1, | ||
3236 | "rightMax": null, | ||
3237 | "rightMin": null | ||
3238 | }, | ||
3239 | "gridPos": { | ||
3240 | "h": 7, | ||
3241 | "w": 6, | ||
3242 | "x": 0, | ||
3243 | "y": 71 | ||
3244 | }, | ||
3245 | "id": 33, | ||
3246 | "legend": { | ||
3247 | "avg": false, | ||
3248 | "current": false, | ||
3249 | "max": false, | ||
3250 | "min": false, | ||
3251 | "show": true, | ||
3252 | "total": false, | ||
3253 | "values": false | ||
3254 | }, | ||
3255 | "lines": true, | ||
3256 | "linewidth": 1, | ||
3257 | "links": [], | ||
3258 | "nullPointMode": "null", | ||
3259 | "paceLength": 10, | ||
3260 | "percentage": false, | ||
3261 | "pointradius": 5, | ||
3262 | "points": false, | ||
3263 | "renderer": "flot", | ||
3264 | "seriesOverrides": [], | ||
3265 | "spaceLength": 10, | ||
3266 | "stack": false, | ||
3267 | "steppedLine": false, | ||
3268 | "targets": [ | ||
3269 | { | ||
3270 | "expr": "jvm_buffer_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"direct\"}", | ||
3271 | "format": "time_series", | ||
3272 | "intervalFactor": 2, | ||
3273 | "legendFormat": "used", | ||
3274 | "metric": "", | ||
3275 | "refId": "A", | ||
3276 | "step": 2400 | ||
3277 | }, | ||
3278 | { | ||
3279 | "expr": "jvm_buffer_total_capacity_bytes{application=\"$application\", instance=\"$instance\", id=\"direct\"}", | ||
3280 | "format": "time_series", | ||
3281 | "intervalFactor": 2, | ||
3282 | "legendFormat": "capacity", | ||
3283 | "metric": "", | ||
3284 | "refId": "B", | ||
3285 | "step": 2400 | ||
3286 | } | ||
3287 | ], | ||
3288 | "thresholds": [], | ||
3289 | "timeFrom": null, | ||
3290 | "timeRegions": [], | ||
3291 | "timeShift": null, | ||
3292 | "title": "Direct Buffers", | ||
3293 | "tooltip": { | ||
3294 | "msResolution": false, | ||
3295 | "shared": true, | ||
3296 | "sort": 0, | ||
3297 | "value_type": "cumulative" | ||
3298 | }, | ||
3299 | "type": "graph", | ||
3300 | "x-axis": true, | ||
3301 | "xaxis": { | ||
3302 | "buckets": null, | ||
3303 | "mode": "time", | ||
3304 | "name": null, | ||
3305 | "show": true, | ||
3306 | "values": [] | ||
3307 | }, | ||
3308 | "y-axis": true, | ||
3309 | "y_formats": ["short", "short"], | ||
3310 | "yaxes": [ | ||
3311 | { | ||
3312 | "format": "bytes", | ||
3313 | "label": null, | ||
3314 | "logBase": 1, | ||
3315 | "max": null, | ||
3316 | "min": 0, | ||
3317 | "show": true | ||
3318 | }, | ||
3319 | { | ||
3320 | "format": "short", | ||
3321 | "label": null, | ||
3322 | "logBase": 1, | ||
3323 | "max": null, | ||
3324 | "min": null, | ||
3325 | "show": true | ||
3326 | } | ||
3327 | ], | ||
3328 | "yaxis": { | ||
3329 | "align": false, | ||
3330 | "alignLevel": null | ||
3331 | } | ||
3332 | }, | ||
3333 | { | ||
3334 | "aliasColors": {}, | ||
3335 | "bars": false, | ||
3336 | "dashLength": 10, | ||
3337 | "dashes": false, | ||
3338 | "datasource": "Prometheus", | ||
3339 | "editable": true, | ||
3340 | "error": false, | ||
3341 | "fill": 1, | ||
3342 | "grid": { | ||
3343 | "leftLogBase": 1, | ||
3344 | "leftMax": null, | ||
3345 | "leftMin": null, | ||
3346 | "rightLogBase": 1, | ||
3347 | "rightMax": null, | ||
3348 | "rightMin": null | ||
3349 | }, | ||
3350 | "gridPos": { | ||
3351 | "h": 7, | ||
3352 | "w": 6, | ||
3353 | "x": 6, | ||
3354 | "y": 71 | ||
3355 | }, | ||
3356 | "id": 83, | ||
3357 | "legend": { | ||
3358 | "avg": false, | ||
3359 | "current": false, | ||
3360 | "max": false, | ||
3361 | "min": false, | ||
3362 | "show": true, | ||
3363 | "total": false, | ||
3364 | "values": false | ||
3365 | }, | ||
3366 | "lines": true, | ||
3367 | "linewidth": 1, | ||
3368 | "links": [], | ||
3369 | "nullPointMode": "null", | ||
3370 | "paceLength": 10, | ||
3371 | "percentage": false, | ||
3372 | "pointradius": 5, | ||
3373 | "points": false, | ||
3374 | "renderer": "flot", | ||
3375 | "seriesOverrides": [], | ||
3376 | "spaceLength": 10, | ||
3377 | "stack": false, | ||
3378 | "steppedLine": false, | ||
3379 | "targets": [ | ||
3380 | { | ||
3381 | "expr": "jvm_buffer_count{application=\"$application\", instance=\"$instance\", id=\"direct\"} or jvm_buffer_count_buffers{application=\"$application\", instance=\"$instance\", id=\"direct\"}", | ||
3382 | "format": "time_series", | ||
3383 | "intervalFactor": 2, | ||
3384 | "legendFormat": "count", | ||
3385 | "metric": "", | ||
3386 | "refId": "A", | ||
3387 | "step": 2400 | ||
3388 | } | ||
3389 | ], | ||
3390 | "thresholds": [], | ||
3391 | "timeFrom": null, | ||
3392 | "timeRegions": [], | ||
3393 | "timeShift": null, | ||
3394 | "title": "Direct Buffers", | ||
3395 | "tooltip": { | ||
3396 | "msResolution": false, | ||
3397 | "shared": true, | ||
3398 | "sort": 0, | ||
3399 | "value_type": "cumulative" | ||
3400 | }, | ||
3401 | "type": "graph", | ||
3402 | "x-axis": true, | ||
3403 | "xaxis": { | ||
3404 | "buckets": null, | ||
3405 | "mode": "time", | ||
3406 | "name": null, | ||
3407 | "show": true, | ||
3408 | "values": [] | ||
3409 | }, | ||
3410 | "y-axis": true, | ||
3411 | "y_formats": ["short", "short"], | ||
3412 | "yaxes": [ | ||
3413 | { | ||
3414 | "decimals": 0, | ||
3415 | "format": "short", | ||
3416 | "label": null, | ||
3417 | "logBase": 1, | ||
3418 | "max": null, | ||
3419 | "min": 0, | ||
3420 | "show": true | ||
3421 | }, | ||
3422 | { | ||
3423 | "format": "short", | ||
3424 | "label": null, | ||
3425 | "logBase": 1, | ||
3426 | "max": null, | ||
3427 | "min": null, | ||
3428 | "show": true | ||
3429 | } | ||
3430 | ], | ||
3431 | "yaxis": { | ||
3432 | "align": false, | ||
3433 | "alignLevel": null | ||
3434 | } | ||
3435 | }, | ||
3436 | { | ||
3437 | "aliasColors": {}, | ||
3438 | "bars": false, | ||
3439 | "dashLength": 10, | ||
3440 | "dashes": false, | ||
3441 | "datasource": "Prometheus", | ||
3442 | "editable": true, | ||
3443 | "error": false, | ||
3444 | "fill": 1, | ||
3445 | "grid": { | ||
3446 | "leftLogBase": 1, | ||
3447 | "leftMax": null, | ||
3448 | "leftMin": null, | ||
3449 | "rightLogBase": 1, | ||
3450 | "rightMax": null, | ||
3451 | "rightMin": null | ||
3452 | }, | ||
3453 | "gridPos": { | ||
3454 | "h": 7, | ||
3455 | "w": 6, | ||
3456 | "x": 12, | ||
3457 | "y": 71 | ||
3458 | }, | ||
3459 | "id": 85, | ||
3460 | "legend": { | ||
3461 | "avg": false, | ||
3462 | "current": false, | ||
3463 | "max": false, | ||
3464 | "min": false, | ||
3465 | "show": true, | ||
3466 | "total": false, | ||
3467 | "values": false | ||
3468 | }, | ||
3469 | "lines": true, | ||
3470 | "linewidth": 1, | ||
3471 | "links": [], | ||
3472 | "nullPointMode": "null", | ||
3473 | "paceLength": 10, | ||
3474 | "percentage": false, | ||
3475 | "pointradius": 5, | ||
3476 | "points": false, | ||
3477 | "renderer": "flot", | ||
3478 | "seriesOverrides": [], | ||
3479 | "spaceLength": 10, | ||
3480 | "stack": false, | ||
3481 | "steppedLine": false, | ||
3482 | "targets": [ | ||
3483 | { | ||
3484 | "expr": "jvm_buffer_memory_used_bytes{application=\"$application\", instance=\"$instance\", id=\"mapped\"}", | ||
3485 | "format": "time_series", | ||
3486 | "intervalFactor": 2, | ||
3487 | "legendFormat": "used", | ||
3488 | "metric": "", | ||
3489 | "refId": "A", | ||
3490 | "step": 2400 | ||
3491 | }, | ||
3492 | { | ||
3493 | "expr": "jvm_buffer_total_capacity_bytes{application=\"$application\", instance=\"$instance\", id=\"mapped\"}", | ||
3494 | "format": "time_series", | ||
3495 | "intervalFactor": 2, | ||
3496 | "legendFormat": "capacity", | ||
3497 | "metric": "", | ||
3498 | "refId": "B", | ||
3499 | "step": 2400 | ||
3500 | } | ||
3501 | ], | ||
3502 | "thresholds": [], | ||
3503 | "timeFrom": null, | ||
3504 | "timeRegions": [], | ||
3505 | "timeShift": null, | ||
3506 | "title": "Mapped Buffers", | ||
3507 | "tooltip": { | ||
3508 | "msResolution": false, | ||
3509 | "shared": true, | ||
3510 | "sort": 0, | ||
3511 | "value_type": "cumulative" | ||
3512 | }, | ||
3513 | "type": "graph", | ||
3514 | "x-axis": true, | ||
3515 | "xaxis": { | ||
3516 | "buckets": null, | ||
3517 | "mode": "time", | ||
3518 | "name": null, | ||
3519 | "show": true, | ||
3520 | "values": [] | ||
3521 | }, | ||
3522 | "y-axis": true, | ||
3523 | "y_formats": ["short", "short"], | ||
3524 | "yaxes": [ | ||
3525 | { | ||
3526 | "format": "bytes", | ||
3527 | "label": null, | ||
3528 | "logBase": 1, | ||
3529 | "max": null, | ||
3530 | "min": 0, | ||
3531 | "show": true | ||
3532 | }, | ||
3533 | { | ||
3534 | "format": "short", | ||
3535 | "label": null, | ||
3536 | "logBase": 1, | ||
3537 | "max": null, | ||
3538 | "min": null, | ||
3539 | "show": true | ||
3540 | } | ||
3541 | ], | ||
3542 | "yaxis": { | ||
3543 | "align": false, | ||
3544 | "alignLevel": null | ||
3545 | } | ||
3546 | }, | ||
3547 | { | ||
3548 | "aliasColors": {}, | ||
3549 | "bars": false, | ||
3550 | "dashLength": 10, | ||
3551 | "dashes": false, | ||
3552 | "datasource": "Prometheus", | ||
3553 | "editable": true, | ||
3554 | "error": false, | ||
3555 | "fill": 1, | ||
3556 | "grid": { | ||
3557 | "leftLogBase": 1, | ||
3558 | "leftMax": null, | ||
3559 | "leftMin": null, | ||
3560 | "rightLogBase": 1, | ||
3561 | "rightMax": null, | ||
3562 | "rightMin": null | ||
3563 | }, | ||
3564 | "gridPos": { | ||
3565 | "h": 7, | ||
3566 | "w": 6, | ||
3567 | "x": 18, | ||
3568 | "y": 71 | ||
3569 | }, | ||
3570 | "id": 84, | ||
3571 | "legend": { | ||
3572 | "avg": false, | ||
3573 | "current": false, | ||
3574 | "max": false, | ||
3575 | "min": false, | ||
3576 | "show": true, | ||
3577 | "total": false, | ||
3578 | "values": false | ||
3579 | }, | ||
3580 | "lines": true, | ||
3581 | "linewidth": 1, | ||
3582 | "links": [], | ||
3583 | "nullPointMode": "null", | ||
3584 | "paceLength": 10, | ||
3585 | "percentage": false, | ||
3586 | "pointradius": 5, | ||
3587 | "points": false, | ||
3588 | "renderer": "flot", | ||
3589 | "seriesOverrides": [], | ||
3590 | "spaceLength": 10, | ||
3591 | "stack": false, | ||
3592 | "steppedLine": false, | ||
3593 | "targets": [ | ||
3594 | { | ||
3595 | "expr": "jvm_buffer_count{application=\"$application\", instance=\"$instance\", id=\"mapped\"} or jvm_buffer_count_buffers{application=\"$application\", instance=\"$instance\", id=\"mapped\"}", | ||
3596 | "format": "time_series", | ||
3597 | "intervalFactor": 2, | ||
3598 | "legendFormat": "count", | ||
3599 | "metric": "", | ||
3600 | "refId": "A", | ||
3601 | "step": 2400 | ||
3602 | } | ||
3603 | ], | ||
3604 | "thresholds": [], | ||
3605 | "timeFrom": null, | ||
3606 | "timeRegions": [], | ||
3607 | "timeShift": null, | ||
3608 | "title": "Mapped Buffers", | ||
3609 | "tooltip": { | ||
3610 | "msResolution": false, | ||
3611 | "shared": true, | ||
3612 | "sort": 0, | ||
3613 | "value_type": "cumulative" | ||
3614 | }, | ||
3615 | "type": "graph", | ||
3616 | "x-axis": true, | ||
3617 | "xaxis": { | ||
3618 | "buckets": null, | ||
3619 | "mode": "time", | ||
3620 | "name": null, | ||
3621 | "show": true, | ||
3622 | "values": [] | ||
3623 | }, | ||
3624 | "y-axis": true, | ||
3625 | "y_formats": ["short", "short"], | ||
3626 | "yaxes": [ | ||
3627 | { | ||
3628 | "decimals": 0, | ||
3629 | "format": "short", | ||
3630 | "label": null, | ||
3631 | "logBase": 1, | ||
3632 | "max": null, | ||
3633 | "min": 0, | ||
3634 | "show": true | ||
3635 | }, | ||
3636 | { | ||
3637 | "format": "short", | ||
3638 | "label": null, | ||
3639 | "logBase": 1, | ||
3640 | "max": null, | ||
3641 | "min": null, | ||
3642 | "show": true | ||
3643 | } | ||
3644 | ], | ||
3645 | "yaxis": { | ||
3646 | "align": false, | ||
3647 | "alignLevel": null | ||
3648 | } | ||
3649 | } | ||
3650 | ], | ||
3651 | "refresh": "10s", | ||
3652 | "schemaVersion": 18, | ||
3653 | "style": "dark", | ||
3654 | "tags": [], | ||
3655 | "templating": { | ||
3656 | "list": [ | ||
3657 | { | ||
3658 | "allValue": null, | ||
3659 | "current": { | ||
3660 | "text": "test", | ||
3661 | "value": "test" | ||
3662 | }, | ||
3663 | "datasource": "Prometheus", | ||
3664 | "definition": "", | ||
3665 | "hide": 0, | ||
3666 | "includeAll": false, | ||
3667 | "label": "Application", | ||
3668 | "multi": false, | ||
3669 | "name": "application", | ||
3670 | "options": [], | ||
3671 | "query": "label_values(application)", | ||
3672 | "refresh": 2, | ||
3673 | "regex": "", | ||
3674 | "skipUrlSync": false, | ||
3675 | "sort": 0, | ||
3676 | "tagValuesQuery": "", | ||
3677 | "tags": [], | ||
3678 | "tagsQuery": "", | ||
3679 | "type": "query", | ||
3680 | "useTags": false | ||
3681 | }, | ||
3682 | { | ||
3683 | "allFormat": "glob", | ||
3684 | "allValue": null, | ||
3685 | "current": { | ||
3686 | "text": "localhost:8080", | ||
3687 | "value": "localhost:8080" | ||
3688 | }, | ||
3689 | "datasource": "Prometheus", | ||
3690 | "definition": "", | ||
3691 | "hide": 0, | ||
3692 | "includeAll": false, | ||
3693 | "label": "Instance", | ||
3694 | "multi": false, | ||
3695 | "multiFormat": "glob", | ||
3696 | "name": "instance", | ||
3697 | "options": [], | ||
3698 | "query": "label_values(jvm_memory_used_bytes{application=\"$application\"}, instance)", | ||
3699 | "refresh": 2, | ||
3700 | "regex": "", | ||
3701 | "skipUrlSync": false, | ||
3702 | "sort": 0, | ||
3703 | "tagValuesQuery": "", | ||
3704 | "tags": [], | ||
3705 | "tagsQuery": "", | ||
3706 | "type": "query", | ||
3707 | "useTags": false | ||
3708 | }, | ||
3709 | { | ||
3710 | "allFormat": "glob", | ||
3711 | "allValue": null, | ||
3712 | "current": { | ||
3713 | "text": "All", | ||
3714 | "value": "$__all" | ||
3715 | }, | ||
3716 | "datasource": "Prometheus", | ||
3717 | "definition": "", | ||
3718 | "hide": 0, | ||
3719 | "includeAll": true, | ||
3720 | "label": "JVM Memory Pools Heap", | ||
3721 | "multi": false, | ||
3722 | "multiFormat": "glob", | ||
3723 | "name": "jvm_memory_pool_heap", | ||
3724 | "options": [], | ||
3725 | "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"heap\"},id)", | ||
3726 | "refresh": 1, | ||
3727 | "regex": "", | ||
3728 | "skipUrlSync": false, | ||
3729 | "sort": 1, | ||
3730 | "tagValuesQuery": "", | ||
3731 | "tags": [], | ||
3732 | "tagsQuery": "", | ||
3733 | "type": "query", | ||
3734 | "useTags": false | ||
3735 | }, | ||
3736 | { | ||
3737 | "allFormat": "glob", | ||
3738 | "allValue": null, | ||
3739 | "current": { | ||
3740 | "text": "All", | ||
3741 | "value": "$__all" | ||
3742 | }, | ||
3743 | "datasource": "Prometheus", | ||
3744 | "definition": "", | ||
3745 | "hide": 0, | ||
3746 | "includeAll": true, | ||
3747 | "label": "JVM Memory Pools Non-Heap", | ||
3748 | "multi": false, | ||
3749 | "multiFormat": "glob", | ||
3750 | "name": "jvm_memory_pool_nonheap", | ||
3751 | "options": [], | ||
3752 | "query": "label_values(jvm_memory_used_bytes{application=\"$application\", instance=\"$instance\", area=\"nonheap\"},id)", | ||
3753 | "refresh": 1, | ||
3754 | "regex": "", | ||
3755 | "skipUrlSync": false, | ||
3756 | "sort": 2, | ||
3757 | "tagValuesQuery": "", | ||
3758 | "tags": [], | ||
3759 | "tagsQuery": "", | ||
3760 | "type": "query", | ||
3761 | "useTags": false | ||
3762 | } | ||
3763 | ] | ||
3764 | }, | ||
3765 | "time": { | ||
3766 | "from": "now-30m", | ||
3767 | "to": "now" | ||
3768 | }, | ||
3769 | "timepicker": { | ||
3770 | "now": true, | ||
3771 | "refresh_intervals": ["5s", "10s", "30s", "1m", "5m", "15m", "30m", "1h", "2h", "1d"], | ||
3772 | "time_options": ["5m", "15m", "1h", "6h", "12h", "24h", "2d", "7d", "30d"] | ||
3773 | }, | ||
3774 | "timezone": "browser", | ||
3775 | "title": "JVM (Micrometer)", | ||
3776 | "uid": "Ud1CFe3iz", | ||
3777 | "version": 1 | ||
3778 | } |
File src/main/docker/grafana/provisioning/dashboards/dashboard.yml added (mode: 100644) (index 0000000..4817a83) | |||
1 | apiVersion: 1 | ||
2 | |||
3 | providers: | ||
4 | - name: 'Prometheus' | ||
5 | orgId: 1 | ||
6 | folder: '' | ||
7 | type: file | ||
8 | disableDeletion: false | ||
9 | editable: true | ||
10 | options: | ||
11 | path: /etc/grafana/provisioning/dashboards |
File src/main/docker/grafana/provisioning/datasources/datasource.yml added (mode: 100644) (index 0000000..57b2bb3) | |||
1 | apiVersion: 1 | ||
2 | |||
3 | # list of datasources that should be deleted from the database | ||
4 | deleteDatasources: | ||
5 | - name: Prometheus | ||
6 | orgId: 1 | ||
7 | |||
8 | # list of datasources to insert/update depending | ||
9 | # whats available in the database | ||
10 | datasources: | ||
11 | # <string, required> name of the datasource. Required | ||
12 | - name: Prometheus | ||
13 | # <string, required> datasource type. Required | ||
14 | type: prometheus | ||
15 | # <string, required> access mode. direct or proxy. Required | ||
16 | access: proxy | ||
17 | # <int> org id. will default to orgId 1 if not specified | ||
18 | orgId: 1 | ||
19 | # <string> url | ||
20 | # On MacOS, replace localhost by host.docker.internal | ||
21 | url: http://localhost:9090 | ||
22 | # <string> database password, if used | ||
23 | password: | ||
24 | # <string> database user, if used | ||
25 | user: | ||
26 | # <string> database name, if used | ||
27 | database: | ||
28 | # <bool> enable/disable basic auth | ||
29 | basicAuth: false | ||
30 | # <string> basic auth username | ||
31 | basicAuthUser: admin | ||
32 | # <string> basic auth password | ||
33 | basicAuthPassword: admin | ||
34 | # <bool> enable/disable with credentials headers | ||
35 | withCredentials: | ||
36 | # <bool> mark as default datasource. Max one per org | ||
37 | isDefault: true | ||
38 | # <map> fields that will be converted to json and stored in json_data | ||
39 | jsonData: | ||
40 | graphiteVersion: '1.1' | ||
41 | tlsAuth: false | ||
42 | tlsAuthWithCACert: false | ||
43 | # <string> json object of data that will be encrypted. | ||
44 | secureJsonData: | ||
45 | tlsCACert: '...' | ||
46 | tlsClientCert: '...' | ||
47 | tlsClientKey: '...' | ||
48 | version: 1 | ||
49 | # <bool> allow users to edit datasources from the UI. | ||
50 | editable: true |
File src/main/docker/monitoring.yml added (mode: 100644) (index 0000000..4d20182) | |||
1 | version: '2' | ||
2 | services: | ||
3 | honlap-prometheus: | ||
4 | image: prom/prometheus:v2.16.0 | ||
5 | volumes: | ||
6 | - ./prometheus/:/etc/prometheus/ | ||
7 | command: | ||
8 | - '--config.file=/etc/prometheus/prometheus.yml' | ||
9 | ports: | ||
10 | - 9090:9090 | ||
11 | # On MacOS, remove next line and replace localhost by host.docker.internal in prometheus/prometheus.yml and | ||
12 | # grafana/provisioning/datasources/datasource.yml | ||
13 | network_mode: 'host' # to test locally running service | ||
14 | honlap-grafana: | ||
15 | image: grafana/grafana:6.6.2 | ||
16 | volumes: | ||
17 | - ./grafana/provisioning/:/etc/grafana/provisioning/ | ||
18 | environment: | ||
19 | - GF_SECURITY_ADMIN_PASSWORD=admin | ||
20 | - GF_USERS_ALLOW_SIGN_UP=false | ||
21 | - GF_INSTALL_PLUGINS=grafana-piechart-panel | ||
22 | ports: | ||
23 | - 3000:3000 | ||
24 | # On MacOS, remove next line and replace localhost by host.docker.internal in prometheus/prometheus.yml and | ||
25 | # grafana/provisioning/datasources/datasource.yml | ||
26 | network_mode: 'host' # to test locally running service |
File src/main/docker/postgresql.yml added (mode: 100644) (index 0000000..eb04b1f) | |||
1 | version: '2' | ||
2 | services: | ||
3 | honlap-postgresql: | ||
4 | image: postgres:12.1 | ||
5 | # volumes: | ||
6 | # - ~/volumes/jhipster/honlap/postgresql/:/var/lib/postgresql/data/ | ||
7 | environment: | ||
8 | - POSTGRES_USER=honlap | ||
9 | - POSTGRES_PASSWORD= | ||
10 | ports: | ||
11 | - 5432:5432 |
File src/main/docker/prometheus/prometheus.yml added (mode: 100644) (index 0000000..b370a2f) | |||
1 | # Sample global config for monitoring JHipster applications | ||
2 | global: | ||
3 | scrape_interval: 15s # By default, scrape targets every 15 seconds. | ||
4 | evaluation_interval: 15s # By default, scrape targets every 15 seconds. | ||
5 | # scrape_timeout is set to the global default (10s). | ||
6 | |||
7 | # Attach these labels to any time series or alerts when communicating with | ||
8 | # external systems (federation, remote storage, Alertmanager). | ||
9 | external_labels: | ||
10 | monitor: 'jhipster' | ||
11 | |||
12 | # A scrape configuration containing exactly one endpoint to scrape: | ||
13 | # Here it's Prometheus itself. | ||
14 | scrape_configs: | ||
15 | # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config. | ||
16 | - job_name: 'prometheus' | ||
17 | |||
18 | # Override the global default and scrape targets from this job every 5 seconds. | ||
19 | scrape_interval: 5s | ||
20 | |||
21 | # scheme defaults to 'http' enable https in case your application is server via https | ||
22 | #scheme: https | ||
23 | # basic auth is not needed by default. See https://www.jhipster.tech/monitoring/#configuring-metrics-forwarding for details | ||
24 | #basic_auth: | ||
25 | # username: admin | ||
26 | # password: admin | ||
27 | metrics_path: /management/prometheus | ||
28 | static_configs: | ||
29 | - targets: | ||
30 | # On MacOS, replace localhost by host.docker.internal | ||
31 | - localhost:8080 |
File src/main/docker/sonar.yml added (mode: 100644) (index 0000000..55b0f39) | |||
1 | version: '2' | ||
2 | services: | ||
3 | honlap-sonar: | ||
4 | image: sonarqube:8.2-community | ||
5 | ports: | ||
6 | - 9001:9000 | ||
7 | - 9092:9092 |
File src/main/java/hu/dns/honlap/ApplicationWebXml.java added (mode: 100644) (index 0000000..794441b) | |||
1 | package hu.dns.honlap; | ||
2 | |||
3 | import io.github.jhipster.config.DefaultProfileUtil; | ||
4 | |||
5 | import org.springframework.boot.builder.SpringApplicationBuilder; | ||
6 | import org.springframework.boot.web.servlet.support.SpringBootServletInitializer; | ||
7 | |||
8 | /** | ||
9 | * This is a helper Java class that provides an alternative to creating a {@code web.xml}. | ||
10 | * This will be invoked only when the application is deployed to a Servlet container like Tomcat, JBoss etc. | ||
11 | */ | ||
12 | public class ApplicationWebXml extends SpringBootServletInitializer { | ||
13 | |||
14 | @Override | ||
15 | protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { | ||
16 | // set a default to use when no profile is configured. | ||
17 | DefaultProfileUtil.addDefaultProfile(application.application()); | ||
18 | return application.sources(HonlapApp.class); | ||
19 | } | ||
20 | } |
File src/main/java/hu/dns/honlap/HonlapApp.java added (mode: 100644) (index 0000000..4eda3ac) | |||
1 | package hu.dns.honlap; | ||
2 | |||
3 | import hu.dns.honlap.config.ApplicationProperties; | ||
4 | |||
5 | import io.github.jhipster.config.DefaultProfileUtil; | ||
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.core.env.Environment; | ||
16 | |||
17 | import javax.annotation.PostConstruct; | ||
18 | import java.net.InetAddress; | ||
19 | import java.net.UnknownHostException; | ||
20 | import java.util.Arrays; | ||
21 | import java.util.Collection; | ||
22 | |||
23 | @SpringBootApplication | ||
24 | @EnableConfigurationProperties({LiquibaseProperties.class, ApplicationProperties.class}) | ||
25 | public class HonlapApp { | ||
26 | |||
27 | private static final Logger log = LoggerFactory.getLogger(HonlapApp.class); | ||
28 | |||
29 | private final Environment env; | ||
30 | |||
31 | public HonlapApp(Environment env) { | ||
32 | this.env = env; | ||
33 | } | ||
34 | |||
35 | /** | ||
36 | * Initializes honlap. | ||
37 | * <p> | ||
38 | * Spring profiles can be configured with a program argument --spring.profiles.active=your-active-profile | ||
39 | * <p> | ||
40 | * 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>. | ||
41 | */ | ||
42 | @PostConstruct | ||
43 | public void initApplication() { | ||
44 | Collection<String> activeProfiles = Arrays.asList(env.getActiveProfiles()); | ||
45 | if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_PRODUCTION)) { | ||
46 | log.error("You have misconfigured your application! It should not run " + | ||
47 | "with both the 'dev' and 'prod' profiles at the same time."); | ||
48 | } | ||
49 | if (activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) && activeProfiles.contains(JHipsterConstants.SPRING_PROFILE_CLOUD)) { | ||
50 | log.error("You have misconfigured your application! It should not " + | ||
51 | "run with both the 'dev' and 'cloud' profiles at the same time."); | ||
52 | } | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Main method, used to run the application. | ||
57 | * | ||
58 | * @param args the command line arguments. | ||
59 | */ | ||
60 | public static void main(String[] args) { | ||
61 | SpringApplication app = new SpringApplication(HonlapApp.class); | ||
62 | DefaultProfileUtil.addDefaultProfile(app); | ||
63 | Environment env = app.run(args).getEnvironment(); | ||
64 | logApplicationStartup(env); | ||
65 | } | ||
66 | |||
67 | private static void logApplicationStartup(Environment env) { | ||
68 | String protocol = "http"; | ||
69 | if (env.getProperty("server.ssl.key-store") != null) { | ||
70 | protocol = "https"; | ||
71 | } | ||
72 | String serverPort = env.getProperty("server.port"); | ||
73 | String contextPath = env.getProperty("server.servlet.context-path"); | ||
74 | if (StringUtils.isBlank(contextPath)) { | ||
75 | contextPath = "/"; | ||
76 | } | ||
77 | String hostAddress = "localhost"; | ||
78 | try { | ||
79 | hostAddress = InetAddress.getLocalHost().getHostAddress(); | ||
80 | } catch (UnknownHostException e) { | ||
81 | log.warn("The host name could not be determined, using `localhost` as fallback"); | ||
82 | } | ||
83 | log.info("\n----------------------------------------------------------\n\t" + | ||
84 | "Application '{}' is running! Access URLs:\n\t" + | ||
85 | "Local: \t\t{}://localhost:{}{}\n\t" + | ||
86 | "External: \t{}://{}:{}{}\n\t" + | ||
87 | "Profile(s): \t{}\n----------------------------------------------------------", | ||
88 | env.getProperty("spring.application.name"), | ||
89 | protocol, | ||
90 | serverPort, | ||
91 | contextPath, | ||
92 | protocol, | ||
93 | hostAddress, | ||
94 | serverPort, | ||
95 | contextPath, | ||
96 | env.getActiveProfiles()); | ||
97 | } | ||
98 | } |
File src/main/java/hu/dns/honlap/aop/logging/LoggingAspect.java added (mode: 100644) (index 0000000..d33070c) | |||
1 | package hu.dns.honlap.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 | import org.springframework.core.env.Profiles; | ||
15 | |||
16 | import java.util.Arrays; | ||
17 | |||
18 | /** | ||
19 | * Aspect for logging execution of service and repository Spring components. | ||
20 | * | ||
21 | * By default, it only runs with the "dev" profile. | ||
22 | */ | ||
23 | @Aspect | ||
24 | public class LoggingAspect { | ||
25 | |||
26 | private final Environment env; | ||
27 | |||
28 | public LoggingAspect(Environment env) { | ||
29 | this.env = env; | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * Pointcut that matches all repositories, services and Web REST endpoints. | ||
34 | */ | ||
35 | @Pointcut("within(@org.springframework.stereotype.Repository *)" + | ||
36 | " || within(@org.springframework.stereotype.Service *)" + | ||
37 | " || within(@org.springframework.web.bind.annotation.RestController *)") | ||
38 | public void springBeanPointcut() { | ||
39 | // Method is empty as this is just a Pointcut, the implementations are in the advices. | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * Pointcut that matches all Spring beans in the application's main packages. | ||
44 | */ | ||
45 | @Pointcut("within(hu.dns.honlap.repository..*)"+ | ||
46 | " || within(hu.dns.honlap.service..*)"+ | ||
47 | " || within(hu.dns.honlap.web.rest..*)") | ||
48 | public void applicationPackagePointcut() { | ||
49 | // Method is empty as this is just a Pointcut, the implementations are in the advices. | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Retrieves the {@link Logger} associated to the given {@link JoinPoint}. | ||
54 | * | ||
55 | * @param joinPoint join point we want the logger for. | ||
56 | * @return {@link Logger} associated to the given {@link JoinPoint}. | ||
57 | */ | ||
58 | private Logger logger(JoinPoint joinPoint) { | ||
59 | return LoggerFactory.getLogger(joinPoint.getSignature().getDeclaringTypeName()); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Advice that logs methods throwing exceptions. | ||
64 | * | ||
65 | * @param joinPoint join point for advice. | ||
66 | * @param e exception. | ||
67 | */ | ||
68 | @AfterThrowing(pointcut = "applicationPackagePointcut() && springBeanPointcut()", throwing = "e") | ||
69 | public void logAfterThrowing(JoinPoint joinPoint, Throwable e) { | ||
70 | if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) { | ||
71 | logger(joinPoint) | ||
72 | .error( | ||
73 | "Exception in {}() with cause = \'{}\' and exception = \'{}\'", | ||
74 | joinPoint.getSignature().getName(), | ||
75 | e.getCause() != null ? e.getCause() : "NULL", | ||
76 | e.getMessage(), | ||
77 | e | ||
78 | ); | ||
79 | } else { | ||
80 | logger(joinPoint) | ||
81 | .error( | ||
82 | "Exception in {}() with cause = {}", | ||
83 | joinPoint.getSignature().getName(), | ||
84 | e.getCause() != null ? e.getCause() : "NULL" | ||
85 | ); | ||
86 | } | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * Advice that logs when a method is entered and exited. | ||
91 | * | ||
92 | * @param joinPoint join point for advice. | ||
93 | * @return result. | ||
94 | * @throws Throwable throws {@link IllegalArgumentException}. | ||
95 | */ | ||
96 | @Around("applicationPackagePointcut() && springBeanPointcut()") | ||
97 | public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { | ||
98 | Logger log = logger(joinPoint); | ||
99 | if (log.isDebugEnabled()) { | ||
100 | log.debug("Enter: {}() with argument[s] = {}", joinPoint.getSignature().getName(), Arrays.toString(joinPoint.getArgs())); | ||
101 | } | ||
102 | try { | ||
103 | Object result = joinPoint.proceed(); | ||
104 | if (log.isDebugEnabled()) { | ||
105 | log.debug("Exit: {}() with result = {}", joinPoint.getSignature().getName(), result); | ||
106 | } | ||
107 | return result; | ||
108 | } catch (IllegalArgumentException e) { | ||
109 | log.error("Illegal argument: {} in {}()", Arrays.toString(joinPoint.getArgs()), joinPoint.getSignature().getName()); | ||
110 | throw e; | ||
111 | } | ||
112 | } | ||
113 | } |
File src/main/java/hu/dns/honlap/config/ApplicationProperties.java added (mode: 100644) (index 0000000..1f99f01) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import org.springframework.boot.context.properties.ConfigurationProperties; | ||
4 | |||
5 | /** | ||
6 | * Properties specific to Honlap. | ||
7 | * <p> | ||
8 | * Properties are configured in the {@code 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 | } |
File src/main/java/hu/dns/honlap/config/AsyncConfiguration.java added (mode: 100644) (index 0000000..a0bf6f2) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import io.github.jhipster.async.ExceptionHandlingAsyncTaskExecutor; | ||
4 | import org.slf4j.Logger; | ||
5 | import org.slf4j.LoggerFactory; | ||
6 | import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; | ||
7 | import org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler; | ||
8 | import org.springframework.boot.autoconfigure.task.TaskExecutionProperties; | ||
9 | import org.springframework.context.annotation.Bean; | ||
10 | import org.springframework.context.annotation.Configuration; | ||
11 | import org.springframework.scheduling.annotation.AsyncConfigurer; | ||
12 | import org.springframework.scheduling.annotation.EnableAsync; | ||
13 | import org.springframework.scheduling.annotation.EnableScheduling; | ||
14 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
15 | |||
16 | import java.util.concurrent.Executor; | ||
17 | |||
18 | @Configuration | ||
19 | @EnableAsync | ||
20 | @EnableScheduling | ||
21 | public class AsyncConfiguration implements AsyncConfigurer { | ||
22 | |||
23 | private final Logger log = LoggerFactory.getLogger(AsyncConfiguration.class); | ||
24 | |||
25 | private final TaskExecutionProperties taskExecutionProperties; | ||
26 | |||
27 | public AsyncConfiguration(TaskExecutionProperties taskExecutionProperties) { | ||
28 | this.taskExecutionProperties = taskExecutionProperties; | ||
29 | } | ||
30 | |||
31 | @Override | ||
32 | @Bean(name = "taskExecutor") | ||
33 | public Executor getAsyncExecutor() { | ||
34 | log.debug("Creating Async Task Executor"); | ||
35 | ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); | ||
36 | executor.setCorePoolSize(taskExecutionProperties.getPool().getCoreSize()); | ||
37 | executor.setMaxPoolSize(taskExecutionProperties.getPool().getMaxSize()); | ||
38 | executor.setQueueCapacity(taskExecutionProperties.getPool().getQueueCapacity()); | ||
39 | executor.setThreadNamePrefix(taskExecutionProperties.getThreadNamePrefix()); | ||
40 | return new ExceptionHandlingAsyncTaskExecutor(executor); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { | ||
45 | return new SimpleAsyncUncaughtExceptionHandler(); | ||
46 | } | ||
47 | } |
File src/main/java/hu/dns/honlap/config/CacheConfiguration.java added (mode: 100644) (index 0000000..70d4965) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import java.time.Duration; | ||
4 | |||
5 | import org.ehcache.config.builders.*; | ||
6 | import org.ehcache.jsr107.Eh107Configuration; | ||
7 | |||
8 | import org.hibernate.cache.jcache.ConfigSettings; | ||
9 | import io.github.jhipster.config.JHipsterProperties; | ||
10 | |||
11 | import org.springframework.boot.autoconfigure.cache.JCacheManagerCustomizer; | ||
12 | import org.springframework.boot.autoconfigure.orm.jpa.HibernatePropertiesCustomizer; | ||
13 | import org.springframework.cache.annotation.EnableCaching; | ||
14 | import org.springframework.context.annotation.*; | ||
15 | |||
16 | @Configuration | ||
17 | @EnableCaching | ||
18 | public class CacheConfiguration { | ||
19 | |||
20 | private final javax.cache.configuration.Configuration<Object, Object> jcacheConfiguration; | ||
21 | |||
22 | public CacheConfiguration(JHipsterProperties jHipsterProperties) { | ||
23 | JHipsterProperties.Cache.Ehcache ehcache = jHipsterProperties.getCache().getEhcache(); | ||
24 | |||
25 | jcacheConfiguration = Eh107Configuration.fromEhcacheCacheConfiguration( | ||
26 | CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, | ||
27 | ResourcePoolsBuilder.heap(ehcache.getMaxEntries())) | ||
28 | .withExpiry(ExpiryPolicyBuilder.timeToLiveExpiration(Duration.ofSeconds(ehcache.getTimeToLiveSeconds()))) | ||
29 | .build()); | ||
30 | } | ||
31 | |||
32 | @Bean | ||
33 | public HibernatePropertiesCustomizer hibernatePropertiesCustomizer(javax.cache.CacheManager cacheManager) { | ||
34 | return hibernateProperties -> hibernateProperties.put(ConfigSettings.CACHE_MANAGER, cacheManager); | ||
35 | } | ||
36 | |||
37 | @Bean | ||
38 | public JCacheManagerCustomizer cacheManagerCustomizer() { | ||
39 | return cm -> { | ||
40 | createCache(cm, hu.dns.honlap.repository.UserRepository.USERS_BY_LOGIN_CACHE); | ||
41 | createCache(cm, hu.dns.honlap.repository.UserRepository.USERS_BY_EMAIL_CACHE); | ||
42 | createCache(cm, hu.dns.honlap.domain.User.class.getName()); | ||
43 | createCache(cm, hu.dns.honlap.domain.Authority.class.getName()); | ||
44 | createCache(cm, hu.dns.honlap.domain.User.class.getName() + ".authorities"); | ||
45 | createCache(cm, hu.dns.honlap.domain.PieceOfNews.class.getName()); | ||
46 | // jhipster-needle-ehcache-add-entry | ||
47 | }; | ||
48 | } | ||
49 | |||
50 | private void createCache(javax.cache.CacheManager cm, String cacheName) { | ||
51 | javax.cache.Cache<Object, Object> cache = cm.getCache(cacheName); | ||
52 | if (cache == null) { | ||
53 | cm.createCache(cacheName, jcacheConfiguration); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | } |
File src/main/java/hu/dns/honlap/config/CloudDatabaseConfiguration.java added (mode: 100644) (index 0000000..8969123) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import io.github.jhipster.config.JHipsterConstants; | ||
4 | |||
5 | import org.slf4j.Logger; | ||
6 | import org.slf4j.LoggerFactory; | ||
7 | import org.springframework.cloud.config.java.AbstractCloudConfig; | ||
8 | import org.springframework.context.annotation.*; | ||
9 | |||
10 | import javax.sql.DataSource; | ||
11 | import org.springframework.boot.context.properties.ConfigurationProperties; | ||
12 | |||
13 | |||
14 | @Configuration | ||
15 | @Profile(JHipsterConstants.SPRING_PROFILE_CLOUD) | ||
16 | public class CloudDatabaseConfiguration extends AbstractCloudConfig { | ||
17 | |||
18 | private final Logger log = LoggerFactory.getLogger(CloudDatabaseConfiguration.class); | ||
19 | |||
20 | private static final String CLOUD_CONFIGURATION_HIKARI_PREFIX = "spring.datasource.hikari"; | ||
21 | |||
22 | @Bean | ||
23 | @ConfigurationProperties(CLOUD_CONFIGURATION_HIKARI_PREFIX) | ||
24 | public DataSource dataSource() { | ||
25 | log.info("Configuring JDBC datasource from a cloud provider"); | ||
26 | return connectionFactory().dataSource(); | ||
27 | } | ||
28 | } |
File src/main/java/hu/dns/honlap/config/Constants.java added (mode: 100644) (index 0000000..776c47a) | |||
1 | package hu.dns.honlap.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 DEFAULT_LANGUAGE = "hu"; | ||
13 | public static final String ANONYMOUS_USER = "anonymoususer"; | ||
14 | |||
15 | private Constants() { | ||
16 | } | ||
17 | } |
File src/main/java/hu/dns/honlap/config/DatabaseConfiguration.java added (mode: 100644) (index 0000000..af5ac7e) | |||
1 | package hu.dns.honlap.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 | |||
18 | @Configuration | ||
19 | @EnableJpaRepositories("hu.dns.honlap.repository") | ||
20 | @EnableJpaAuditing(auditorAwareRef = "springSecurityAuditorAware") | ||
21 | @EnableTransactionManagement | ||
22 | public class DatabaseConfiguration { | ||
23 | |||
24 | private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class); | ||
25 | |||
26 | private final Environment env; | ||
27 | |||
28 | public DatabaseConfiguration(Environment env) { | ||
29 | this.env = env; | ||
30 | } | ||
31 | |||
32 | /** | ||
33 | * Open the TCP port for the H2 database, so it is available remotely. | ||
34 | * | ||
35 | * @return the H2 database TCP server. | ||
36 | * @throws SQLException if the server failed to start. | ||
37 | */ | ||
38 | @Bean(initMethod = "start", destroyMethod = "stop") | ||
39 | @Profile(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT) | ||
40 | public Object h2TCPServer() throws SQLException { | ||
41 | String port = getValidPortForH2(); | ||
42 | log.debug("H2 database is available on port {}", port); | ||
43 | return H2ConfigurationHelper.createServer(port); | ||
44 | } | ||
45 | |||
46 | private String getValidPortForH2() { | ||
47 | int port = Integer.parseInt(env.getProperty("server.port")); | ||
48 | if (port < 10000) { | ||
49 | port = 10000 + port; | ||
50 | } else { | ||
51 | if (port < 63536) { | ||
52 | port = port + 2000; | ||
53 | } else { | ||
54 | port = port - 2000; | ||
55 | } | ||
56 | } | ||
57 | return String.valueOf(port); | ||
58 | } | ||
59 | } |
File src/main/java/hu/dns/honlap/config/DateTimeFormatConfiguration.java added (mode: 100644) (index 0000000..e38757e) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/config/JacksonConfiguration.java added (mode: 100644) (index 0000000..9993dc0) | |||
1 | package hu.dns.honlap.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 | * Support for Hibernate types in Jackson. | ||
32 | */ | ||
33 | @Bean | ||
34 | public Hibernate5Module hibernate5Module() { | ||
35 | return new Hibernate5Module(); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * Jackson Afterburner module to speed up serialization/deserialization. | ||
40 | */ | ||
41 | @Bean | ||
42 | public AfterburnerModule afterburnerModule() { | ||
43 | return new AfterburnerModule(); | ||
44 | } | ||
45 | |||
46 | /* | ||
47 | * Module for serialization/deserialization of RFC7807 Problem. | ||
48 | */ | ||
49 | @Bean | ||
50 | ProblemModule problemModule() { | ||
51 | return new ProblemModule(); | ||
52 | } | ||
53 | |||
54 | /* | ||
55 | * Module for serialization/deserialization of ConstraintViolationProblem. | ||
56 | */ | ||
57 | @Bean | ||
58 | ConstraintViolationProblemModule constraintViolationProblemModule() { | ||
59 | return new ConstraintViolationProblemModule(); | ||
60 | } | ||
61 | } |
File src/main/java/hu/dns/honlap/config/LiquibaseConfiguration.java added (mode: 100644) (index 0000000..f315ddb) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import io.github.jhipster.config.JHipsterConstants; | ||
4 | import io.github.jhipster.config.liquibase.SpringLiquibaseUtil; | ||
5 | import liquibase.integration.spring.SpringLiquibase; | ||
6 | import org.slf4j.Logger; | ||
7 | import org.slf4j.LoggerFactory; | ||
8 | import org.springframework.beans.factory.ObjectProvider; | ||
9 | import org.springframework.beans.factory.annotation.Qualifier; | ||
10 | import org.springframework.boot.autoconfigure.jdbc.DataSourceProperties; | ||
11 | import org.springframework.boot.autoconfigure.liquibase.LiquibaseDataSource; | ||
12 | import org.springframework.boot.autoconfigure.liquibase.LiquibaseProperties; | ||
13 | import org.springframework.context.annotation.Bean; | ||
14 | import org.springframework.context.annotation.Configuration; | ||
15 | import org.springframework.core.env.Environment; | ||
16 | import org.springframework.core.env.Profiles; | ||
17 | |||
18 | import javax.sql.DataSource; | ||
19 | import java.util.concurrent.Executor; | ||
20 | |||
21 | @Configuration | ||
22 | public class LiquibaseConfiguration { | ||
23 | |||
24 | private final Logger log = LoggerFactory.getLogger(LiquibaseConfiguration.class); | ||
25 | |||
26 | private final Environment env; | ||
27 | |||
28 | public LiquibaseConfiguration(Environment env) { | ||
29 | this.env = env; | ||
30 | } | ||
31 | |||
32 | @Bean | ||
33 | public SpringLiquibase liquibase(@Qualifier("taskExecutor") Executor executor, | ||
34 | @LiquibaseDataSource ObjectProvider<DataSource> liquibaseDataSource, LiquibaseProperties liquibaseProperties, | ||
35 | ObjectProvider<DataSource> dataSource, DataSourceProperties dataSourceProperties) { | ||
36 | |||
37 | // If you don't want Liquibase to start asynchronously, substitute by this: | ||
38 | // SpringLiquibase liquibase = SpringLiquibaseUtil.createSpringLiquibase(liquibaseDataSource.getIfAvailable(), liquibaseProperties, dataSource.getIfUnique(), dataSourceProperties); | ||
39 | SpringLiquibase liquibase = SpringLiquibaseUtil.createAsyncSpringLiquibase(this.env, executor, liquibaseDataSource.getIfAvailable(), liquibaseProperties, dataSource.getIfUnique(), dataSourceProperties); | ||
40 | liquibase.setChangeLog("classpath:config/liquibase/master.xml"); | ||
41 | liquibase.setContexts(liquibaseProperties.getContexts()); | ||
42 | liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema()); | ||
43 | liquibase.setLiquibaseSchema(liquibaseProperties.getLiquibaseSchema()); | ||
44 | liquibase.setLiquibaseTablespace(liquibaseProperties.getLiquibaseTablespace()); | ||
45 | liquibase.setDatabaseChangeLogLockTable(liquibaseProperties.getDatabaseChangeLogLockTable()); | ||
46 | liquibase.setDatabaseChangeLogTable(liquibaseProperties.getDatabaseChangeLogTable()); | ||
47 | liquibase.setDropFirst(liquibaseProperties.isDropFirst()); | ||
48 | liquibase.setLabels(liquibaseProperties.getLabels()); | ||
49 | liquibase.setChangeLogParameters(liquibaseProperties.getParameters()); | ||
50 | liquibase.setRollbackFile(liquibaseProperties.getRollbackFile()); | ||
51 | liquibase.setTestRollbackOnUpdate(liquibaseProperties.isTestRollbackOnUpdate()); | ||
52 | if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_NO_LIQUIBASE))) { | ||
53 | liquibase.setShouldRun(false); | ||
54 | } else { | ||
55 | liquibase.setShouldRun(liquibaseProperties.isEnabled()); | ||
56 | log.debug("Configuring Liquibase"); | ||
57 | } | ||
58 | return liquibase; | ||
59 | } | ||
60 | } |
File src/main/java/hu/dns/honlap/config/LocaleConfiguration.java added (mode: 100644) (index 0000000..797eb3b) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/config/LoggingAspectConfiguration.java added (mode: 100644) (index 0000000..f5a6d0c) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/config/LoggingConfiguration.java added (mode: 100644) (index 0000000..d5158ab) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import ch.qos.logback.classic.LoggerContext; | ||
4 | import com.fasterxml.jackson.core.JsonProcessingException; | ||
5 | import com.fasterxml.jackson.databind.ObjectMapper; | ||
6 | import io.github.jhipster.config.JHipsterProperties; | ||
7 | import org.slf4j.LoggerFactory; | ||
8 | import org.springframework.beans.factory.annotation.Value; | ||
9 | import org.springframework.context.annotation.Configuration; | ||
10 | |||
11 | import java.util.HashMap; | ||
12 | import java.util.Map; | ||
13 | |||
14 | import static io.github.jhipster.config.logging.LoggingUtils.*; | ||
15 | |||
16 | /* | ||
17 | * Configures the console and Logstash log appenders from the app properties | ||
18 | */ | ||
19 | @Configuration | ||
20 | public class LoggingConfiguration { | ||
21 | |||
22 | public LoggingConfiguration(@Value("${spring.application.name}") String appName, | ||
23 | @Value("${server.port}") String serverPort, | ||
24 | JHipsterProperties jHipsterProperties, | ||
25 | ObjectMapper mapper) throws JsonProcessingException { | ||
26 | |||
27 | LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory(); | ||
28 | |||
29 | Map<String, String> map = new HashMap<>(); | ||
30 | map.put("app_name", appName); | ||
31 | map.put("app_port", serverPort); | ||
32 | String customFields = mapper.writeValueAsString(map); | ||
33 | |||
34 | JHipsterProperties.Logging loggingProperties = jHipsterProperties.getLogging(); | ||
35 | JHipsterProperties.Logging.Logstash logstashProperties = loggingProperties.getLogstash(); | ||
36 | |||
37 | if (loggingProperties.isUseJsonFormat()) { | ||
38 | addJsonConsoleAppender(context, customFields); | ||
39 | } | ||
40 | if (logstashProperties.isEnabled()) { | ||
41 | addLogstashTcpSocketAppender(context, customFields, logstashProperties); | ||
42 | } | ||
43 | if (loggingProperties.isUseJsonFormat() || logstashProperties.isEnabled()) { | ||
44 | addContextListener(context, customFields, loggingProperties); | ||
45 | } | ||
46 | if (jHipsterProperties.getMetrics().getLogs().isEnabled()) { | ||
47 | setMetricsMarkerLogbackFilter(context, loggingProperties.isUseJsonFormat()); | ||
48 | } | ||
49 | } | ||
50 | } |
File src/main/java/hu/dns/honlap/config/SecurityConfiguration.java added (mode: 100644) (index 0000000..d640719) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import hu.dns.honlap.security.*; | ||
4 | import hu.dns.honlap.security.jwt.*; | ||
5 | |||
6 | import org.springframework.context.annotation.Bean; | ||
7 | import org.springframework.context.annotation.Import; | ||
8 | import org.springframework.http.HttpMethod; | ||
9 | import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; | ||
10 | import org.springframework.security.config.annotation.web.builders.HttpSecurity; | ||
11 | import org.springframework.security.config.annotation.web.builders.WebSecurity; | ||
12 | import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; | ||
13 | import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; | ||
14 | import org.springframework.security.config.http.SessionCreationPolicy; | ||
15 | import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; | ||
16 | import org.springframework.security.crypto.password.PasswordEncoder; | ||
17 | import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; | ||
18 | import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; | ||
19 | import org.springframework.web.filter.CorsFilter; | ||
20 | import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport; | ||
21 | |||
22 | @EnableWebSecurity | ||
23 | @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) | ||
24 | @Import(SecurityProblemSupport.class) | ||
25 | public class SecurityConfiguration extends WebSecurityConfigurerAdapter { | ||
26 | |||
27 | private final TokenProvider tokenProvider; | ||
28 | |||
29 | private final CorsFilter corsFilter; | ||
30 | private final SecurityProblemSupport problemSupport; | ||
31 | |||
32 | public SecurityConfiguration(TokenProvider tokenProvider, CorsFilter corsFilter, SecurityProblemSupport problemSupport) { | ||
33 | this.tokenProvider = tokenProvider; | ||
34 | this.corsFilter = corsFilter; | ||
35 | this.problemSupport = problemSupport; | ||
36 | } | ||
37 | |||
38 | @Bean | ||
39 | public PasswordEncoder passwordEncoder() { | ||
40 | return new BCryptPasswordEncoder(); | ||
41 | } | ||
42 | |||
43 | @Override | ||
44 | public void configure(WebSecurity web) { | ||
45 | web.ignoring() | ||
46 | .antMatchers(HttpMethod.OPTIONS, "/**") | ||
47 | .antMatchers("/app/**/*.{js,html}") | ||
48 | .antMatchers("/i18n/**") | ||
49 | .antMatchers("/content/**") | ||
50 | .antMatchers("/h2-console/**") | ||
51 | .antMatchers("/swagger-ui/index.html") | ||
52 | .antMatchers("/test/**"); | ||
53 | } | ||
54 | |||
55 | @Override | ||
56 | public void configure(HttpSecurity http) throws Exception { | ||
57 | // @formatter:off | ||
58 | http | ||
59 | .csrf() | ||
60 | .disable() | ||
61 | .addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) | ||
62 | .exceptionHandling() | ||
63 | .authenticationEntryPoint(problemSupport) | ||
64 | .accessDeniedHandler(problemSupport) | ||
65 | .and() | ||
66 | .headers() | ||
67 | .contentSecurityPolicy("default-src 'self'; frame-src 'self' data:; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://storage.googleapis.com; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self' data:") | ||
68 | .and() | ||
69 | .referrerPolicy(ReferrerPolicyHeaderWriter.ReferrerPolicy.STRICT_ORIGIN_WHEN_CROSS_ORIGIN) | ||
70 | .and() | ||
71 | .featurePolicy("geolocation 'none'; midi 'none'; sync-xhr 'none'; microphone 'none'; camera 'none'; magnetometer 'none'; gyroscope 'none'; speaker 'none'; fullscreen 'self'; payment 'none'") | ||
72 | .and() | ||
73 | .frameOptions() | ||
74 | .deny() | ||
75 | .and() | ||
76 | .sessionManagement() | ||
77 | .sessionCreationPolicy(SessionCreationPolicy.STATELESS) | ||
78 | .and() | ||
79 | .authorizeRequests() | ||
80 | .antMatchers("/api/authenticate").permitAll() | ||
81 | .antMatchers("/api/register").permitAll() | ||
82 | .antMatchers("/api/activate").permitAll() | ||
83 | .antMatchers("/api/account/reset-password/init").permitAll() | ||
84 | .antMatchers("/api/account/reset-password/finish").permitAll() | ||
85 | .antMatchers("/api/**").authenticated() | ||
86 | .antMatchers("/management/health").permitAll() | ||
87 | .antMatchers("/management/info").permitAll() | ||
88 | .antMatchers("/management/prometheus").permitAll() | ||
89 | .antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN) | ||
90 | .and() | ||
91 | .httpBasic() | ||
92 | .and() | ||
93 | .apply(securityConfigurerAdapter()); | ||
94 | // @formatter:on | ||
95 | } | ||
96 | |||
97 | private JWTConfigurer securityConfigurerAdapter() { | ||
98 | return new JWTConfigurer(tokenProvider); | ||
99 | } | ||
100 | } |
File src/main/java/hu/dns/honlap/config/WebConfigurer.java added (mode: 100644) (index 0000000..889fde5) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import io.github.jhipster.config.JHipsterConstants; | ||
4 | import io.github.jhipster.config.JHipsterProperties; | ||
5 | import io.github.jhipster.config.h2.H2ConfigurationHelper; | ||
6 | import io.github.jhipster.web.filter.CachingHttpHeadersFilter; | ||
7 | import org.slf4j.Logger; | ||
8 | import org.slf4j.LoggerFactory; | ||
9 | import org.springframework.boot.web.server.*; | ||
10 | import org.springframework.boot.web.servlet.ServletContextInitializer; | ||
11 | import org.springframework.boot.web.servlet.server.ConfigurableServletWebServerFactory; | ||
12 | import org.springframework.context.annotation.Bean; | ||
13 | import org.springframework.context.annotation.Configuration; | ||
14 | import org.springframework.core.env.Environment; | ||
15 | import org.springframework.core.env.Profiles; | ||
16 | import org.springframework.http.MediaType; | ||
17 | import org.springframework.web.cors.CorsConfiguration; | ||
18 | import org.springframework.web.cors.UrlBasedCorsConfigurationSource; | ||
19 | import org.springframework.web.filter.CorsFilter; | ||
20 | |||
21 | import javax.servlet.*; | ||
22 | import java.io.File; | ||
23 | import java.io.UnsupportedEncodingException; | ||
24 | import java.nio.charset.StandardCharsets; | ||
25 | import java.nio.file.Paths; | ||
26 | import java.util.*; | ||
27 | |||
28 | import static java.net.URLDecoder.decode; | ||
29 | |||
30 | /** | ||
31 | * Configuration of web application with Servlet 3.0 APIs. | ||
32 | */ | ||
33 | @Configuration | ||
34 | public class WebConfigurer implements ServletContextInitializer, WebServerFactoryCustomizer<WebServerFactory> { | ||
35 | |||
36 | private final Logger log = LoggerFactory.getLogger(WebConfigurer.class); | ||
37 | |||
38 | private final Environment env; | ||
39 | |||
40 | private final JHipsterProperties jHipsterProperties; | ||
41 | |||
42 | public WebConfigurer(Environment env, JHipsterProperties jHipsterProperties) { | ||
43 | this.env = env; | ||
44 | this.jHipsterProperties = jHipsterProperties; | ||
45 | } | ||
46 | |||
47 | @Override | ||
48 | public void onStartup(ServletContext servletContext) throws ServletException { | ||
49 | if (env.getActiveProfiles().length != 0) { | ||
50 | log.info("Web application configuration, using profiles: {}", (Object[]) env.getActiveProfiles()); | ||
51 | } | ||
52 | EnumSet<DispatcherType> disps = EnumSet.of(DispatcherType.REQUEST, DispatcherType.FORWARD, DispatcherType.ASYNC); | ||
53 | if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_PRODUCTION))) { | ||
54 | initCachingHttpHeadersFilter(servletContext, disps); | ||
55 | } | ||
56 | if (env.acceptsProfiles(Profiles.of(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT))) { | ||
57 | initH2Console(servletContext); | ||
58 | } | ||
59 | log.info("Web application fully configured"); | ||
60 | } | ||
61 | |||
62 | /** | ||
63 | * Customize the Servlet engine: Mime types, the document root, the cache. | ||
64 | */ | ||
65 | @Override | ||
66 | public void customize(WebServerFactory server) { | ||
67 | setMimeMappings(server); | ||
68 | // When running in an IDE or with ./mvnw spring-boot:run, set location of the static web assets. | ||
69 | setLocationForStaticAssets(server); | ||
70 | } | ||
71 | |||
72 | private void setMimeMappings(WebServerFactory server) { | ||
73 | if (server instanceof ConfigurableServletWebServerFactory) { | ||
74 | MimeMappings mappings = new MimeMappings(MimeMappings.DEFAULT); | ||
75 | // IE issue, see https://github.com/jhipster/generator-jhipster/pull/711 | ||
76 | mappings.add("html", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase()); | ||
77 | // CloudFoundry issue, see https://github.com/cloudfoundry/gorouter/issues/64 | ||
78 | mappings.add("json", MediaType.TEXT_HTML_VALUE + ";charset=" + StandardCharsets.UTF_8.name().toLowerCase()); | ||
79 | ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server; | ||
80 | servletWebServer.setMimeMappings(mappings); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | private void setLocationForStaticAssets(WebServerFactory server) { | ||
85 | if (server instanceof ConfigurableServletWebServerFactory) { | ||
86 | ConfigurableServletWebServerFactory servletWebServer = (ConfigurableServletWebServerFactory) server; | ||
87 | File root; | ||
88 | String prefixPath = resolvePathPrefix(); | ||
89 | root = new File(prefixPath + "target/classes/static/"); | ||
90 | if (root.exists() && root.isDirectory()) { | ||
91 | servletWebServer.setDocumentRoot(root); | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * Resolve path prefix to static resources. | ||
98 | */ | ||
99 | private String resolvePathPrefix() { | ||
100 | String fullExecutablePath; | ||
101 | try { | ||
102 | fullExecutablePath = decode(this.getClass().getResource("").getPath(), StandardCharsets.UTF_8.name()); | ||
103 | } catch (UnsupportedEncodingException e) { | ||
104 | /* try without decoding if this ever happens */ | ||
105 | fullExecutablePath = this.getClass().getResource("").getPath(); | ||
106 | } | ||
107 | String rootPath = Paths.get(".").toUri().normalize().getPath(); | ||
108 | String extractedPath = fullExecutablePath.replace(rootPath, ""); | ||
109 | int extractionEndIndex = extractedPath.indexOf("target/"); | ||
110 | if (extractionEndIndex <= 0) { | ||
111 | return ""; | ||
112 | } | ||
113 | return extractedPath.substring(0, extractionEndIndex); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * Initializes the caching HTTP Headers Filter. | ||
118 | */ | ||
119 | private void initCachingHttpHeadersFilter(ServletContext servletContext, | ||
120 | EnumSet<DispatcherType> disps) { | ||
121 | log.debug("Registering Caching HTTP Headers Filter"); | ||
122 | FilterRegistration.Dynamic cachingHttpHeadersFilter = | ||
123 | servletContext.addFilter("cachingHttpHeadersFilter", | ||
124 | new CachingHttpHeadersFilter(jHipsterProperties)); | ||
125 | |||
126 | cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/i18n/*"); | ||
127 | cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/content/*"); | ||
128 | cachingHttpHeadersFilter.addMappingForUrlPatterns(disps, true, "/app/*"); | ||
129 | cachingHttpHeadersFilter.setAsyncSupported(true); | ||
130 | } | ||
131 | |||
132 | @Bean | ||
133 | public CorsFilter corsFilter() { | ||
134 | UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); | ||
135 | CorsConfiguration config = jHipsterProperties.getCors(); | ||
136 | if (config.getAllowedOrigins() != null && !config.getAllowedOrigins().isEmpty()) { | ||
137 | log.debug("Registering CORS filter"); | ||
138 | source.registerCorsConfiguration("/api/**", config); | ||
139 | source.registerCorsConfiguration("/management/**", config); | ||
140 | source.registerCorsConfiguration("/v2/api-docs", config); | ||
141 | } | ||
142 | return new CorsFilter(source); | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * Initializes H2 console. | ||
147 | */ | ||
148 | private void initH2Console(ServletContext servletContext) { | ||
149 | log.debug("Initialize H2 console"); | ||
150 | H2ConfigurationHelper.initH2Console(servletContext); | ||
151 | } | ||
152 | |||
153 | } |
File src/main/java/hu/dns/honlap/config/audit/AuditEventConverter.java added (mode: 100644) (index 0000000..bf77154) | |||
1 | package hu.dns.honlap.config.audit; | ||
2 | |||
3 | import hu.dns.honlap.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 {@link PersistentAuditEvent}s to a list of {@link AuditEvent}s. | ||
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 {@link PersistentAuditEvent} to an {@link 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 {@code AuditEventRepository} interface. | ||
47 | * | ||
48 | * @param data the data to convert. | ||
49 | * @return a map of {@link String}, {@link 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 {@link String}, {@link 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 | } |
File src/main/java/hu/dns/honlap/config/audit/package-info.java added (mode: 100644) (index 0000000..a98b0f9) | |||
1 | /** | ||
2 | * Audit specific code. | ||
3 | */ | ||
4 | package hu.dns.honlap.config.audit; |
File src/main/java/hu/dns/honlap/config/package-info.java added (mode: 100644) (index 0000000..9888ec0) | |||
1 | /** | ||
2 | * Spring Framework configuration files. | ||
3 | */ | ||
4 | package hu.dns.honlap.config; |
File src/main/java/hu/dns/honlap/domain/AbstractAuditingEntity.java added (mode: 100644) (index 0000000..ad4a763) | |||
1 | package hu.dns.honlap.domain; | ||
2 | |||
3 | import com.fasterxml.jackson.annotation.JsonIgnore; | ||
4 | import org.springframework.data.annotation.CreatedBy; | ||
5 | import org.springframework.data.annotation.CreatedDate; | ||
6 | import org.springframework.data.annotation.LastModifiedBy; | ||
7 | import org.springframework.data.annotation.LastModifiedDate; | ||
8 | import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
9 | |||
10 | import java.io.Serializable; | ||
11 | import java.time.Instant; | ||
12 | import javax.persistence.Column; | ||
13 | import javax.persistence.EntityListeners; | ||
14 | import javax.persistence.MappedSuperclass; | ||
15 | |||
16 | /** | ||
17 | * Base abstract class for entities which will hold definitions for created, last modified, created by, | ||
18 | * last modified by attributes. | ||
19 | */ | ||
20 | @MappedSuperclass | ||
21 | @EntityListeners(AuditingEntityListener.class) | ||
22 | public abstract class AbstractAuditingEntity implements Serializable { | ||
23 | |||
24 | private static final long serialVersionUID = 1L; | ||
25 | |||
26 | @CreatedBy | ||
27 | @Column(name = "created_by", nullable = false, length = 50, updatable = false) | ||
28 | @JsonIgnore | ||
29 | private String createdBy; | ||
30 | |||
31 | @CreatedDate | ||
32 | @Column(name = "created_date", updatable = false) | ||
33 | @JsonIgnore | ||
34 | private Instant createdDate = Instant.now(); | ||
35 | |||
36 | @LastModifiedBy | ||
37 | @Column(name = "last_modified_by", length = 50) | ||
38 | @JsonIgnore | ||
39 | private String lastModifiedBy; | ||
40 | |||
41 | @LastModifiedDate | ||
42 | @Column(name = "last_modified_date") | ||
43 | @JsonIgnore | ||
44 | private Instant lastModifiedDate = Instant.now(); | ||
45 | |||
46 | public String getCreatedBy() { | ||
47 | return createdBy; | ||
48 | } | ||
49 | |||
50 | public void setCreatedBy(String createdBy) { | ||
51 | this.createdBy = createdBy; | ||
52 | } | ||
53 | |||
54 | public Instant getCreatedDate() { | ||
55 | return createdDate; | ||
56 | } | ||
57 | |||
58 | public void setCreatedDate(Instant createdDate) { | ||
59 | this.createdDate = createdDate; | ||
60 | } | ||
61 | |||
62 | public String getLastModifiedBy() { | ||
63 | return lastModifiedBy; | ||
64 | } | ||
65 | |||
66 | public void setLastModifiedBy(String lastModifiedBy) { | ||
67 | this.lastModifiedBy = lastModifiedBy; | ||
68 | } | ||
69 | |||
70 | public Instant getLastModifiedDate() { | ||
71 | return lastModifiedDate; | ||
72 | } | ||
73 | |||
74 | public void setLastModifiedDate(Instant lastModifiedDate) { | ||
75 | this.lastModifiedDate = lastModifiedDate; | ||
76 | } | ||
77 | } |
File src/main/java/hu/dns/honlap/domain/Authority.java added (mode: 100644) (index 0000000..09a9ae1) | |||
1 | package hu.dns.honlap.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 | import java.util.Objects; | ||
13 | |||
14 | /** | ||
15 | * An authority (a security role) used by Spring Security. | ||
16 | */ | ||
17 | @Entity | ||
18 | @Table(name = "auth_authority") | ||
19 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) | ||
20 | public class Authority implements Serializable { | ||
21 | |||
22 | private static final long serialVersionUID = 1L; | ||
23 | |||
24 | @NotNull | ||
25 | @Size(max = 50) | ||
26 | @Id | ||
27 | @Column(length = 50) | ||
28 | private String name; | ||
29 | |||
30 | public String getName() { | ||
31 | return name; | ||
32 | } | ||
33 | |||
34 | public void setName(String name) { | ||
35 | this.name = name; | ||
36 | } | ||
37 | |||
38 | @Override | ||
39 | public boolean equals(Object o) { | ||
40 | if (this == o) { | ||
41 | return true; | ||
42 | } | ||
43 | if (!(o instanceof Authority)) { | ||
44 | return false; | ||
45 | } | ||
46 | return Objects.equals(name, ((Authority) o).name); | ||
47 | } | ||
48 | |||
49 | @Override | ||
50 | public int hashCode() { | ||
51 | return Objects.hashCode(name); | ||
52 | } | ||
53 | |||
54 | @Override | ||
55 | public String toString() { | ||
56 | return "Authority{" + | ||
57 | "name='" + name + '\'' + | ||
58 | "}"; | ||
59 | } | ||
60 | } |
File src/main/java/hu/dns/honlap/domain/PersistentAuditEvent.java added (mode: 100644) (index 0000000..9f8c37e) | |||
1 | package hu.dns.honlap.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.Map; | ||
9 | |||
10 | /** | ||
11 | * Persist AuditEvent managed by the Spring Boot actuator. | ||
12 | * | ||
13 | * @see org.springframework.boot.actuate.audit.AuditEvent | ||
14 | */ | ||
15 | @Entity | ||
16 | @Table(name = "auth_persistent_audit_event") | ||
17 | public class PersistentAuditEvent implements Serializable { | ||
18 | |||
19 | private static final long serialVersionUID = 1L; | ||
20 | |||
21 | @Id | ||
22 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") | ||
23 | @SequenceGenerator(name = "sequenceGenerator") | ||
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 = "auth_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 instanceof PersistentAuditEvent)) { | ||
89 | return false; | ||
90 | } | ||
91 | return id != null && id.equals(((PersistentAuditEvent) o).id); | ||
92 | } | ||
93 | |||
94 | @Override | ||
95 | public int hashCode() { | ||
96 | return 31; | ||
97 | } | ||
98 | |||
99 | @Override | ||
100 | public String toString() { | ||
101 | return "PersistentAuditEvent{" + | ||
102 | "principal='" + principal + '\'' + | ||
103 | ", auditEventDate=" + auditEventDate + | ||
104 | ", auditEventType='" + auditEventType + '\'' + | ||
105 | '}'; | ||
106 | } | ||
107 | } |
File src/main/java/hu/dns/honlap/domain/PieceOfNews.java added (mode: 100644) (index 0000000..4639067) | |||
1 | package hu.dns.honlap.domain; | ||
2 | |||
3 | import io.swagger.annotations.ApiModel; | ||
4 | import org.hibernate.annotations.Cache; | ||
5 | import org.hibernate.annotations.CacheConcurrencyStrategy; | ||
6 | |||
7 | import javax.persistence.*; | ||
8 | import javax.validation.constraints.*; | ||
9 | |||
10 | import java.io.Serializable; | ||
11 | import java.util.Objects; | ||
12 | import java.time.Instant; | ||
13 | |||
14 | /** | ||
15 | * Hírek | ||
16 | */ | ||
17 | @ApiModel(description = "Hírek") | ||
18 | @Entity | ||
19 | @Table(name = "piece_of_news") | ||
20 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) | ||
21 | public class PieceOfNews implements Serializable { | ||
22 | |||
23 | private static final long serialVersionUID = 1L; | ||
24 | |||
25 | @Id | ||
26 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") | ||
27 | @SequenceGenerator(name = "sequenceGenerator") | ||
28 | private Long id; | ||
29 | |||
30 | @NotNull | ||
31 | @Column(name = "app_id", nullable = false) | ||
32 | private Integer appId; | ||
33 | |||
34 | @NotNull | ||
35 | @Column(name = "news_date", nullable = false) | ||
36 | private Instant newsDate; | ||
37 | |||
38 | @NotNull | ||
39 | @Size(max = 300) | ||
40 | @Column(name = "headline", length = 300, nullable = false) | ||
41 | private String headline; | ||
42 | |||
43 | @NotNull | ||
44 | @Size(max = 600) | ||
45 | @Column(name = "content", length = 600, nullable = false) | ||
46 | private String content; | ||
47 | |||
48 | @NotNull | ||
49 | @Size(max = 600) | ||
50 | @Column(name = "link", length = 600, nullable = false) | ||
51 | private String link; | ||
52 | |||
53 | @Column(name = "publish_date") | ||
54 | private Instant publishDate; | ||
55 | |||
56 | @Column(name = "created_by") | ||
57 | private String createdBy; | ||
58 | |||
59 | @Column(name = "created_date") | ||
60 | private Instant createdDate; | ||
61 | |||
62 | @Column(name = "last_modified_by") | ||
63 | private String lastModifiedBy; | ||
64 | |||
65 | @Column(name = "last_modified_date") | ||
66 | private Instant lastModifiedDate; | ||
67 | |||
68 | // jhipster-needle-entity-add-field - JHipster will add fields here, do not remove | ||
69 | public Long getId() { | ||
70 | return id; | ||
71 | } | ||
72 | |||
73 | public void setId(Long id) { | ||
74 | this.id = id; | ||
75 | } | ||
76 | |||
77 | public Integer getAppId() { | ||
78 | return appId; | ||
79 | } | ||
80 | |||
81 | public PieceOfNews appId(Integer appId) { | ||
82 | this.appId = appId; | ||
83 | return this; | ||
84 | } | ||
85 | |||
86 | public void setAppId(Integer appId) { | ||
87 | this.appId = appId; | ||
88 | } | ||
89 | |||
90 | public Instant getNewsDate() { | ||
91 | return newsDate; | ||
92 | } | ||
93 | |||
94 | public PieceOfNews newsDate(Instant newsDate) { | ||
95 | this.newsDate = newsDate; | ||
96 | return this; | ||
97 | } | ||
98 | |||
99 | public void setNewsDate(Instant newsDate) { | ||
100 | this.newsDate = newsDate; | ||
101 | } | ||
102 | |||
103 | public String getHeadline() { | ||
104 | return headline; | ||
105 | } | ||
106 | |||
107 | public PieceOfNews headline(String headline) { | ||
108 | this.headline = headline; | ||
109 | return this; | ||
110 | } | ||
111 | |||
112 | public void setHeadline(String headline) { | ||
113 | this.headline = headline; | ||
114 | } | ||
115 | |||
116 | public String getContent() { | ||
117 | return content; | ||
118 | } | ||
119 | |||
120 | public PieceOfNews content(String content) { | ||
121 | this.content = content; | ||
122 | return this; | ||
123 | } | ||
124 | |||
125 | public void setContent(String content) { | ||
126 | this.content = content; | ||
127 | } | ||
128 | |||
129 | public String getLink() { | ||
130 | return link; | ||
131 | } | ||
132 | |||
133 | public PieceOfNews link(String link) { | ||
134 | this.link = link; | ||
135 | return this; | ||
136 | } | ||
137 | |||
138 | public void setLink(String link) { | ||
139 | this.link = link; | ||
140 | } | ||
141 | |||
142 | public Instant getPublishDate() { | ||
143 | return publishDate; | ||
144 | } | ||
145 | |||
146 | public PieceOfNews publishDate(Instant publishDate) { | ||
147 | this.publishDate = publishDate; | ||
148 | return this; | ||
149 | } | ||
150 | |||
151 | public void setPublishDate(Instant publishDate) { | ||
152 | this.publishDate = publishDate; | ||
153 | } | ||
154 | |||
155 | public String getCreatedBy() { | ||
156 | return createdBy; | ||
157 | } | ||
158 | |||
159 | public PieceOfNews createdBy(String createdBy) { | ||
160 | this.createdBy = createdBy; | ||
161 | return this; | ||
162 | } | ||
163 | |||
164 | public void setCreatedBy(String createdBy) { | ||
165 | this.createdBy = createdBy; | ||
166 | } | ||
167 | |||
168 | public Instant getCreatedDate() { | ||
169 | return createdDate; | ||
170 | } | ||
171 | |||
172 | public PieceOfNews createdDate(Instant createdDate) { | ||
173 | this.createdDate = createdDate; | ||
174 | return this; | ||
175 | } | ||
176 | |||
177 | public void setCreatedDate(Instant createdDate) { | ||
178 | this.createdDate = createdDate; | ||
179 | } | ||
180 | |||
181 | public String getLastModifiedBy() { | ||
182 | return lastModifiedBy; | ||
183 | } | ||
184 | |||
185 | public PieceOfNews lastModifiedBy(String lastModifiedBy) { | ||
186 | this.lastModifiedBy = lastModifiedBy; | ||
187 | return this; | ||
188 | } | ||
189 | |||
190 | public void setLastModifiedBy(String lastModifiedBy) { | ||
191 | this.lastModifiedBy = lastModifiedBy; | ||
192 | } | ||
193 | |||
194 | public Instant getLastModifiedDate() { | ||
195 | return lastModifiedDate; | ||
196 | } | ||
197 | |||
198 | public PieceOfNews lastModifiedDate(Instant lastModifiedDate) { | ||
199 | this.lastModifiedDate = lastModifiedDate; | ||
200 | return this; | ||
201 | } | ||
202 | |||
203 | public void setLastModifiedDate(Instant lastModifiedDate) { | ||
204 | this.lastModifiedDate = lastModifiedDate; | ||
205 | } | ||
206 | // jhipster-needle-entity-add-getters-setters - JHipster will add getters and setters here, do not remove | ||
207 | |||
208 | @Override | ||
209 | public boolean equals(Object o) { | ||
210 | if (this == o) { | ||
211 | return true; | ||
212 | } | ||
213 | if (!(o instanceof PieceOfNews)) { | ||
214 | return false; | ||
215 | } | ||
216 | return id != null && id.equals(((PieceOfNews) o).id); | ||
217 | } | ||
218 | |||
219 | @Override | ||
220 | public int hashCode() { | ||
221 | return 31; | ||
222 | } | ||
223 | |||
224 | @Override | ||
225 | public String toString() { | ||
226 | return "PieceOfNews{" + | ||
227 | "id=" + getId() + | ||
228 | ", appId=" + getAppId() + | ||
229 | ", newsDate='" + getNewsDate() + "'" + | ||
230 | ", headline='" + getHeadline() + "'" + | ||
231 | ", content='" + getContent() + "'" + | ||
232 | ", link='" + getLink() + "'" + | ||
233 | ", publishDate='" + getPublishDate() + "'" + | ||
234 | ", createdBy='" + getCreatedBy() + "'" + | ||
235 | ", createdDate='" + getCreatedDate() + "'" + | ||
236 | ", lastModifiedBy='" + getLastModifiedBy() + "'" + | ||
237 | ", lastModifiedDate='" + getLastModifiedDate() + "'" + | ||
238 | "}"; | ||
239 | } | ||
240 | } |
File src/main/java/hu/dns/honlap/domain/User.java added (mode: 100644) (index 0000000..2d21127) | |||
1 | package hu.dns.honlap.domain; | ||
2 | |||
3 | import hu.dns.honlap.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 | |||
11 | import javax.persistence.*; | ||
12 | import javax.validation.constraints.Email; | ||
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.time.Instant; | ||
18 | import java.util.HashSet; | ||
19 | import java.util.Locale; | ||
20 | import java.util.Set; | ||
21 | |||
22 | /** | ||
23 | * A user. | ||
24 | */ | ||
25 | @Entity | ||
26 | @Table(name = "auth_user") | ||
27 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) | ||
28 | public class User extends AbstractAuditingEntity implements Serializable { | ||
29 | |||
30 | private static final long serialVersionUID = 1L; | ||
31 | |||
32 | @Id | ||
33 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") | ||
34 | @SequenceGenerator(name = "sequenceGenerator") | ||
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 | |||
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 = 10) | ||
67 | @Column(name = "lang_key", length = 10) | ||
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 | |||
82 | @JsonIgnore | ||
83 | private String resetKey; | ||
84 | |||
85 | @Column(name = "reset_date") | ||
86 | private Instant resetDate = null; | ||
87 | |||
88 | @JsonIgnore | ||
89 | @ManyToMany | ||
90 | @JoinTable( | ||
91 | name = "auth_user_authority", | ||
92 | joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")}, | ||
93 | inverseJoinColumns = {@JoinColumn(name = "authority_name", referencedColumnName = "name")}) | ||
94 | @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE) | ||
95 | @BatchSize(size = 20) | ||
96 | private Set<Authority> authorities = new HashSet<>(); | ||
97 | |||
98 | public Long getId() { | ||
99 | return id; | ||
100 | } | ||
101 | |||
102 | public void setId(Long id) { | ||
103 | this.id = id; | ||
104 | } | ||
105 | |||
106 | public String getLogin() { | ||
107 | return login; | ||
108 | } | ||
109 | |||
110 | // Lowercase the login before saving it in database | ||
111 | public void setLogin(String login) { | ||
112 | this.login = StringUtils.lowerCase(login, Locale.ENGLISH); | ||
113 | } | ||
114 | |||
115 | public String getPassword() { | ||
116 | return password; | ||
117 | } | ||
118 | |||
119 | public void setPassword(String password) { | ||
120 | this.password = password; | ||
121 | } | ||
122 | |||
123 | public String getFirstName() { | ||
124 | return firstName; | ||
125 | } | ||
126 | |||
127 | public void setFirstName(String firstName) { | ||
128 | this.firstName = firstName; | ||
129 | } | ||
130 | |||
131 | public String getLastName() { | ||
132 | return lastName; | ||
133 | } | ||
134 | |||
135 | public void setLastName(String lastName) { | ||
136 | this.lastName = lastName; | ||
137 | } | ||
138 | |||
139 | public String getEmail() { | ||
140 | return email; | ||
141 | } | ||
142 | |||
143 | public void setEmail(String email) { | ||
144 | this.email = email; | ||
145 | } | ||
146 | |||
147 | public String getImageUrl() { | ||
148 | return imageUrl; | ||
149 | } | ||
150 | |||
151 | public void setImageUrl(String imageUrl) { | ||
152 | this.imageUrl = imageUrl; | ||
153 | } | ||
154 | |||
155 | public boolean getActivated() { | ||
156 | return activated; | ||
157 | } | ||
158 | |||
159 | public void setActivated(boolean activated) { | ||
160 | this.activated = activated; | ||
161 | } | ||
162 | |||
163 | public String getActivationKey() { | ||
164 | return activationKey; | ||
165 | } | ||
166 | |||
167 | public void setActivationKey(String activationKey) { | ||
168 | this.activationKey = activationKey; | ||
169 | } | ||
170 | |||
171 | public String getResetKey() { | ||
172 | return resetKey; | ||
173 | } | ||
174 | |||
175 | public void setResetKey(String resetKey) { | ||
176 | this.resetKey = resetKey; | ||
177 | } | ||
178 | |||
179 | public Instant getResetDate() { | ||
180 | return resetDate; | ||
181 | } | ||
182 | |||
183 | public void setResetDate(Instant resetDate) { | ||
184 | this.resetDate = resetDate; | ||
185 | } | ||
186 | |||
187 | public String getLangKey() { | ||
188 | return langKey; | ||
189 | } | ||
190 | |||
191 | public void setLangKey(String langKey) { | ||
192 | this.langKey = langKey; | ||
193 | } | ||
194 | |||
195 | public Set<Authority> getAuthorities() { | ||
196 | return authorities; | ||
197 | } | ||
198 | |||
199 | public void setAuthorities(Set<Authority> authorities) { | ||
200 | this.authorities = authorities; | ||
201 | } | ||
202 | |||
203 | @Override | ||
204 | public boolean equals(Object o) { | ||
205 | if (this == o) { | ||
206 | return true; | ||
207 | } | ||
208 | if (!(o instanceof User)) { | ||
209 | return false; | ||
210 | } | ||
211 | return id != null && id.equals(((User) o).id); | ||
212 | } | ||
213 | |||
214 | @Override | ||
215 | public int hashCode() { | ||
216 | return 31; | ||
217 | } | ||
218 | |||
219 | @Override | ||
220 | public String toString() { | ||
221 | return "User{" + | ||
222 | "login='" + login + '\'' + | ||
223 | ", firstName='" + firstName + '\'' + | ||
224 | ", lastName='" + lastName + '\'' + | ||
225 | ", email='" + email + '\'' + | ||
226 | ", imageUrl='" + imageUrl + '\'' + | ||
227 | ", activated='" + activated + '\'' + | ||
228 | ", langKey='" + langKey + '\'' + | ||
229 | ", activationKey='" + activationKey + '\'' + | ||
230 | "}"; | ||
231 | } | ||
232 | } |
File src/main/java/hu/dns/honlap/domain/package-info.java added (mode: 100644) (index 0000000..8330bab) | |||
1 | /** | ||
2 | * JPA domain objects. | ||
3 | */ | ||
4 | package hu.dns.honlap.domain; |
File src/main/java/hu/dns/honlap/repository/AuthorityRepository.java added (mode: 100644) (index 0000000..970c3a3) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.domain.Authority; | ||
4 | |||
5 | import org.springframework.data.jpa.repository.JpaRepository; | ||
6 | |||
7 | /** | ||
8 | * Spring Data JPA repository for the {@link Authority} entity. | ||
9 | */ | ||
10 | public interface AuthorityRepository extends JpaRepository<Authority, String> { | ||
11 | } |
File src/main/java/hu/dns/honlap/repository/CustomAuditEventRepository.java added (mode: 100644) (index 0000000..d21aff8) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.config.Constants; | ||
4 | import hu.dns.honlap.config.audit.AuditEventConverter; | ||
5 | import hu.dns.honlap.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 {@link 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 | } |
File src/main/java/hu/dns/honlap/repository/PersistenceAuditEventRepository.java added (mode: 100644) (index 0000000..a19005e) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.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 {@link PersistentAuditEvent} entity. | ||
13 | */ | ||
14 | public interface PersistenceAuditEventRepository extends JpaRepository<PersistentAuditEvent, Long> { | ||
15 | |||
16 | List<PersistentAuditEvent> findByPrincipal(String principal); | ||
17 | |||
18 | List<PersistentAuditEvent> findByPrincipalAndAuditEventDateAfterAndAuditEventType(String principal, Instant after, String type); | ||
19 | |||
20 | Page<PersistentAuditEvent> findAllByAuditEventDateBetween(Instant fromDate, Instant toDate, Pageable pageable); | ||
21 | |||
22 | List<PersistentAuditEvent> findByAuditEventDateBefore(Instant before); | ||
23 | } |
File src/main/java/hu/dns/honlap/repository/PieceOfNewsRepository.java added (mode: 100644) (index 0000000..5a84329) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.domain.PieceOfNews; | ||
4 | |||
5 | import org.springframework.data.jpa.repository.*; | ||
6 | import org.springframework.stereotype.Repository; | ||
7 | |||
8 | /** | ||
9 | * Spring Data repository for the PieceOfNews entity. | ||
10 | */ | ||
11 | @SuppressWarnings("unused") | ||
12 | @Repository | ||
13 | public interface PieceOfNewsRepository extends JpaRepository<PieceOfNews, Long> { | ||
14 | } |
File src/main/java/hu/dns/honlap/repository/UserRepository.java added (mode: 100644) (index 0000000..ea7b281) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.domain.User; | ||
4 | |||
5 | import org.springframework.cache.annotation.Cacheable; | ||
6 | import org.springframework.data.domain.Page; | ||
7 | |||
8 | import org.springframework.data.domain.Pageable; | ||
9 | import org.springframework.data.jpa.repository.EntityGraph; | ||
10 | import org.springframework.data.jpa.repository.JpaRepository; | ||
11 | import org.springframework.stereotype.Repository; | ||
12 | |||
13 | import java.util.List; | ||
14 | import java.util.Optional; | ||
15 | import java.time.Instant; | ||
16 | |||
17 | /** | ||
18 | * Spring Data JPA repository for the {@link User} entity. | ||
19 | */ | ||
20 | @Repository | ||
21 | public interface UserRepository extends JpaRepository<User, Long> { | ||
22 | |||
23 | String USERS_BY_LOGIN_CACHE = "usersByLogin"; | ||
24 | |||
25 | String USERS_BY_EMAIL_CACHE = "usersByEmail"; | ||
26 | |||
27 | Optional<User> findOneByActivationKey(String activationKey); | ||
28 | |||
29 | List<User> findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(Instant dateTime); | ||
30 | |||
31 | Optional<User> findOneByResetKey(String resetKey); | ||
32 | |||
33 | Optional<User> findOneByEmailIgnoreCase(String email); | ||
34 | |||
35 | Optional<User> findOneByLogin(String login); | ||
36 | |||
37 | |||
38 | |||
39 | @EntityGraph(attributePaths = "authorities") | ||
40 | Optional<User> findOneWithAuthoritiesById(Long id); | ||
41 | |||
42 | @EntityGraph(attributePaths = "authorities") | ||
43 | @Cacheable(cacheNames = USERS_BY_LOGIN_CACHE) | ||
44 | Optional<User> findOneWithAuthoritiesByLogin(String login); | ||
45 | |||
46 | @EntityGraph(attributePaths = "authorities") | ||
47 | @Cacheable(cacheNames = USERS_BY_EMAIL_CACHE) | ||
48 | Optional<User> findOneWithAuthoritiesByEmailIgnoreCase(String email); | ||
49 | |||
50 | Page<User> findAllByLoginNot(Pageable pageable, String login); | ||
51 | } |
File src/main/java/hu/dns/honlap/repository/package-info.java added (mode: 100644) (index 0000000..6eefa79) | |||
1 | /** | ||
2 | * Spring Data JPA repositories. | ||
3 | */ | ||
4 | package hu.dns.honlap.repository; |
File src/main/java/hu/dns/honlap/security/AuthoritiesConstants.java added (mode: 100644) (index 0000000..bf07416) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/security/DomainUserDetailsService.java added (mode: 100644) (index 0000000..f06cbbb) | |||
1 | package hu.dns.honlap.security; | ||
2 | |||
3 | import hu.dns.honlap.domain.User; | ||
4 | import hu.dns.honlap.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.findOneWithAuthoritiesByEmailIgnoreCase(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 | } |
File src/main/java/hu/dns/honlap/security/SecurityUtils.java added (mode: 100644) (index 0000000..f6e7182) | |||
1 | package hu.dns.honlap.security; | ||
2 | |||
3 | import org.springframework.security.core.Authentication; | ||
4 | import org.springframework.security.core.GrantedAuthority; | ||
5 | import org.springframework.security.core.context.SecurityContext; | ||
6 | import org.springframework.security.core.context.SecurityContextHolder; | ||
7 | import org.springframework.security.core.userdetails.UserDetails; | ||
8 | |||
9 | import java.util.Optional; | ||
10 | import java.util.stream.Stream; | ||
11 | |||
12 | /** | ||
13 | * Utility class for Spring Security. | ||
14 | */ | ||
15 | public final class SecurityUtils { | ||
16 | |||
17 | private SecurityUtils() { | ||
18 | } | ||
19 | |||
20 | /** | ||
21 | * Get the login of the current user. | ||
22 | * | ||
23 | * @return the login of the current user. | ||
24 | */ | ||
25 | public static Optional<String> getCurrentUserLogin() { | ||
26 | SecurityContext securityContext = SecurityContextHolder.getContext(); | ||
27 | return Optional.ofNullable(extractPrincipal(securityContext.getAuthentication())); | ||
28 | } | ||
29 | |||
30 | private static String extractPrincipal(Authentication authentication) { | ||
31 | if (authentication == null) { | ||
32 | return null; | ||
33 | } else if (authentication.getPrincipal() instanceof UserDetails) { | ||
34 | UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal(); | ||
35 | return springSecurityUser.getUsername(); | ||
36 | } else if (authentication.getPrincipal() instanceof String) { | ||
37 | return (String) authentication.getPrincipal(); | ||
38 | } | ||
39 | return null; | ||
40 | } | ||
41 | |||
42 | |||
43 | /** | ||
44 | * Get the JWT of the current user. | ||
45 | * | ||
46 | * @return the JWT of the current user. | ||
47 | */ | ||
48 | public static Optional<String> getCurrentUserJWT() { | ||
49 | SecurityContext securityContext = SecurityContextHolder.getContext(); | ||
50 | return Optional.ofNullable(securityContext.getAuthentication()) | ||
51 | .filter(authentication -> authentication.getCredentials() instanceof String) | ||
52 | .map(authentication -> (String) authentication.getCredentials()); | ||
53 | } | ||
54 | |||
55 | /** | ||
56 | * Check if a user is authenticated. | ||
57 | * | ||
58 | * @return true if the user is authenticated, false otherwise. | ||
59 | */ | ||
60 | public static boolean isAuthenticated() { | ||
61 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
62 | return authentication != null && | ||
63 | getAuthorities(authentication).noneMatch(AuthoritiesConstants.ANONYMOUS::equals); | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * If the current user has a specific authority (security role). | ||
68 | * <p> | ||
69 | * The name of this method comes from the {@code isUserInRole()} method in the Servlet API. | ||
70 | * | ||
71 | * @param authority the authority to check. | ||
72 | * @return true if the current user has the authority, false otherwise. | ||
73 | */ | ||
74 | public static boolean isCurrentUserInRole(String authority) { | ||
75 | Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); | ||
76 | return authentication != null && | ||
77 | getAuthorities(authentication).anyMatch(authority::equals); | ||
78 | } | ||
79 | |||
80 | private static Stream<String> getAuthorities(Authentication authentication) { | ||
81 | return authentication.getAuthorities().stream() | ||
82 | .map(GrantedAuthority::getAuthority); | ||
83 | } | ||
84 | |||
85 | } |
File src/main/java/hu/dns/honlap/security/SpringSecurityAuditorAware.java added (mode: 100644) (index 0000000..5271e75) | |||
1 | package hu.dns.honlap.security; | ||
2 | |||
3 | import hu.dns.honlap.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 {@link 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 | } |
File src/main/java/hu/dns/honlap/security/UserNotActivatedException.java added (mode: 100644) (index 0000000..b6c0201) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/security/jwt/JWTConfigurer.java added (mode: 100644) (index 0000000..c8bddf1) | |||
1 | package hu.dns.honlap.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 final TokenProvider tokenProvider; | ||
11 | |||
12 | public JWTConfigurer(TokenProvider tokenProvider) { | ||
13 | this.tokenProvider = tokenProvider; | ||
14 | } | ||
15 | |||
16 | @Override | ||
17 | public void configure(HttpSecurity http) { | ||
18 | JWTFilter customFilter = new JWTFilter(tokenProvider); | ||
19 | http.addFilterBefore(customFilter, UsernamePasswordAuthenticationFilter.class); | ||
20 | } | ||
21 | } |
File src/main/java/hu/dns/honlap/security/jwt/JWTFilter.java added (mode: 100644) (index 0000000..5be409c) | |||
1 | package hu.dns.honlap.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 final 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 | } |
File src/main/java/hu/dns/honlap/security/jwt/TokenProvider.java added (mode: 100644) (index 0000000..dee1a70) | |||
1 | package hu.dns.honlap.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 (JwtException | IllegalArgumentException e) { | ||
105 | log.info("Invalid JWT token."); | ||
106 | log.trace("Invalid JWT token trace.", e); | ||
107 | } | ||
108 | return false; | ||
109 | } | ||
110 | } |
File src/main/java/hu/dns/honlap/security/package-info.java added (mode: 100644) (index 0000000..bf2571c) | |||
1 | /** | ||
2 | * Spring Security configuration. | ||
3 | */ | ||
4 | package hu.dns.honlap.security; |
File src/main/java/hu/dns/honlap/service/AuditEventService.java added (mode: 100644) (index 0000000..40ab0e0) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import io.github.jhipster.config.JHipsterProperties; | ||
4 | import hu.dns.honlap.config.audit.AuditEventConverter; | ||
5 | import hu.dns.honlap.repository.PersistenceAuditEventRepository; | ||
6 | import org.slf4j.Logger; | ||
7 | import org.slf4j.LoggerFactory; | ||
8 | import org.springframework.boot.actuate.audit.AuditEvent; | ||
9 | import org.springframework.data.domain.Page; | ||
10 | import org.springframework.data.domain.Pageable; | ||
11 | import org.springframework.scheduling.annotation.Scheduled; | ||
12 | import org.springframework.stereotype.Service; | ||
13 | import org.springframework.transaction.annotation.Transactional; | ||
14 | |||
15 | import java.time.Instant; | ||
16 | import java.time.temporal.ChronoUnit; | ||
17 | import java.util.Optional; | ||
18 | |||
19 | /** | ||
20 | * Service for managing audit events. | ||
21 | * <p> | ||
22 | * This is the default implementation to support SpringBoot Actuator {@code AuditEventRepository}. | ||
23 | */ | ||
24 | @Service | ||
25 | @Transactional | ||
26 | public class AuditEventService { | ||
27 | |||
28 | private final Logger log = LoggerFactory.getLogger(AuditEventService.class); | ||
29 | |||
30 | private final JHipsterProperties jHipsterProperties; | ||
31 | |||
32 | private final PersistenceAuditEventRepository persistenceAuditEventRepository; | ||
33 | |||
34 | private final AuditEventConverter auditEventConverter; | ||
35 | |||
36 | public AuditEventService( | ||
37 | PersistenceAuditEventRepository persistenceAuditEventRepository, | ||
38 | AuditEventConverter auditEventConverter, JHipsterProperties jhipsterProperties) { | ||
39 | |||
40 | this.persistenceAuditEventRepository = persistenceAuditEventRepository; | ||
41 | this.auditEventConverter = auditEventConverter; | ||
42 | this.jHipsterProperties = jhipsterProperties; | ||
43 | } | ||
44 | |||
45 | /** | ||
46 | * Old audit events should be automatically deleted after 30 days. | ||
47 | * | ||
48 | * This is scheduled to get fired at 12:00 (am). | ||
49 | */ | ||
50 | @Scheduled(cron = "0 0 12 * * ?") | ||
51 | public void removeOldAuditEvents() { | ||
52 | persistenceAuditEventRepository | ||
53 | .findByAuditEventDateBefore(Instant.now().minus(jHipsterProperties.getAuditEvents().getRetentionPeriod(), ChronoUnit.DAYS)) | ||
54 | .forEach(auditEvent -> { | ||
55 | log.debug("Deleting audit data {}", auditEvent); | ||
56 | persistenceAuditEventRepository.delete(auditEvent); | ||
57 | }); | ||
58 | } | ||
59 | |||
60 | public Page<AuditEvent> findAll(Pageable pageable) { | ||
61 | return persistenceAuditEventRepository.findAll(pageable) | ||
62 | .map(auditEventConverter::convertToAuditEvent); | ||
63 | } | ||
64 | |||
65 | public Page<AuditEvent> findByDates(Instant fromDate, Instant toDate, Pageable pageable) { | ||
66 | return persistenceAuditEventRepository.findAllByAuditEventDateBetween(fromDate, toDate, pageable) | ||
67 | .map(auditEventConverter::convertToAuditEvent); | ||
68 | } | ||
69 | |||
70 | public Optional<AuditEvent> find(Long id) { | ||
71 | return persistenceAuditEventRepository.findById(id) | ||
72 | .map(auditEventConverter::convertToAuditEvent); | ||
73 | } | ||
74 | } |
File src/main/java/hu/dns/honlap/service/EmailAlreadyUsedException.java added (mode: 100644) (index 0000000..30b1739) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | public class EmailAlreadyUsedException extends RuntimeException { | ||
4 | |||
5 | private static final long serialVersionUID = 1L; | ||
6 | |||
7 | public EmailAlreadyUsedException() { | ||
8 | super("Email is already in use!"); | ||
9 | } | ||
10 | |||
11 | } |
File src/main/java/hu/dns/honlap/service/InvalidPasswordException.java added (mode: 100644) (index 0000000..fad3ecb) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | public class InvalidPasswordException extends RuntimeException { | ||
4 | |||
5 | private static final long serialVersionUID = 1L; | ||
6 | |||
7 | public InvalidPasswordException() { | ||
8 | super("Incorrect password"); | ||
9 | } | ||
10 | |||
11 | } |
File src/main/java/hu/dns/honlap/service/MailService.java added (mode: 100644) (index 0000000..44d8ebd) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import hu.dns.honlap.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.MessagingException; | ||
10 | import javax.mail.internet.MimeMessage; | ||
11 | |||
12 | import org.slf4j.Logger; | ||
13 | import org.slf4j.LoggerFactory; | ||
14 | import org.springframework.context.MessageSource; | ||
15 | import org.springframework.mail.MailException; | ||
16 | import org.springframework.mail.javamail.JavaMailSender; | ||
17 | import org.springframework.mail.javamail.MimeMessageHelper; | ||
18 | import org.springframework.scheduling.annotation.Async; | ||
19 | import org.springframework.stereotype.Service; | ||
20 | import org.thymeleaf.context.Context; | ||
21 | import org.thymeleaf.spring5.SpringTemplateEngine; | ||
22 | |||
23 | /** | ||
24 | * Service for sending emails. | ||
25 | * <p> | ||
26 | * We use the {@link Async} annotation to send emails asynchronously. | ||
27 | */ | ||
28 | @Service | ||
29 | public class MailService { | ||
30 | |||
31 | private final Logger log = LoggerFactory.getLogger(MailService.class); | ||
32 | |||
33 | private static final String USER = "user"; | ||
34 | |||
35 | private static final String BASE_URL = "baseUrl"; | ||
36 | |||
37 | private final JHipsterProperties jHipsterProperties; | ||
38 | |||
39 | private final JavaMailSender javaMailSender; | ||
40 | |||
41 | private final MessageSource messageSource; | ||
42 | |||
43 | private final SpringTemplateEngine templateEngine; | ||
44 | |||
45 | public MailService(JHipsterProperties jHipsterProperties, JavaMailSender javaMailSender, | ||
46 | MessageSource messageSource, SpringTemplateEngine templateEngine) { | ||
47 | |||
48 | this.jHipsterProperties = jHipsterProperties; | ||
49 | this.javaMailSender = javaMailSender; | ||
50 | this.messageSource = messageSource; | ||
51 | this.templateEngine = templateEngine; | ||
52 | } | ||
53 | |||
54 | @Async | ||
55 | public void sendEmail(String to, String subject, String content, boolean isMultipart, boolean isHtml) { | ||
56 | log.debug("Send email[multipart '{}' and html '{}'] to '{}' with subject '{}' and content={}", | ||
57 | isMultipart, isHtml, to, subject, content); | ||
58 | |||
59 | // Prepare message using a Spring helper | ||
60 | MimeMessage mimeMessage = javaMailSender.createMimeMessage(); | ||
61 | try { | ||
62 | MimeMessageHelper message = new MimeMessageHelper(mimeMessage, isMultipart, StandardCharsets.UTF_8.name()); | ||
63 | message.setTo(to); | ||
64 | message.setFrom(jHipsterProperties.getMail().getFrom()); | ||
65 | message.setSubject(subject); | ||
66 | message.setText(content, isHtml); | ||
67 | javaMailSender.send(mimeMessage); | ||
68 | log.debug("Sent email to User '{}'", to); | ||
69 | } catch (MailException | MessagingException e) { | ||
70 | log.warn("Email could not be sent to user '{}'", to, e); | ||
71 | } | ||
72 | } | ||
73 | |||
74 | @Async | ||
75 | public void sendEmailFromTemplate(User user, String templateName, String titleKey) { | ||
76 | if (user.getEmail() == null) { | ||
77 | log.debug("Email doesn't exist for user '{}'", user.getLogin()); | ||
78 | return; | ||
79 | } | ||
80 | Locale locale = Locale.forLanguageTag(user.getLangKey()); | ||
81 | Context context = new Context(locale); | ||
82 | context.setVariable(USER, user); | ||
83 | context.setVariable(BASE_URL, jHipsterProperties.getMail().getBaseUrl()); | ||
84 | String content = templateEngine.process(templateName, context); | ||
85 | String subject = messageSource.getMessage(titleKey, null, locale); | ||
86 | sendEmail(user.getEmail(), subject, content, false, true); | ||
87 | } | ||
88 | |||
89 | @Async | ||
90 | public void sendActivationEmail(User user) { | ||
91 | log.debug("Sending activation email to '{}'", user.getEmail()); | ||
92 | sendEmailFromTemplate(user, "mail/activationEmail", "email.activation.title"); | ||
93 | } | ||
94 | |||
95 | @Async | ||
96 | public void sendCreationEmail(User user) { | ||
97 | log.debug("Sending creation email to '{}'", user.getEmail()); | ||
98 | sendEmailFromTemplate(user, "mail/creationEmail", "email.activation.title"); | ||
99 | } | ||
100 | |||
101 | @Async | ||
102 | public void sendPasswordResetMail(User user) { | ||
103 | log.debug("Sending password reset email to '{}'", user.getEmail()); | ||
104 | sendEmailFromTemplate(user, "mail/passwordResetEmail", "email.reset.title"); | ||
105 | } | ||
106 | } |
File src/main/java/hu/dns/honlap/service/UserService.java added (mode: 100644) (index 0000000..cbfa5ce) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import hu.dns.honlap.config.Constants; | ||
4 | import hu.dns.honlap.domain.Authority; | ||
5 | import hu.dns.honlap.domain.User; | ||
6 | import hu.dns.honlap.repository.AuthorityRepository; | ||
7 | import hu.dns.honlap.repository.UserRepository; | ||
8 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
9 | import hu.dns.honlap.security.SecurityUtils; | ||
10 | import hu.dns.honlap.service.dto.UserDTO; | ||
11 | |||
12 | import io.github.jhipster.security.RandomUtil; | ||
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 UsernameAlreadyUsedException(); | ||
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 | if (userDTO.getEmail() != null) { | ||
111 | newUser.setEmail(userDTO.getEmail().toLowerCase()); | ||
112 | } | ||
113 | newUser.setImageUrl(userDTO.getImageUrl()); | ||
114 | newUser.setLangKey(userDTO.getLangKey()); | ||
115 | // new user is not active | ||
116 | newUser.setActivated(false); | ||
117 | // new user gets registration key | ||
118 | newUser.setActivationKey(RandomUtil.generateActivationKey()); | ||
119 | Set<Authority> authorities = new HashSet<>(); | ||
120 | authorityRepository.findById(AuthoritiesConstants.USER).ifPresent(authorities::add); | ||
121 | newUser.setAuthorities(authorities); | ||
122 | userRepository.save(newUser); | ||
123 | this.clearUserCaches(newUser); | ||
124 | log.debug("Created Information for User: {}", newUser); | ||
125 | return newUser; | ||
126 | } | ||
127 | |||
128 | private boolean removeNonActivatedUser(User existingUser) { | ||
129 | if (existingUser.getActivated()) { | ||
130 | return false; | ||
131 | } | ||
132 | userRepository.delete(existingUser); | ||
133 | userRepository.flush(); | ||
134 | this.clearUserCaches(existingUser); | ||
135 | return true; | ||
136 | } | ||
137 | |||
138 | public User createUser(UserDTO userDTO) { | ||
139 | User user = new User(); | ||
140 | user.setLogin(userDTO.getLogin().toLowerCase()); | ||
141 | user.setFirstName(userDTO.getFirstName()); | ||
142 | user.setLastName(userDTO.getLastName()); | ||
143 | if (userDTO.getEmail() != null) { | ||
144 | user.setEmail(userDTO.getEmail().toLowerCase()); | ||
145 | } | ||
146 | user.setImageUrl(userDTO.getImageUrl()); | ||
147 | if (userDTO.getLangKey() == null) { | ||
148 | user.setLangKey(Constants.DEFAULT_LANGUAGE); // default language | ||
149 | } else { | ||
150 | user.setLangKey(userDTO.getLangKey()); | ||
151 | } | ||
152 | String encryptedPassword = passwordEncoder.encode(RandomUtil.generatePassword()); | ||
153 | user.setPassword(encryptedPassword); | ||
154 | user.setResetKey(RandomUtil.generateResetKey()); | ||
155 | user.setResetDate(Instant.now()); | ||
156 | user.setActivated(true); | ||
157 | if (userDTO.getAuthorities() != null) { | ||
158 | Set<Authority> authorities = userDTO.getAuthorities().stream() | ||
159 | .map(authorityRepository::findById) | ||
160 | .filter(Optional::isPresent) | ||
161 | .map(Optional::get) | ||
162 | .collect(Collectors.toSet()); | ||
163 | user.setAuthorities(authorities); | ||
164 | } | ||
165 | userRepository.save(user); | ||
166 | this.clearUserCaches(user); | ||
167 | log.debug("Created Information for User: {}", user); | ||
168 | return user; | ||
169 | } | ||
170 | |||
171 | /** | ||
172 | * Update basic information (first name, last name, email, language) for the current user. | ||
173 | * | ||
174 | * @param firstName first name of user. | ||
175 | * @param lastName last name of user. | ||
176 | * @param email email id of user. | ||
177 | * @param langKey language key. | ||
178 | * @param imageUrl image URL of user. | ||
179 | */ | ||
180 | public void updateUser(String firstName, String lastName, String email, String langKey, String imageUrl) { | ||
181 | SecurityUtils.getCurrentUserLogin() | ||
182 | .flatMap(userRepository::findOneByLogin) | ||
183 | .ifPresent(user -> { | ||
184 | user.setFirstName(firstName); | ||
185 | user.setLastName(lastName); | ||
186 | if (email != null) { | ||
187 | user.setEmail(email.toLowerCase()); | ||
188 | } | ||
189 | user.setLangKey(langKey); | ||
190 | user.setImageUrl(imageUrl); | ||
191 | this.clearUserCaches(user); | ||
192 | log.debug("Changed Information for User: {}", user); | ||
193 | }); | ||
194 | } | ||
195 | |||
196 | /** | ||
197 | * Update all information for a specific user, and return the modified user. | ||
198 | * | ||
199 | * @param userDTO user to update. | ||
200 | * @return updated user. | ||
201 | */ | ||
202 | public Optional<UserDTO> updateUser(UserDTO userDTO) { | ||
203 | return Optional.of(userRepository | ||
204 | .findById(userDTO.getId())) | ||
205 | .filter(Optional::isPresent) | ||
206 | .map(Optional::get) | ||
207 | .map(user -> { | ||
208 | this.clearUserCaches(user); | ||
209 | user.setLogin(userDTO.getLogin().toLowerCase()); | ||
210 | user.setFirstName(userDTO.getFirstName()); | ||
211 | user.setLastName(userDTO.getLastName()); | ||
212 | if (userDTO.getEmail() != null) { | ||
213 | user.setEmail(userDTO.getEmail().toLowerCase()); | ||
214 | } | ||
215 | user.setImageUrl(userDTO.getImageUrl()); | ||
216 | user.setActivated(userDTO.isActivated()); | ||
217 | user.setLangKey(userDTO.getLangKey()); | ||
218 | Set<Authority> managedAuthorities = user.getAuthorities(); | ||
219 | managedAuthorities.clear(); | ||
220 | userDTO.getAuthorities().stream() | ||
221 | .map(authorityRepository::findById) | ||
222 | .filter(Optional::isPresent) | ||
223 | .map(Optional::get) | ||
224 | .forEach(managedAuthorities::add); | ||
225 | this.clearUserCaches(user); | ||
226 | log.debug("Changed Information for User: {}", user); | ||
227 | return user; | ||
228 | }) | ||
229 | .map(UserDTO::new); | ||
230 | } | ||
231 | |||
232 | public void deleteUser(String login) { | ||
233 | userRepository.findOneByLogin(login).ifPresent(user -> { | ||
234 | userRepository.delete(user); | ||
235 | this.clearUserCaches(user); | ||
236 | log.debug("Deleted User: {}", user); | ||
237 | }); | ||
238 | } | ||
239 | |||
240 | public void changePassword(String currentClearTextPassword, String newPassword) { | ||
241 | SecurityUtils.getCurrentUserLogin() | ||
242 | .flatMap(userRepository::findOneByLogin) | ||
243 | .ifPresent(user -> { | ||
244 | String currentEncryptedPassword = user.getPassword(); | ||
245 | if (!passwordEncoder.matches(currentClearTextPassword, currentEncryptedPassword)) { | ||
246 | throw new InvalidPasswordException(); | ||
247 | } | ||
248 | String encryptedPassword = passwordEncoder.encode(newPassword); | ||
249 | user.setPassword(encryptedPassword); | ||
250 | this.clearUserCaches(user); | ||
251 | log.debug("Changed password for User: {}", user); | ||
252 | }); | ||
253 | } | ||
254 | |||
255 | @Transactional(readOnly = true) | ||
256 | public Page<UserDTO> getAllManagedUsers(Pageable pageable) { | ||
257 | return userRepository.findAllByLoginNot(pageable, Constants.ANONYMOUS_USER).map(UserDTO::new); | ||
258 | } | ||
259 | |||
260 | @Transactional(readOnly = true) | ||
261 | public Optional<User> getUserWithAuthoritiesByLogin(String login) { | ||
262 | return userRepository.findOneWithAuthoritiesByLogin(login); | ||
263 | } | ||
264 | |||
265 | @Transactional(readOnly = true) | ||
266 | public Optional<User> getUserWithAuthorities(Long id) { | ||
267 | return userRepository.findOneWithAuthoritiesById(id); | ||
268 | } | ||
269 | |||
270 | @Transactional(readOnly = true) | ||
271 | public Optional<User> getUserWithAuthorities() { | ||
272 | return SecurityUtils.getCurrentUserLogin().flatMap(userRepository::findOneWithAuthoritiesByLogin); | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Not activated users should be automatically deleted after 3 days. | ||
277 | * <p> | ||
278 | * This is scheduled to get fired everyday, at 01:00 (am). | ||
279 | */ | ||
280 | @Scheduled(cron = "0 0 1 * * ?") | ||
281 | public void removeNotActivatedUsers() { | ||
282 | userRepository | ||
283 | .findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(Instant.now().minus(3, ChronoUnit.DAYS)) | ||
284 | .forEach(user -> { | ||
285 | log.debug("Deleting not activated user {}", user.getLogin()); | ||
286 | userRepository.delete(user); | ||
287 | this.clearUserCaches(user); | ||
288 | }); | ||
289 | } | ||
290 | |||
291 | /** | ||
292 | * Gets a list of all the authorities. | ||
293 | * @return a list of all the authorities. | ||
294 | */ | ||
295 | public List<String> getAuthorities() { | ||
296 | return authorityRepository.findAll().stream().map(Authority::getName).collect(Collectors.toList()); | ||
297 | } | ||
298 | |||
299 | |||
300 | private void clearUserCaches(User user) { | ||
301 | Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE)).evict(user.getLogin()); | ||
302 | if (user.getEmail() != null) { | ||
303 | Objects.requireNonNull(cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE)).evict(user.getEmail()); | ||
304 | } | ||
305 | } | ||
306 | } |
File src/main/java/hu/dns/honlap/service/UsernameAlreadyUsedException.java added (mode: 100644) (index 0000000..37566c4) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | public class UsernameAlreadyUsedException extends RuntimeException { | ||
4 | |||
5 | private static final long serialVersionUID = 1L; | ||
6 | |||
7 | public UsernameAlreadyUsedException() { | ||
8 | super("Login name already used!"); | ||
9 | } | ||
10 | |||
11 | } |
File src/main/java/hu/dns/honlap/service/dto/PasswordChangeDTO.java added (mode: 100644) (index 0000000..056edf3) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/service/dto/UserDTO.java added (mode: 100644) (index 0000000..5cb3af8) | |||
1 | package hu.dns.honlap.service.dto; | ||
2 | |||
3 | import hu.dns.honlap.config.Constants; | ||
4 | |||
5 | import hu.dns.honlap.domain.Authority; | ||
6 | import hu.dns.honlap.domain.User; | ||
7 | |||
8 | import javax.validation.constraints.*; | ||
9 | import java.time.Instant; | ||
10 | import java.util.Set; | ||
11 | import java.util.stream.Collectors; | ||
12 | |||
13 | /** | ||
14 | * A DTO representing a user, with his authorities. | ||
15 | */ | ||
16 | public class UserDTO { | ||
17 | |||
18 | private Long id; | ||
19 | |||
20 | @NotBlank | ||
21 | @Pattern(regexp = Constants.LOGIN_REGEX) | ||
22 | @Size(min = 1, max = 50) | ||
23 | private String login; | ||
24 | |||
25 | @Size(max = 50) | ||
26 | private String firstName; | ||
27 | |||
28 | @Size(max = 50) | ||
29 | private String lastName; | ||
30 | |||
31 | |||
32 | @Size(min = 5, max = 254) | ||
33 | private String email; | ||
34 | |||
35 | @Size(max = 256) | ||
36 | private String imageUrl; | ||
37 | |||
38 | private boolean activated = false; | ||
39 | |||
40 | @Size(min = 2, max = 10) | ||
41 | private String langKey; | ||
42 | |||
43 | private String createdBy; | ||
44 | |||
45 | private Instant createdDate; | ||
46 | |||
47 | private String lastModifiedBy; | ||
48 | |||
49 | private Instant lastModifiedDate; | ||
50 | |||
51 | private Set<String> authorities; | ||
52 | |||
53 | public UserDTO() { | ||
54 | // Empty constructor needed for Jackson. | ||
55 | } | ||
56 | |||
57 | public UserDTO(User user) { | ||
58 | this.id = user.getId(); | ||
59 | this.login = user.getLogin(); | ||
60 | this.firstName = user.getFirstName(); | ||
61 | this.lastName = user.getLastName(); | ||
62 | this.email = user.getEmail(); | ||
63 | this.activated = user.getActivated(); | ||
64 | this.imageUrl = user.getImageUrl(); | ||
65 | this.langKey = user.getLangKey(); | ||
66 | this.createdBy = user.getCreatedBy(); | ||
67 | this.createdDate = user.getCreatedDate(); | ||
68 | this.lastModifiedBy = user.getLastModifiedBy(); | ||
69 | this.lastModifiedDate = user.getLastModifiedDate(); | ||
70 | this.authorities = user.getAuthorities().stream() | ||
71 | .map(Authority::getName) | ||
72 | .collect(Collectors.toSet()); | ||
73 | } | ||
74 | |||
75 | public Long getId() { | ||
76 | return id; | ||
77 | } | ||
78 | |||
79 | public void setId(Long id) { | ||
80 | this.id = id; | ||
81 | } | ||
82 | |||
83 | public String getLogin() { | ||
84 | return login; | ||
85 | } | ||
86 | |||
87 | public void setLogin(String login) { | ||
88 | this.login = login; | ||
89 | } | ||
90 | |||
91 | public String getFirstName() { | ||
92 | return firstName; | ||
93 | } | ||
94 | |||
95 | public void setFirstName(String firstName) { | ||
96 | this.firstName = firstName; | ||
97 | } | ||
98 | |||
99 | public String getLastName() { | ||
100 | return lastName; | ||
101 | } | ||
102 | |||
103 | public void setLastName(String lastName) { | ||
104 | this.lastName = lastName; | ||
105 | } | ||
106 | |||
107 | public String getEmail() { | ||
108 | return email; | ||
109 | } | ||
110 | |||
111 | public void setEmail(String email) { | ||
112 | this.email = email; | ||
113 | } | ||
114 | |||
115 | public String getImageUrl() { | ||
116 | return imageUrl; | ||
117 | } | ||
118 | |||
119 | public void setImageUrl(String imageUrl) { | ||
120 | this.imageUrl = imageUrl; | ||
121 | } | ||
122 | |||
123 | public boolean isActivated() { | ||
124 | return activated; | ||
125 | } | ||
126 | |||
127 | public void setActivated(boolean activated) { | ||
128 | this.activated = activated; | ||
129 | } | ||
130 | |||
131 | public String getLangKey() { | ||
132 | return langKey; | ||
133 | } | ||
134 | |||
135 | public void setLangKey(String langKey) { | ||
136 | this.langKey = langKey; | ||
137 | } | ||
138 | |||
139 | public String getCreatedBy() { | ||
140 | return createdBy; | ||
141 | } | ||
142 | |||
143 | public void setCreatedBy(String createdBy) { | ||
144 | this.createdBy = createdBy; | ||
145 | } | ||
146 | |||
147 | public Instant getCreatedDate() { | ||
148 | return createdDate; | ||
149 | } | ||
150 | |||
151 | public void setCreatedDate(Instant createdDate) { | ||
152 | this.createdDate = createdDate; | ||
153 | } | ||
154 | |||
155 | public String getLastModifiedBy() { | ||
156 | return lastModifiedBy; | ||
157 | } | ||
158 | |||
159 | public void setLastModifiedBy(String lastModifiedBy) { | ||
160 | this.lastModifiedBy = lastModifiedBy; | ||
161 | } | ||
162 | |||
163 | public Instant getLastModifiedDate() { | ||
164 | return lastModifiedDate; | ||
165 | } | ||
166 | |||
167 | public void setLastModifiedDate(Instant lastModifiedDate) { | ||
168 | this.lastModifiedDate = lastModifiedDate; | ||
169 | } | ||
170 | |||
171 | public Set<String> getAuthorities() { | ||
172 | return authorities; | ||
173 | } | ||
174 | |||
175 | public void setAuthorities(Set<String> authorities) { | ||
176 | this.authorities = authorities; | ||
177 | } | ||
178 | |||
179 | @Override | ||
180 | public String toString() { | ||
181 | return "UserDTO{" + | ||
182 | "login='" + login + '\'' + | ||
183 | ", firstName='" + firstName + '\'' + | ||
184 | ", lastName='" + lastName + '\'' + | ||
185 | ", email='" + email + '\'' + | ||
186 | ", imageUrl='" + imageUrl + '\'' + | ||
187 | ", activated=" + activated + | ||
188 | ", langKey='" + langKey + '\'' + | ||
189 | ", createdBy=" + createdBy + | ||
190 | ", createdDate=" + createdDate + | ||
191 | ", lastModifiedBy='" + lastModifiedBy + '\'' + | ||
192 | ", lastModifiedDate=" + lastModifiedDate + | ||
193 | ", authorities=" + authorities + | ||
194 | "}"; | ||
195 | } | ||
196 | } |
File src/main/java/hu/dns/honlap/service/dto/package-info.java added (mode: 100644) (index 0000000..21d1c52) | |||
1 | /** | ||
2 | * Data Transfer Objects. | ||
3 | */ | ||
4 | package hu.dns.honlap.service.dto; |
File src/main/java/hu/dns/honlap/service/mapper/UserMapper.java added (mode: 100644) (index 0000000..cc5d50c) | |||
1 | package hu.dns.honlap.service.mapper; | ||
2 | |||
3 | import hu.dns.honlap.domain.Authority; | ||
4 | import hu.dns.honlap.domain.User; | ||
5 | import hu.dns.honlap.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 {@link User} and its DTO called {@link 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 List<UserDTO> usersToUserDTOs(List<User> users) { | ||
22 | return users.stream() | ||
23 | .filter(Objects::nonNull) | ||
24 | .map(this::userToUserDTO) | ||
25 | .collect(Collectors.toList()); | ||
26 | } | ||
27 | |||
28 | public UserDTO userToUserDTO(User user) { | ||
29 | return new UserDTO(user); | ||
30 | } | ||
31 | |||
32 | public List<User> userDTOsToUsers(List<UserDTO> userDTOs) { | ||
33 | return userDTOs.stream() | ||
34 | .filter(Objects::nonNull) | ||
35 | .map(this::userDTOToUser) | ||
36 | .collect(Collectors.toList()); | ||
37 | } | ||
38 | |||
39 | public User userDTOToUser(UserDTO userDTO) { | ||
40 | if (userDTO == null) { | ||
41 | return null; | ||
42 | } else { | ||
43 | User user = new User(); | ||
44 | user.setId(userDTO.getId()); | ||
45 | user.setLogin(userDTO.getLogin()); | ||
46 | user.setFirstName(userDTO.getFirstName()); | ||
47 | user.setLastName(userDTO.getLastName()); | ||
48 | user.setEmail(userDTO.getEmail()); | ||
49 | user.setImageUrl(userDTO.getImageUrl()); | ||
50 | user.setActivated(userDTO.isActivated()); | ||
51 | user.setLangKey(userDTO.getLangKey()); | ||
52 | Set<Authority> authorities = this.authoritiesFromStrings(userDTO.getAuthorities()); | ||
53 | user.setAuthorities(authorities); | ||
54 | return user; | ||
55 | } | ||
56 | } | ||
57 | |||
58 | |||
59 | private Set<Authority> authoritiesFromStrings(Set<String> authoritiesAsString) { | ||
60 | Set<Authority> authorities = new HashSet<>(); | ||
61 | |||
62 | if (authoritiesAsString != null) { | ||
63 | authorities = authoritiesAsString.stream().map(string -> { | ||
64 | Authority auth = new Authority(); | ||
65 | auth.setName(string); | ||
66 | return auth; | ||
67 | }).collect(Collectors.toSet()); | ||
68 | } | ||
69 | |||
70 | return authorities; | ||
71 | } | ||
72 | |||
73 | public User userFromId(Long id) { | ||
74 | if (id == null) { | ||
75 | return null; | ||
76 | } | ||
77 | User user = new User(); | ||
78 | user.setId(id); | ||
79 | return user; | ||
80 | } | ||
81 | } |
File src/main/java/hu/dns/honlap/service/mapper/package-info.java added (mode: 100644) (index 0000000..af2199c) | |||
1 | /** | ||
2 | * MapStruct mappers for mapping domain objects and Data Transfer Objects. | ||
3 | */ | ||
4 | package hu.dns.honlap.service.mapper; |
File src/main/java/hu/dns/honlap/service/package-info.java added (mode: 100644) (index 0000000..0835a98) | |||
1 | /** | ||
2 | * Service layer beans. | ||
3 | */ | ||
4 | package hu.dns.honlap.service; |
File src/main/java/hu/dns/honlap/web/rest/AccountResource.java added (mode: 100644) (index 0000000..1c59eaf) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.domain.User; | ||
4 | import hu.dns.honlap.repository.UserRepository; | ||
5 | import hu.dns.honlap.security.SecurityUtils; | ||
6 | import hu.dns.honlap.service.MailService; | ||
7 | import hu.dns.honlap.service.UserService; | ||
8 | import hu.dns.honlap.service.dto.PasswordChangeDTO; | ||
9 | import hu.dns.honlap.service.dto.UserDTO; | ||
10 | import hu.dns.honlap.web.rest.errors.*; | ||
11 | import hu.dns.honlap.web.rest.vm.KeyAndPasswordVM; | ||
12 | import hu.dns.honlap.web.rest.vm.ManagedUserVM; | ||
13 | |||
14 | import org.apache.commons.lang3.StringUtils; | ||
15 | import org.slf4j.Logger; | ||
16 | import org.slf4j.LoggerFactory; | ||
17 | import org.springframework.http.HttpStatus; | ||
18 | import org.springframework.web.bind.annotation.*; | ||
19 | |||
20 | import javax.servlet.http.HttpServletRequest; | ||
21 | import javax.validation.Valid; | ||
22 | import java.util.*; | ||
23 | |||
24 | /** | ||
25 | * REST controller for managing the current user's account. | ||
26 | */ | ||
27 | @RestController | ||
28 | @RequestMapping("/api") | ||
29 | public class AccountResource { | ||
30 | |||
31 | private static class AccountResourceException extends RuntimeException { | ||
32 | private AccountResourceException(String message) { | ||
33 | super(message); | ||
34 | } | ||
35 | } | ||
36 | |||
37 | private final Logger log = LoggerFactory.getLogger(AccountResource.class); | ||
38 | |||
39 | private final UserRepository userRepository; | ||
40 | |||
41 | private final UserService userService; | ||
42 | |||
43 | private final MailService mailService; | ||
44 | |||
45 | public AccountResource(UserRepository userRepository, UserService userService, MailService mailService) { | ||
46 | |||
47 | this.userRepository = userRepository; | ||
48 | this.userService = userService; | ||
49 | this.mailService = mailService; | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * {@code POST /register} : register the user. | ||
54 | * | ||
55 | * @param managedUserVM the managed user View Model. | ||
56 | * @throws InvalidPasswordException {@code 400 (Bad Request)} if the password is incorrect. | ||
57 | * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already used. | ||
58 | * @throws LoginAlreadyUsedException {@code 400 (Bad Request)} if the login is already used. | ||
59 | */ | ||
60 | @PostMapping("/register") | ||
61 | @ResponseStatus(HttpStatus.CREATED) | ||
62 | public void registerAccount(@Valid @RequestBody ManagedUserVM managedUserVM) { | ||
63 | if (!checkPasswordLength(managedUserVM.getPassword())) { | ||
64 | throw new InvalidPasswordException(); | ||
65 | } | ||
66 | User user = userService.registerUser(managedUserVM, managedUserVM.getPassword()); | ||
67 | mailService.sendActivationEmail(user); | ||
68 | } | ||
69 | |||
70 | /** | ||
71 | * {@code GET /activate} : activate the registered user. | ||
72 | * | ||
73 | * @param key the activation key. | ||
74 | * @throws RuntimeException {@code 500 (Internal Server Error)} if the user couldn't be activated. | ||
75 | */ | ||
76 | @GetMapping("/activate") | ||
77 | public void activateAccount(@RequestParam(value = "key") String key) { | ||
78 | Optional<User> user = userService.activateRegistration(key); | ||
79 | if (!user.isPresent()) { | ||
80 | throw new AccountResourceException("No user was found for this activation key"); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * {@code GET /authenticate} : check if the user is authenticated, and return its login. | ||
86 | * | ||
87 | * @param request the HTTP request. | ||
88 | * @return the login if the user is authenticated. | ||
89 | */ | ||
90 | @GetMapping("/authenticate") | ||
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 | * {@code GET /account} : get the current user. | ||
98 | * | ||
99 | * @return the current user. | ||
100 | * @throws RuntimeException {@code 500 (Internal Server Error)} if the user couldn't be returned. | ||
101 | */ | ||
102 | @GetMapping("/account") | ||
103 | public UserDTO getAccount() { | ||
104 | return userService.getUserWithAuthorities() | ||
105 | .map(UserDTO::new) | ||
106 | .orElseThrow(() -> new AccountResourceException("User could not be found")); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * {@code POST /account} : update the current user information. | ||
111 | * | ||
112 | * @param userDTO the current user information. | ||
113 | * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already used. | ||
114 | * @throws RuntimeException {@code 500 (Internal Server Error)} if the user login wasn't found. | ||
115 | */ | ||
116 | @PostMapping("/account") | ||
117 | public void saveAccount(@Valid @RequestBody UserDTO userDTO) { | ||
118 | String userLogin = SecurityUtils.getCurrentUserLogin().orElseThrow(() -> new AccountResourceException("Current user login not found")); | ||
119 | Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); | ||
120 | if (existingUser.isPresent() && (!existingUser.get().getLogin().equalsIgnoreCase(userLogin))) { | ||
121 | throw new EmailAlreadyUsedException(); | ||
122 | } | ||
123 | Optional<User> user = userRepository.findOneByLogin(userLogin); | ||
124 | if (!user.isPresent()) { | ||
125 | throw new AccountResourceException("User could not be found"); | ||
126 | } | ||
127 | userService.updateUser(userDTO.getFirstName(), userDTO.getLastName(), userDTO.getEmail(), | ||
128 | userDTO.getLangKey(), userDTO.getImageUrl()); | ||
129 | } | ||
130 | |||
131 | /** | ||
132 | * {@code POST /account/change-password} : changes the current user's password. | ||
133 | * | ||
134 | * @param passwordChangeDto current and new password. | ||
135 | * @throws InvalidPasswordException {@code 400 (Bad Request)} if the new password is incorrect. | ||
136 | */ | ||
137 | @PostMapping(path = "/account/change-password") | ||
138 | public void changePassword(@RequestBody PasswordChangeDTO passwordChangeDto) { | ||
139 | if (!checkPasswordLength(passwordChangeDto.getNewPassword())) { | ||
140 | throw new InvalidPasswordException(); | ||
141 | } | ||
142 | userService.changePassword(passwordChangeDto.getCurrentPassword(), passwordChangeDto.getNewPassword()); | ||
143 | } | ||
144 | |||
145 | /** | ||
146 | * {@code POST /account/reset-password/init} : Send an email to reset the password of the user. | ||
147 | * | ||
148 | * @param mail the mail of the user. | ||
149 | */ | ||
150 | @PostMapping(path = "/account/reset-password/init") | ||
151 | public void requestPasswordReset(@RequestBody String mail) { | ||
152 | Optional<User> user = userService.requestPasswordReset(mail); | ||
153 | if (user.isPresent()) { | ||
154 | mailService.sendPasswordResetMail(user.get()); | ||
155 | } else { | ||
156 | // Pretend the request has been successful to prevent checking which emails really exist | ||
157 | // but log that an invalid attempt has been made | ||
158 | log.warn("Password reset requested for non existing mail '{}'", mail); | ||
159 | } | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * {@code POST /account/reset-password/finish} : Finish to reset the password of the user. | ||
164 | * | ||
165 | * @param keyAndPassword the generated key and the new password. | ||
166 | * @throws InvalidPasswordException {@code 400 (Bad Request)} if the password is incorrect. | ||
167 | * @throws RuntimeException {@code 500 (Internal Server Error)} if the password could not be reset. | ||
168 | */ | ||
169 | @PostMapping(path = "/account/reset-password/finish") | ||
170 | public void finishPasswordReset(@RequestBody KeyAndPasswordVM keyAndPassword) { | ||
171 | if (!checkPasswordLength(keyAndPassword.getNewPassword())) { | ||
172 | throw new InvalidPasswordException(); | ||
173 | } | ||
174 | Optional<User> user = | ||
175 | userService.completePasswordReset(keyAndPassword.getNewPassword(), keyAndPassword.getKey()); | ||
176 | |||
177 | if (!user.isPresent()) { | ||
178 | throw new AccountResourceException("No user was found for this reset key"); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | private static boolean checkPasswordLength(String password) { | ||
183 | return !StringUtils.isEmpty(password) && | ||
184 | password.length() >= ManagedUserVM.PASSWORD_MIN_LENGTH && | ||
185 | password.length() <= ManagedUserVM.PASSWORD_MAX_LENGTH; | ||
186 | } | ||
187 | } |
File src/main/java/hu/dns/honlap/web/rest/AuditResource.java added (mode: 100644) (index 0000000..4421306) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.service.AuditEventService; | ||
4 | |||
5 | import io.github.jhipster.web.util.PaginationUtil; | ||
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 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
15 | |||
16 | import java.time.Instant; | ||
17 | import java.time.LocalDate; | ||
18 | import java.time.ZoneId; | ||
19 | import java.util.List; | ||
20 | |||
21 | /** | ||
22 | * REST controller for getting the {@link AuditEvent}s. | ||
23 | */ | ||
24 | @RestController | ||
25 | @RequestMapping("/management/audits") | ||
26 | public class AuditResource { | ||
27 | |||
28 | private final AuditEventService auditEventService; | ||
29 | |||
30 | public AuditResource(AuditEventService auditEventService) { | ||
31 | this.auditEventService = auditEventService; | ||
32 | } | ||
33 | |||
34 | /** | ||
35 | * {@code GET /audits} : get a page of {@link AuditEvent}s. | ||
36 | * | ||
37 | * @param pageable the pagination information. | ||
38 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of {@link AuditEvent}s in body. | ||
39 | */ | ||
40 | @GetMapping | ||
41 | public ResponseEntity<List<AuditEvent>> getAll(Pageable pageable) { | ||
42 | Page<AuditEvent> page = auditEventService.findAll(pageable); | ||
43 | HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); | ||
44 | return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); | ||
45 | } | ||
46 | |||
47 | /** | ||
48 | * {@code GET /audits} : get a page of {@link AuditEvent} between the {@code fromDate} and {@code toDate}. | ||
49 | * | ||
50 | * @param fromDate the start of the time period of {@link AuditEvent} to get. | ||
51 | * @param toDate the end of the time period of {@link AuditEvent} to get. | ||
52 | * @param pageable the pagination information. | ||
53 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of {@link AuditEvent} in body. | ||
54 | */ | ||
55 | @GetMapping(params = {"fromDate", "toDate"}) | ||
56 | public ResponseEntity<List<AuditEvent>> getByDates( | ||
57 | @RequestParam(value = "fromDate") LocalDate fromDate, | ||
58 | @RequestParam(value = "toDate") LocalDate toDate, | ||
59 | Pageable pageable) { | ||
60 | |||
61 | Instant from = fromDate.atStartOfDay(ZoneId.systemDefault()).toInstant(); | ||
62 | Instant to = toDate.atStartOfDay(ZoneId.systemDefault()).plusDays(1).toInstant(); | ||
63 | |||
64 | Page<AuditEvent> page = auditEventService.findByDates(from, to, pageable); | ||
65 | HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); | ||
66 | return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * {@code GET /audits/:id} : get an {@link AuditEvent} by id. | ||
71 | * | ||
72 | * @param id the id of the entity to get. | ||
73 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the {@link AuditEvent} in body, or status {@code 404 (Not Found)}. | ||
74 | */ | ||
75 | @GetMapping("/{id:.+}") | ||
76 | public ResponseEntity<AuditEvent> get(@PathVariable Long id) { | ||
77 | return ResponseUtil.wrapOrNotFound(auditEventService.find(id)); | ||
78 | } | ||
79 | } |
File src/main/java/hu/dns/honlap/web/rest/ClientForwardController.java added (mode: 100644) (index 0000000..751a530) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import org.springframework.stereotype.Controller; | ||
4 | import org.springframework.web.bind.annotation.GetMapping; | ||
5 | |||
6 | @Controller | ||
7 | public class ClientForwardController { | ||
8 | |||
9 | /** | ||
10 | * Forwards any unmapped paths (except those containing a period) to the client {@code index.html}. | ||
11 | * @return forward to client {@code index.html}. | ||
12 | */ | ||
13 | @GetMapping(value = "/**/{path:[^\\.]*}") | ||
14 | public String forward() { | ||
15 | return "forward:/"; | ||
16 | } | ||
17 | } |
File src/main/java/hu/dns/honlap/web/rest/PieceOfNewsResource.java added (mode: 100644) (index 0000000..1f4a43d) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.domain.PieceOfNews; | ||
4 | import hu.dns.honlap.repository.PieceOfNewsRepository; | ||
5 | import hu.dns.honlap.web.rest.errors.BadRequestAlertException; | ||
6 | |||
7 | import io.github.jhipster.web.util.HeaderUtil; | ||
8 | import io.github.jhipster.web.util.PaginationUtil; | ||
9 | import io.github.jhipster.web.util.ResponseUtil; | ||
10 | import org.slf4j.Logger; | ||
11 | import org.slf4j.LoggerFactory; | ||
12 | import org.springframework.beans.factory.annotation.Value; | ||
13 | import org.springframework.data.domain.Page; | ||
14 | import org.springframework.data.domain.Pageable; | ||
15 | import org.springframework.http.HttpHeaders; | ||
16 | import org.springframework.http.HttpStatus; | ||
17 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
18 | import org.springframework.http.ResponseEntity; | ||
19 | import org.springframework.transaction.annotation.Transactional; | ||
20 | import org.springframework.web.bind.annotation.*; | ||
21 | |||
22 | import javax.validation.Valid; | ||
23 | import java.net.URI; | ||
24 | import java.net.URISyntaxException; | ||
25 | import java.util.List; | ||
26 | import java.util.Optional; | ||
27 | |||
28 | /** | ||
29 | * REST controller for managing {@link hu.dns.honlap.domain.PieceOfNews}. | ||
30 | */ | ||
31 | @RestController | ||
32 | @RequestMapping("/api") | ||
33 | @Transactional | ||
34 | public class PieceOfNewsResource { | ||
35 | |||
36 | private final Logger log = LoggerFactory.getLogger(PieceOfNewsResource.class); | ||
37 | |||
38 | private static final String ENTITY_NAME = "pieceOfNews"; | ||
39 | |||
40 | @Value("${jhipster.clientApp.name}") | ||
41 | private String applicationName; | ||
42 | |||
43 | private final PieceOfNewsRepository pieceOfNewsRepository; | ||
44 | |||
45 | public PieceOfNewsResource(PieceOfNewsRepository pieceOfNewsRepository) { | ||
46 | this.pieceOfNewsRepository = pieceOfNewsRepository; | ||
47 | } | ||
48 | |||
49 | /** | ||
50 | * {@code POST /piece-of-news} : Create a new pieceOfNews. | ||
51 | * | ||
52 | * @param pieceOfNews the pieceOfNews to create. | ||
53 | * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new pieceOfNews, or with status {@code 400 (Bad Request)} if the pieceOfNews has already an ID. | ||
54 | * @throws URISyntaxException if the Location URI syntax is incorrect. | ||
55 | */ | ||
56 | @PostMapping("/piece-of-news") | ||
57 | public ResponseEntity<PieceOfNews> createPieceOfNews(@Valid @RequestBody PieceOfNews pieceOfNews) throws URISyntaxException { | ||
58 | log.debug("REST request to save PieceOfNews : {}", pieceOfNews); | ||
59 | if (pieceOfNews.getId() != null) { | ||
60 | throw new BadRequestAlertException("A new pieceOfNews cannot already have an ID", ENTITY_NAME, "idexists"); | ||
61 | } | ||
62 | PieceOfNews result = pieceOfNewsRepository.save(pieceOfNews); | ||
63 | return ResponseEntity.created(new URI("/api/piece-of-news/" + result.getId())) | ||
64 | .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString())) | ||
65 | .body(result); | ||
66 | } | ||
67 | |||
68 | /** | ||
69 | * {@code PUT /piece-of-news} : Updates an existing pieceOfNews. | ||
70 | * | ||
71 | * @param pieceOfNews the pieceOfNews to update. | ||
72 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated pieceOfNews, | ||
73 | * or with status {@code 400 (Bad Request)} if the pieceOfNews is not valid, | ||
74 | * or with status {@code 500 (Internal Server Error)} if the pieceOfNews couldn't be updated. | ||
75 | * @throws URISyntaxException if the Location URI syntax is incorrect. | ||
76 | */ | ||
77 | @PutMapping("/piece-of-news") | ||
78 | public ResponseEntity<PieceOfNews> updatePieceOfNews(@Valid @RequestBody PieceOfNews pieceOfNews) throws URISyntaxException { | ||
79 | log.debug("REST request to update PieceOfNews : {}", pieceOfNews); | ||
80 | if (pieceOfNews.getId() == null) { | ||
81 | throw new BadRequestAlertException("Invalid id", ENTITY_NAME, "idnull"); | ||
82 | } | ||
83 | PieceOfNews result = pieceOfNewsRepository.save(pieceOfNews); | ||
84 | return ResponseEntity.ok() | ||
85 | .headers(HeaderUtil.createEntityUpdateAlert(applicationName, true, ENTITY_NAME, pieceOfNews.getId().toString())) | ||
86 | .body(result); | ||
87 | } | ||
88 | |||
89 | /** | ||
90 | * {@code GET /piece-of-news} : get all the pieceOfNews. | ||
91 | * | ||
92 | * @param pageable the pagination information. | ||
93 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and the list of pieceOfNews in body. | ||
94 | */ | ||
95 | @GetMapping("/piece-of-news") | ||
96 | public ResponseEntity<List<PieceOfNews>> getAllPieceOfNews(Pageable pageable) { | ||
97 | log.debug("REST request to get a page of PieceOfNews"); | ||
98 | Page<PieceOfNews> page = pieceOfNewsRepository.findAll(pageable); | ||
99 | HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); | ||
100 | return ResponseEntity.ok().headers(headers).body(page.getContent()); | ||
101 | } | ||
102 | |||
103 | /** | ||
104 | * {@code GET /piece-of-news/:id} : get the "id" pieceOfNews. | ||
105 | * | ||
106 | * @param id the id of the pieceOfNews to retrieve. | ||
107 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the pieceOfNews, or with status {@code 404 (Not Found)}. | ||
108 | */ | ||
109 | @GetMapping("/piece-of-news/{id}") | ||
110 | public ResponseEntity<PieceOfNews> getPieceOfNews(@PathVariable Long id) { | ||
111 | log.debug("REST request to get PieceOfNews : {}", id); | ||
112 | Optional<PieceOfNews> pieceOfNews = pieceOfNewsRepository.findById(id); | ||
113 | return ResponseUtil.wrapOrNotFound(pieceOfNews); | ||
114 | } | ||
115 | |||
116 | /** | ||
117 | * {@code DELETE /piece-of-news/:id} : delete the "id" pieceOfNews. | ||
118 | * | ||
119 | * @param id the id of the pieceOfNews to delete. | ||
120 | * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. | ||
121 | */ | ||
122 | @DeleteMapping("/piece-of-news/{id}") | ||
123 | public ResponseEntity<Void> deletePieceOfNews(@PathVariable Long id) { | ||
124 | log.debug("REST request to delete PieceOfNews : {}", id); | ||
125 | pieceOfNewsRepository.deleteById(id); | ||
126 | return ResponseEntity.noContent().headers(HeaderUtil.createEntityDeletionAlert(applicationName, true, ENTITY_NAME, id.toString())).build(); | ||
127 | } | ||
128 | } |
File src/main/java/hu/dns/honlap/web/rest/UserJWTController.java added (mode: 100644) (index 0000000..361d9fa) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.security.jwt.JWTFilter; | ||
4 | import hu.dns.honlap.security.jwt.TokenProvider; | ||
5 | import hu.dns.honlap.web.rest.vm.LoginVM; | ||
6 | |||
7 | import com.fasterxml.jackson.annotation.JsonProperty; | ||
8 | |||
9 | import org.springframework.http.HttpHeaders; | ||
10 | import org.springframework.http.HttpStatus; | ||
11 | import org.springframework.http.ResponseEntity; | ||
12 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
13 | import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; | ||
14 | import org.springframework.security.core.Authentication; | ||
15 | import org.springframework.security.core.context.SecurityContextHolder; | ||
16 | import org.springframework.web.bind.annotation.*; | ||
17 | |||
18 | import javax.validation.Valid; | ||
19 | |||
20 | /** | ||
21 | * Controller to authenticate users. | ||
22 | */ | ||
23 | @RestController | ||
24 | @RequestMapping("/api") | ||
25 | public class UserJWTController { | ||
26 | |||
27 | private final TokenProvider tokenProvider; | ||
28 | |||
29 | private final AuthenticationManagerBuilder authenticationManagerBuilder; | ||
30 | |||
31 | public UserJWTController(TokenProvider tokenProvider, AuthenticationManagerBuilder authenticationManagerBuilder) { | ||
32 | this.tokenProvider = tokenProvider; | ||
33 | this.authenticationManagerBuilder = authenticationManagerBuilder; | ||
34 | } | ||
35 | |||
36 | @PostMapping("/authenticate") | ||
37 | public ResponseEntity<JWTToken> authorize(@Valid @RequestBody LoginVM loginVM) { | ||
38 | |||
39 | UsernamePasswordAuthenticationToken authenticationToken = | ||
40 | new UsernamePasswordAuthenticationToken(loginVM.getUsername(), loginVM.getPassword()); | ||
41 | |||
42 | Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); | ||
43 | SecurityContextHolder.getContext().setAuthentication(authentication); | ||
44 | boolean rememberMe = (loginVM.isRememberMe() == null) ? false : loginVM.isRememberMe(); | ||
45 | String jwt = tokenProvider.createToken(authentication, rememberMe); | ||
46 | HttpHeaders httpHeaders = new HttpHeaders(); | ||
47 | httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); | ||
48 | return new ResponseEntity<>(new JWTToken(jwt), httpHeaders, HttpStatus.OK); | ||
49 | } | ||
50 | /** | ||
51 | * Object to return as body in JWT Authentication. | ||
52 | */ | ||
53 | static class JWTToken { | ||
54 | |||
55 | private String idToken; | ||
56 | |||
57 | JWTToken(String idToken) { | ||
58 | this.idToken = idToken; | ||
59 | } | ||
60 | |||
61 | @JsonProperty("id_token") | ||
62 | String getIdToken() { | ||
63 | return idToken; | ||
64 | } | ||
65 | |||
66 | void setIdToken(String idToken) { | ||
67 | this.idToken = idToken; | ||
68 | } | ||
69 | } | ||
70 | } |
File src/main/java/hu/dns/honlap/web/rest/UserResource.java added (mode: 100644) (index 0000000..187ade8) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.config.Constants; | ||
4 | import hu.dns.honlap.domain.User; | ||
5 | import hu.dns.honlap.repository.UserRepository; | ||
6 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
7 | import hu.dns.honlap.service.MailService; | ||
8 | import hu.dns.honlap.service.UserService; | ||
9 | import hu.dns.honlap.service.dto.UserDTO; | ||
10 | import hu.dns.honlap.web.rest.errors.BadRequestAlertException; | ||
11 | import hu.dns.honlap.web.rest.errors.EmailAlreadyUsedException; | ||
12 | import hu.dns.honlap.web.rest.errors.LoginAlreadyUsedException; | ||
13 | |||
14 | import io.github.jhipster.web.util.HeaderUtil; | ||
15 | import io.github.jhipster.web.util.PaginationUtil; | ||
16 | import io.github.jhipster.web.util.ResponseUtil; | ||
17 | |||
18 | import org.slf4j.Logger; | ||
19 | import org.slf4j.LoggerFactory; | ||
20 | import org.springframework.beans.factory.annotation.Value; | ||
21 | import org.springframework.data.domain.Page; | ||
22 | import org.springframework.data.domain.Pageable; | ||
23 | import org.springframework.http.HttpHeaders; | ||
24 | import org.springframework.http.HttpStatus; | ||
25 | import org.springframework.http.ResponseEntity; | ||
26 | import org.springframework.security.access.prepost.PreAuthorize; | ||
27 | import org.springframework.web.bind.annotation.*; | ||
28 | import org.springframework.web.servlet.support.ServletUriComponentsBuilder; | ||
29 | |||
30 | import javax.validation.Valid; | ||
31 | import java.net.URI; | ||
32 | import java.net.URISyntaxException; | ||
33 | import java.util.*; | ||
34 | |||
35 | /** | ||
36 | * REST controller for managing users. | ||
37 | * <p> | ||
38 | * This class accesses the {@link User} entity, and needs to fetch its collection of authorities. | ||
39 | * <p> | ||
40 | * For a normal use-case, it would be better to have an eager relationship between User and Authority, | ||
41 | * and send everything to the client side: there would be no View Model and DTO, a lot less code, and an outer-join | ||
42 | * which would be good for performance. | ||
43 | * <p> | ||
44 | * We use a View Model and a DTO for 3 reasons: | ||
45 | * <ul> | ||
46 | * <li>We want to keep a lazy association between the user and the authorities, because people will | ||
47 | * quite often do relationships with the user, and we don't want them to get the authorities all | ||
48 | * the time for nothing (for performance reasons). This is the #1 goal: we should not impact our users' | ||
49 | * application because of this use-case.</li> | ||
50 | * <li> Not having an outer join causes n+1 requests to the database. This is not a real issue as | ||
51 | * we have by default a second-level cache. This means on the first HTTP call we do the n+1 requests, | ||
52 | * but then all authorities come from the cache, so in fact it's much better than doing an outer join | ||
53 | * (which will get lots of data from the database, for each HTTP call).</li> | ||
54 | * <li> As this manages users, for security reasons, we'd rather have a DTO layer.</li> | ||
55 | * </ul> | ||
56 | * <p> | ||
57 | * Another option would be to have a specific JPA entity graph to handle this case. | ||
58 | */ | ||
59 | @RestController | ||
60 | @RequestMapping("/api") | ||
61 | public class UserResource { | ||
62 | |||
63 | private final Logger log = LoggerFactory.getLogger(UserResource.class); | ||
64 | |||
65 | @Value("${jhipster.clientApp.name}") | ||
66 | private String applicationName; | ||
67 | |||
68 | private final UserService userService; | ||
69 | |||
70 | private final UserRepository userRepository; | ||
71 | |||
72 | private final MailService mailService; | ||
73 | |||
74 | public UserResource(UserService userService, UserRepository userRepository, MailService mailService) { | ||
75 | this.userService = userService; | ||
76 | this.userRepository = userRepository; | ||
77 | this.mailService = mailService; | ||
78 | } | ||
79 | |||
80 | /** | ||
81 | * {@code POST /users} : Creates a new user. | ||
82 | * <p> | ||
83 | * Creates a new user if the login and email are not already used, and sends an | ||
84 | * mail with an activation link. | ||
85 | * The user needs to be activated on creation. | ||
86 | * | ||
87 | * @param userDTO the user to create. | ||
88 | * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new user, or with status {@code 400 (Bad Request)} if the login or email is already in use. | ||
89 | * @throws URISyntaxException if the Location URI syntax is incorrect. | ||
90 | * @throws BadRequestAlertException {@code 400 (Bad Request)} if the login or email is already in use. | ||
91 | */ | ||
92 | @PostMapping("/users") | ||
93 | @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") | ||
94 | public ResponseEntity<User> createUser(@Valid @RequestBody UserDTO userDTO) throws URISyntaxException { | ||
95 | log.debug("REST request to save User : {}", userDTO); | ||
96 | |||
97 | if (userDTO.getId() != null) { | ||
98 | throw new BadRequestAlertException("A new user cannot already have an ID", "userManagement", "idexists"); | ||
99 | // Lowercase the user login before comparing with database | ||
100 | } else if (userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()).isPresent()) { | ||
101 | throw new LoginAlreadyUsedException(); | ||
102 | } else if (userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()).isPresent()) { | ||
103 | throw new EmailAlreadyUsedException(); | ||
104 | } else { | ||
105 | User newUser = userService.createUser(userDTO); | ||
106 | mailService.sendCreationEmail(newUser); | ||
107 | return ResponseEntity.created(new URI("/api/users/" + newUser.getLogin())) | ||
108 | .headers(HeaderUtil.createAlert(applicationName, "userManagement.created", newUser.getLogin())) | ||
109 | .body(newUser); | ||
110 | } | ||
111 | } | ||
112 | |||
113 | /** | ||
114 | * {@code PUT /users} : Updates an existing User. | ||
115 | * | ||
116 | * @param userDTO the user to update. | ||
117 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the updated user. | ||
118 | * @throws EmailAlreadyUsedException {@code 400 (Bad Request)} if the email is already in use. | ||
119 | * @throws LoginAlreadyUsedException {@code 400 (Bad Request)} if the login is already in use. | ||
120 | */ | ||
121 | @PutMapping("/users") | ||
122 | @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") | ||
123 | public ResponseEntity<UserDTO> updateUser(@Valid @RequestBody UserDTO userDTO) { | ||
124 | log.debug("REST request to update User : {}", userDTO); | ||
125 | Optional<User> existingUser = userRepository.findOneByEmailIgnoreCase(userDTO.getEmail()); | ||
126 | if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { | ||
127 | throw new EmailAlreadyUsedException(); | ||
128 | } | ||
129 | existingUser = userRepository.findOneByLogin(userDTO.getLogin().toLowerCase()); | ||
130 | if (existingUser.isPresent() && (!existingUser.get().getId().equals(userDTO.getId()))) { | ||
131 | throw new LoginAlreadyUsedException(); | ||
132 | } | ||
133 | Optional<UserDTO> updatedUser = userService.updateUser(userDTO); | ||
134 | |||
135 | return ResponseUtil.wrapOrNotFound(updatedUser, | ||
136 | HeaderUtil.createAlert(applicationName, "userManagement.updated", userDTO.getLogin())); | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * {@code GET /users} : get all users. | ||
141 | * | ||
142 | * @param pageable the pagination information. | ||
143 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body all users. | ||
144 | */ | ||
145 | @GetMapping("/users") | ||
146 | public ResponseEntity<List<UserDTO>> getAllUsers(Pageable pageable) { | ||
147 | final Page<UserDTO> page = userService.getAllManagedUsers(pageable); | ||
148 | HttpHeaders headers = PaginationUtil.generatePaginationHttpHeaders(ServletUriComponentsBuilder.fromCurrentRequest(), page); | ||
149 | return new ResponseEntity<>(page.getContent(), headers, HttpStatus.OK); | ||
150 | } | ||
151 | |||
152 | /** | ||
153 | * Gets a list of all roles. | ||
154 | * @return a string list of all roles. | ||
155 | */ | ||
156 | @GetMapping("/users/authorities") | ||
157 | @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") | ||
158 | public List<String> getAuthorities() { | ||
159 | return userService.getAuthorities(); | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * {@code GET /users/:login} : get the "login" user. | ||
164 | * | ||
165 | * @param login the login of the user to find. | ||
166 | * @return the {@link ResponseEntity} with status {@code 200 (OK)} and with body the "login" user, or with status {@code 404 (Not Found)}. | ||
167 | */ | ||
168 | @GetMapping("/users/{login:" + Constants.LOGIN_REGEX + "}") | ||
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 | * {@code DELETE /users/:login} : delete the "login" User. | ||
178 | * | ||
179 | * @param login the login of the user to delete. | ||
180 | * @return the {@link ResponseEntity} with status {@code 204 (NO_CONTENT)}. | ||
181 | */ | ||
182 | @DeleteMapping("/users/{login:" + Constants.LOGIN_REGEX + "}") | ||
183 | @PreAuthorize("hasAuthority(\"" + AuthoritiesConstants.ADMIN + "\")") | ||
184 | public ResponseEntity<Void> deleteUser(@PathVariable String login) { | ||
185 | log.debug("REST request to delete User: {}", login); | ||
186 | userService.deleteUser(login); | ||
187 | return ResponseEntity.noContent().headers(HeaderUtil.createAlert(applicationName, "userManagement.deleted", login)).build(); | ||
188 | } | ||
189 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/BadRequestAlertException.java added (mode: 100644) (index 0000000..d7a8c1d) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/EmailAlreadyUsedException.java added (mode: 100644) (index 0000000..5666455) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/ErrorConstants.java added (mode: 100644) (index 0000000..c898510) | |||
1 | package hu.dns.honlap.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 INVALID_PASSWORD_TYPE = URI.create(PROBLEM_BASE_URL + "/invalid-password"); | ||
13 | public static final URI EMAIL_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/email-already-used"); | ||
14 | public static final URI LOGIN_ALREADY_USED_TYPE = URI.create(PROBLEM_BASE_URL + "/login-already-used"); | ||
15 | |||
16 | private ErrorConstants() { | ||
17 | } | ||
18 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/ExceptionTranslator.java added (mode: 100644) (index 0000000..f325df3) | |||
1 | package hu.dns.honlap.web.rest.errors; | ||
2 | |||
3 | import io.github.jhipster.web.util.HeaderUtil; | ||
4 | |||
5 | import org.springframework.beans.factory.annotation.Value; | ||
6 | import org.springframework.dao.ConcurrencyFailureException; | ||
7 | import org.springframework.http.ResponseEntity; | ||
8 | import org.springframework.validation.BindingResult; | ||
9 | import org.springframework.web.bind.MethodArgumentNotValidException; | ||
10 | import org.springframework.web.bind.annotation.ControllerAdvice; | ||
11 | import org.springframework.web.bind.annotation.ExceptionHandler; | ||
12 | import org.springframework.web.context.request.NativeWebRequest; | ||
13 | import org.zalando.problem.DefaultProblem; | ||
14 | import org.zalando.problem.Problem; | ||
15 | import org.zalando.problem.ProblemBuilder; | ||
16 | import org.zalando.problem.Status; | ||
17 | import org.zalando.problem.spring.web.advice.ProblemHandling; | ||
18 | import org.zalando.problem.spring.web.advice.security.SecurityAdviceTrait; | ||
19 | import org.zalando.problem.violations.ConstraintViolationProblem; | ||
20 | |||
21 | import javax.annotation.Nonnull; | ||
22 | import javax.annotation.Nullable; | ||
23 | import javax.servlet.http.HttpServletRequest; | ||
24 | import java.util.List; | ||
25 | import java.util.stream.Collectors; | ||
26 | |||
27 | /** | ||
28 | * Controller advice to translate the server side exceptions to client-friendly json structures. | ||
29 | * The error response follows RFC7807 - Problem Details for HTTP APIs (https://tools.ietf.org/html/rfc7807). | ||
30 | */ | ||
31 | @ControllerAdvice | ||
32 | public class ExceptionTranslator implements ProblemHandling, SecurityAdviceTrait { | ||
33 | |||
34 | private static final String FIELD_ERRORS_KEY = "fieldErrors"; | ||
35 | private static final String MESSAGE_KEY = "message"; | ||
36 | private static final String PATH_KEY = "path"; | ||
37 | private static final String VIOLATIONS_KEY = "violations"; | ||
38 | |||
39 | @Value("${jhipster.clientApp.name}") | ||
40 | private String applicationName; | ||
41 | |||
42 | /** | ||
43 | * Post-process the Problem payload to add the message key for the front-end if needed. | ||
44 | */ | ||
45 | @Override | ||
46 | public ResponseEntity<Problem> process(@Nullable ResponseEntity<Problem> entity, NativeWebRequest request) { | ||
47 | if (entity == null) { | ||
48 | return entity; | ||
49 | } | ||
50 | Problem problem = entity.getBody(); | ||
51 | if (!(problem instanceof ConstraintViolationProblem || problem instanceof DefaultProblem)) { | ||
52 | return entity; | ||
53 | } | ||
54 | ProblemBuilder builder = Problem.builder() | ||
55 | .withType(Problem.DEFAULT_TYPE.equals(problem.getType()) ? ErrorConstants.DEFAULT_TYPE : problem.getType()) | ||
56 | .withStatus(problem.getStatus()) | ||
57 | .withTitle(problem.getTitle()) | ||
58 | .with(PATH_KEY, request.getNativeRequest(HttpServletRequest.class).getRequestURI()); | ||
59 | |||
60 | if (problem instanceof ConstraintViolationProblem) { | ||
61 | builder | ||
62 | .with(VIOLATIONS_KEY, ((ConstraintViolationProblem) problem).getViolations()) | ||
63 | .with(MESSAGE_KEY, ErrorConstants.ERR_VALIDATION); | ||
64 | } else { | ||
65 | builder | ||
66 | .withCause(((DefaultProblem) problem).getCause()) | ||
67 | .withDetail(problem.getDetail()) | ||
68 | .withInstance(problem.getInstance()); | ||
69 | problem.getParameters().forEach(builder::with); | ||
70 | if (!problem.getParameters().containsKey(MESSAGE_KEY) && problem.getStatus() != null) { | ||
71 | builder.with(MESSAGE_KEY, "error.http." + problem.getStatus().getStatusCode()); | ||
72 | } | ||
73 | } | ||
74 | return new ResponseEntity<>(builder.build(), entity.getHeaders(), entity.getStatusCode()); | ||
75 | } | ||
76 | |||
77 | @Override | ||
78 | public ResponseEntity<Problem> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, @Nonnull NativeWebRequest request) { | ||
79 | BindingResult result = ex.getBindingResult(); | ||
80 | List<FieldErrorVM> fieldErrors = result.getFieldErrors().stream() | ||
81 | .map(f -> new FieldErrorVM(f.getObjectName().replaceFirst("DTO$", ""), f.getField(), f.getCode())) | ||
82 | .collect(Collectors.toList()); | ||
83 | |||
84 | Problem problem = Problem.builder() | ||
85 | .withType(ErrorConstants.CONSTRAINT_VIOLATION_TYPE) | ||
86 | .withTitle("Method argument not valid") | ||
87 | .withStatus(defaultConstraintViolationStatus()) | ||
88 | .with(MESSAGE_KEY, ErrorConstants.ERR_VALIDATION) | ||
89 | .with(FIELD_ERRORS_KEY, fieldErrors) | ||
90 | .build(); | ||
91 | return create(ex, problem, request); | ||
92 | } | ||
93 | |||
94 | @ExceptionHandler | ||
95 | public ResponseEntity<Problem> handleEmailAlreadyUsedException(hu.dns.honlap.service.EmailAlreadyUsedException ex, NativeWebRequest request) { | ||
96 | EmailAlreadyUsedException problem = new EmailAlreadyUsedException(); | ||
97 | return create(problem, request, HeaderUtil.createFailureAlert(applicationName, true, problem.getEntityName(), problem.getErrorKey(), problem.getMessage())); | ||
98 | } | ||
99 | |||
100 | @ExceptionHandler | ||
101 | public ResponseEntity<Problem> handleUsernameAlreadyUsedException(hu.dns.honlap.service.UsernameAlreadyUsedException ex, NativeWebRequest request) { | ||
102 | LoginAlreadyUsedException problem = new LoginAlreadyUsedException(); | ||
103 | return create(problem, request, HeaderUtil.createFailureAlert(applicationName, true, problem.getEntityName(), problem.getErrorKey(), problem.getMessage())); | ||
104 | } | ||
105 | |||
106 | @ExceptionHandler | ||
107 | public ResponseEntity<Problem> handleInvalidPasswordException(hu.dns.honlap.service.InvalidPasswordException ex, NativeWebRequest request) { | ||
108 | return create(new InvalidPasswordException(), request); | ||
109 | } | ||
110 | |||
111 | @ExceptionHandler | ||
112 | public ResponseEntity<Problem> handleBadRequestAlertException(BadRequestAlertException ex, NativeWebRequest request) { | ||
113 | return create(ex, request, HeaderUtil.createFailureAlert(applicationName, true, ex.getEntityName(), ex.getErrorKey(), ex.getMessage())); | ||
114 | } | ||
115 | |||
116 | @ExceptionHandler | ||
117 | public ResponseEntity<Problem> handleConcurrencyFailure(ConcurrencyFailureException ex, NativeWebRequest request) { | ||
118 | Problem problem = Problem.builder() | ||
119 | .withStatus(Status.CONFLICT) | ||
120 | .with(MESSAGE_KEY, ErrorConstants.ERR_CONCURRENCY_FAILURE) | ||
121 | .build(); | ||
122 | return create(ex, problem, request); | ||
123 | } | ||
124 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/FieldErrorVM.java added (mode: 100644) (index 0000000..925a45a) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/InvalidPasswordException.java added (mode: 100644) (index 0000000..520dc59) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/LoginAlreadyUsedException.java added (mode: 100644) (index 0000000..ff8f353) | |||
1 | package hu.dns.honlap.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 | } |
File src/main/java/hu/dns/honlap/web/rest/errors/package-info.java added (mode: 100644) (index 0000000..298e99b) | |||
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 hu.dns.honlap.web.rest.errors; |
File src/main/java/hu/dns/honlap/web/rest/package-info.java added (mode: 100644) (index 0000000..4f49cf8) | |||
1 | /** | ||
2 | * Spring MVC REST controllers. | ||
3 | */ | ||
4 | package hu.dns.honlap.web.rest; |
File src/main/java/hu/dns/honlap/web/rest/vm/KeyAndPasswordVM.java added (mode: 100644) (index 0000000..4566146) | |||
1 | package hu.dns.honlap.web.rest.vm; | ||
2 | |||
3 | /** | ||
4 | * View Model object for storing the user's key and password. | ||
5 | */ | ||
6 | public class KeyAndPasswordVM { | ||
7 | |||
8 | private String key; | ||
9 | |||
10 | private String newPassword; | ||
11 | |||
12 | public String getKey() { | ||
13 | return key; | ||
14 | } | ||
15 | |||
16 | public void setKey(String key) { | ||
17 | this.key = key; | ||
18 | } | ||
19 | |||
20 | public String getNewPassword() { | ||
21 | return newPassword; | ||
22 | } | ||
23 | |||
24 | public void setNewPassword(String newPassword) { | ||
25 | this.newPassword = newPassword; | ||
26 | } | ||
27 | } |
File src/main/java/hu/dns/honlap/web/rest/vm/LoginVM.java added (mode: 100644) (index 0000000..403b1f7) | |||
1 | package hu.dns.honlap.web.rest.vm; | ||
2 | |||
3 | import javax.validation.constraints.NotNull; | ||
4 | import javax.validation.constraints.Size; | ||
5 | |||
6 | /** | ||
7 | * View Model object for storing a user's credentials. | ||
8 | */ | ||
9 | public class LoginVM { | ||
10 | |||
11 | @NotNull | ||
12 | @Size(min = 1, max = 50) | ||
13 | private String username; | ||
14 | |||
15 | @NotNull | ||
16 | @Size(min = 4, max = 100) | ||
17 | private String password; | ||
18 | |||
19 | private Boolean rememberMe; | ||
20 | |||
21 | public String getUsername() { | ||
22 | return username; | ||
23 | } | ||
24 | |||
25 | public void setUsername(String username) { | ||
26 | this.username = username; | ||
27 | } | ||
28 | |||
29 | public String getPassword() { | ||
30 | return password; | ||
31 | } | ||
32 | |||
33 | public void setPassword(String password) { | ||
34 | this.password = password; | ||
35 | } | ||
36 | |||
37 | public Boolean isRememberMe() { | ||
38 | return rememberMe; | ||
39 | } | ||
40 | |||
41 | public void setRememberMe(Boolean rememberMe) { | ||
42 | this.rememberMe = rememberMe; | ||
43 | } | ||
44 | |||
45 | @Override | ||
46 | public String toString() { | ||
47 | return "LoginVM{" + | ||
48 | "username='" + username + '\'' + | ||
49 | ", rememberMe=" + rememberMe + | ||
50 | '}'; | ||
51 | } | ||
52 | } |
File src/main/java/hu/dns/honlap/web/rest/vm/ManagedUserVM.java added (mode: 100644) (index 0000000..b9b749b) | |||
1 | package hu.dns.honlap.web.rest.vm; | ||
2 | |||
3 | import hu.dns.honlap.service.dto.UserDTO; | ||
4 | import javax.validation.constraints.Size; | ||
5 | |||
6 | /** | ||
7 | * View Model extending the UserDTO, which is meant to be used in the user management UI. | ||
8 | */ | ||
9 | public class ManagedUserVM extends UserDTO { | ||
10 | |||
11 | public static final int PASSWORD_MIN_LENGTH = 4; | ||
12 | |||
13 | public static final int PASSWORD_MAX_LENGTH = 100; | ||
14 | |||
15 | @Size(min = PASSWORD_MIN_LENGTH, max = PASSWORD_MAX_LENGTH) | ||
16 | private String password; | ||
17 | |||
18 | public ManagedUserVM() { | ||
19 | // Empty constructor needed for Jackson. | ||
20 | } | ||
21 | |||
22 | public String getPassword() { | ||
23 | return password; | ||
24 | } | ||
25 | |||
26 | public void setPassword(String password) { | ||
27 | this.password = password; | ||
28 | } | ||
29 | |||
30 | @Override | ||
31 | public String toString() { | ||
32 | return "ManagedUserVM{" + super.toString() + "} "; | ||
33 | } | ||
34 | } |
File src/main/java/hu/dns/honlap/web/rest/vm/package-info.java added (mode: 100644) (index 0000000..82fb467) | |||
1 | /** | ||
2 | * View Models used by Spring MVC REST controllers. | ||
3 | */ | ||
4 | package hu.dns.honlap.web.rest.vm; |
File src/main/jib/entrypoint.sh added (mode: 100644) (index 0000000..7abae6c) | |||
1 | #!/bin/sh | ||
2 | |||
3 | echo "The application will start in ${JHIPSTER_SLEEP}s..." && sleep ${JHIPSTER_SLEEP} | ||
4 | exec java ${JAVA_OPTS} -noverify -XX:+AlwaysPreTouch -Djava.security.egd=file:/dev/./urandom -cp /app/resources/:/app/classes/:/app/libs/* "hu.dns.honlap.HonlapApp" "$@" |
File src/main/resources/.h2.server.properties added (mode: 100644) (index 0000000..8c3cf33) | |||
1 | #H2 Server Properties | ||
2 | 0=JHipster H2 (Disk)|org.h2.Driver|jdbc\:h2\:file\:./target/h2db/db/honlap|honlap | ||
3 | webAllowOthers=true | ||
4 | webPort=8082 | ||
5 | webSSL=false |
File src/main/resources/banner.txt added (mode: 100644) (index 0000000..e0bc55a) | |||
1 | |||
2 | ${AnsiColor.GREEN} ██╗${AnsiColor.RED} ██╗ ██╗ ████████╗ ███████╗ ██████╗ ████████╗ ████████╗ ███████╗ | ||
3 | ${AnsiColor.GREEN} ██║${AnsiColor.RED} ██║ ██║ ╚══██╔══╝ ██╔═══██╗ ██╔════╝ ╚══██╔══╝ ██╔═════╝ ██╔═══██╗ | ||
4 | ${AnsiColor.GREEN} ██║${AnsiColor.RED} ████████║ ██║ ███████╔╝ ╚█████╗ ██║ ██████╗ ███████╔╝ | ||
5 | ${AnsiColor.GREEN}██╗ ██║${AnsiColor.RED} ██╔═══██║ ██║ ██╔════╝ ╚═══██╗ ██║ ██╔═══╝ ██╔══██║ | ||
6 | ${AnsiColor.GREEN}╚██████╔╝${AnsiColor.RED} ██║ ██║ ████████╗ ██║ ██████╔╝ ██║ ████████╗ ██║ ╚██╗ | ||
7 | ${AnsiColor.GREEN} ╚═════╝ ${AnsiColor.RED} ╚═╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═════╝ ╚═╝ ╚═══════╝ ╚═╝ ╚═╝ | ||
8 | |||
9 | ${AnsiColor.BRIGHT_BLUE}:: JHipster 🤓 :: Running Spring Boot ${spring-boot.version} :: | ||
10 | :: https://www.jhipster.tech ::${AnsiColor.DEFAULT} |
File src/main/resources/config/application-dev.yml added (mode: 100644) (index 0000000..07b2f5d) | |||
1 | # =================================================================== | ||
2 | # Spring Boot configuration for the "dev" profile. | ||
3 | # | ||
4 | # This configuration overrides the application.yml file. | ||
5 | # | ||
6 | # More information on profiles: https://www.jhipster.tech/profiles/ | ||
7 | # More information on configuration properties: https://www.jhipster.tech/common-application-properties/ | ||
8 | # =================================================================== | ||
9 | |||
10 | # =================================================================== | ||
11 | # Standard Spring Boot properties. | ||
12 | # Full reference is available at: | ||
13 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html | ||
14 | # =================================================================== | ||
15 | |||
16 | logging: | ||
17 | level: | ||
18 | ROOT: DEBUG | ||
19 | io.github.jhipster: DEBUG | ||
20 | hu.dns.honlap: DEBUG | ||
21 | |||
22 | spring: | ||
23 | profiles: | ||
24 | active: dev | ||
25 | include: | ||
26 | - swagger | ||
27 | # Uncomment to activate TLS for the dev profile | ||
28 | #- tls | ||
29 | devtools: | ||
30 | restart: | ||
31 | enabled: true | ||
32 | additional-exclude: static/**,.h2.server.properties | ||
33 | livereload: | ||
34 | enabled: false # we use Webpack dev server + BrowserSync for livereload | ||
35 | jackson: | ||
36 | serialization: | ||
37 | indent-output: true | ||
38 | datasource: | ||
39 | type: com.zaxxer.hikari.HikariDataSource | ||
40 | url: jdbc:h2:file:./target/h2db/db/honlap;DB_CLOSE_DELAY=-1 | ||
41 | username: honlap | ||
42 | password: | ||
43 | hikari: | ||
44 | poolName: Hikari | ||
45 | auto-commit: false | ||
46 | h2: | ||
47 | console: | ||
48 | enabled: false | ||
49 | jpa: | ||
50 | show-sql: true | ||
51 | properties: | ||
52 | hibernate.id.new_generator_mappings: true | ||
53 | hibernate.connection.provider_disables_autocommit: true | ||
54 | hibernate.cache.use_second_level_cache: true | ||
55 | hibernate.cache.use_query_cache: false | ||
56 | hibernate.generate_statistics: false | ||
57 | liquibase: | ||
58 | # Remove 'faker' if you do not want the sample data to be loaded automatically | ||
59 | contexts: dev, faker | ||
60 | mail: | ||
61 | host: localhost | ||
62 | port: 25 | ||
63 | username: | ||
64 | password: | ||
65 | messages: | ||
66 | cache-duration: PT1S # 1 second, see the ISO 8601 standard | ||
67 | thymeleaf: | ||
68 | cache: false | ||
69 | |||
70 | server: | ||
71 | port: 8080 | ||
72 | |||
73 | # =================================================================== | ||
74 | # JHipster specific properties | ||
75 | # | ||
76 | # Full reference is available at: https://www.jhipster.tech/common-application-properties/ | ||
77 | # =================================================================== | ||
78 | |||
79 | jhipster: | ||
80 | cache: # Cache configuration | ||
81 | ehcache: # Ehcache configuration | ||
82 | time-to-live-seconds: 3600 # By default objects stay 1 hour in the cache | ||
83 | max-entries: 100 # Number of objects in each cache entry | ||
84 | # CORS is only enabled by default with the "dev" profile, so BrowserSync can access the API | ||
85 | cors: | ||
86 | allowed-origins: '*' | ||
87 | allowed-methods: '*' | ||
88 | allowed-headers: '*' | ||
89 | exposed-headers: 'Authorization,Link,X-Total-Count' | ||
90 | allow-credentials: true | ||
91 | max-age: 1800 | ||
92 | security: | ||
93 | authentication: | ||
94 | jwt: | ||
95 | # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) | ||
96 | base64-secret: ZmYxOTYwOGZiYTY1OTJiMTQ3MDNhNGJiNTM3ZWMxN2U1ZTVjODdlMDhmZmNkMGRhYTQxY2ZiMGQzM2Q0ZTNmYzc2YjNjMzU5ZmVkZDgzZDc3OTYxZDMzNzdiNzc3MmVkYjA0NDFkOGIxMTI0MjRiNTMzYzRkNzFkMTJiYWE4Y2Y= | ||
97 | # Token is valid 24 hours | ||
98 | token-validity-in-seconds: 86400 | ||
99 | token-validity-in-seconds-for-remember-me: 2592000 | ||
100 | mail: # specific JHipster mail property, for standard properties see MailProperties | ||
101 | base-url: http://127.0.0.1:8080 | ||
102 | metrics: | ||
103 | logs: # Reports metrics in the logs | ||
104 | enabled: false | ||
105 | report-frequency: 60 # in seconds | ||
106 | logging: | ||
107 | use-json-format: false # By default, logs are not in Json format | ||
108 | logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration | ||
109 | enabled: false | ||
110 | host: localhost | ||
111 | port: 5000 | ||
112 | queue-size: 512 | ||
113 | audit-events: | ||
114 | retention-period: 30 # Number of days before audit events are deleted. | ||
115 | |||
116 | # =================================================================== | ||
117 | # Application specific properties | ||
118 | # Add your own application properties here, see the ApplicationProperties class | ||
119 | # to have type-safe configuration, like in the JHipsterProperties above | ||
120 | # | ||
121 | # More documentation is available at: | ||
122 | # https://www.jhipster.tech/common-application-properties/ | ||
123 | # =================================================================== | ||
124 | |||
125 | # application: |
File src/main/resources/config/application-prod.yml added (mode: 100644) (index 0000000..fcc6e08) | |||
1 | # =================================================================== | ||
2 | # Spring Boot configuration for the "prod" profile. | ||
3 | # | ||
4 | # This configuration overrides the application.yml file. | ||
5 | # | ||
6 | # More information on profiles: https://www.jhipster.tech/profiles/ | ||
7 | # More information on configuration properties: https://www.jhipster.tech/common-application-properties/ | ||
8 | # =================================================================== | ||
9 | |||
10 | # =================================================================== | ||
11 | # Standard Spring Boot properties. | ||
12 | # Full reference is available at: | ||
13 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html | ||
14 | # =================================================================== | ||
15 | |||
16 | logging: | ||
17 | level: | ||
18 | ROOT: INFO | ||
19 | io.github.jhipster: INFO | ||
20 | hu.dns.honlap: INFO | ||
21 | |||
22 | management: | ||
23 | metrics: | ||
24 | export: | ||
25 | prometheus: | ||
26 | enabled: false | ||
27 | |||
28 | spring: | ||
29 | devtools: | ||
30 | restart: | ||
31 | enabled: false | ||
32 | livereload: | ||
33 | enabled: false | ||
34 | datasource: | ||
35 | type: com.zaxxer.hikari.HikariDataSource | ||
36 | url: jdbc:postgresql://localhost:5432/honlap | ||
37 | username: honlap | ||
38 | password: | ||
39 | hikari: | ||
40 | poolName: Hikari | ||
41 | auto-commit: false | ||
42 | jpa: | ||
43 | database-platform: io.github.jhipster.domain.util.FixedPostgreSQL10Dialect | ||
44 | show-sql: false | ||
45 | # Replace by 'prod, faker' to add the faker context and have sample data loaded in production | ||
46 | liquibase: | ||
47 | contexts: prod | ||
48 | mail: | ||
49 | host: localhost | ||
50 | port: 25 | ||
51 | username: | ||
52 | password: | ||
53 | thymeleaf: | ||
54 | cache: true | ||
55 | |||
56 | # =================================================================== | ||
57 | # To enable TLS in production, generate a certificate using: | ||
58 | # keytool -genkey -alias honlap -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore keystore.p12 -validity 3650 | ||
59 | # | ||
60 | # You can also use Let's Encrypt: | ||
61 | # https://maximilian-boehm.com/hp2121/Create-a-Java-Keystore-JKS-from-Let-s-Encrypt-Certificates.htm | ||
62 | # | ||
63 | # Then, modify the server.ssl properties so your "server" configuration looks like: | ||
64 | # | ||
65 | # server: | ||
66 | # port: 443 | ||
67 | # ssl: | ||
68 | # key-store: classpath:config/tls/keystore.p12 | ||
69 | # key-store-password: password | ||
70 | # key-store-type: PKCS12 | ||
71 | # key-alias: honlap | ||
72 | # # The ciphers suite enforce the security by deactivating some old and deprecated SSL cipher, this list was tested against SSL Labs (https://www.ssllabs.com/ssltest/) | ||
73 | # ciphers: TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 ,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 ,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_DHE_RSA_WITH_AES_128_CBC_SHA256,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA256,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_RSA_WITH_CAMELLIA_256_CBC_SHA,TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA,TLS_RSA_WITH_CAMELLIA_128_CBC_SHA | ||
74 | # =================================================================== | ||
75 | server: | ||
76 | port: 8080 | ||
77 | compression: | ||
78 | enabled: true | ||
79 | mime-types: text/html,text/xml,text/plain,text/css, application/javascript, application/json | ||
80 | min-response-size: 1024 | ||
81 | |||
82 | # =================================================================== | ||
83 | # JHipster specific properties | ||
84 | # | ||
85 | # Full reference is available at: https://www.jhipster.tech/common-application-properties/ | ||
86 | # =================================================================== | ||
87 | |||
88 | jhipster: | ||
89 | http: | ||
90 | cache: # Used by the CachingHttpHeadersFilter | ||
91 | timeToLiveInDays: 1461 | ||
92 | cache: # Cache configuration | ||
93 | ehcache: # Ehcache configuration | ||
94 | time-to-live-seconds: 3600 # By default objects stay 1 hour in the cache | ||
95 | max-entries: 1000 # Number of objects in each cache entry | ||
96 | security: | ||
97 | authentication: | ||
98 | jwt: | ||
99 | # This token must be encoded using Base64 and be at least 256 bits long (you can type `openssl rand -base64 64` on your command line to generate a 512 bits one) | ||
100 | # As this is the PRODUCTION configuration, you MUST change the default key, and store it securely: | ||
101 | # - In the JHipster Registry (which includes a Spring Cloud Config server) | ||
102 | # - In a separate `application-prod.yml` file, in the same folder as your executable JAR file | ||
103 | # - In the `JHIPSTER_SECURITY_AUTHENTICATION_JWT_BASE64_SECRET` environment variable | ||
104 | base64-secret: ZmYxOTYwOGZiYTY1OTJiMTQ3MDNhNGJiNTM3ZWMxN2U1ZTVjODdlMDhmZmNkMGRhYTQxY2ZiMGQzM2Q0ZTNmYzc2YjNjMzU5ZmVkZDgzZDc3OTYxZDMzNzdiNzc3MmVkYjA0NDFkOGIxMTI0MjRiNTMzYzRkNzFkMTJiYWE4Y2Y= | ||
105 | # Token is valid 24 hours | ||
106 | token-validity-in-seconds: 86400 | ||
107 | token-validity-in-seconds-for-remember-me: 2592000 | ||
108 | mail: # specific JHipster mail property, for standard properties see MailProperties | ||
109 | base-url: http://my-server-url-to-change # Modify according to your server's URL | ||
110 | metrics: | ||
111 | logs: # Reports metrics in the logs | ||
112 | enabled: false | ||
113 | report-frequency: 60 # in seconds | ||
114 | logging: | ||
115 | use-json-format: false # By default, logs are not in Json format | ||
116 | logstash: # Forward logs to logstash over a socket, used by LoggingConfiguration | ||
117 | enabled: false | ||
118 | host: localhost | ||
119 | port: 5000 | ||
120 | queue-size: 512 | ||
121 | audit-events: | ||
122 | retention-period: 30 # Number of days before audit events are deleted. | ||
123 | |||
124 | # =================================================================== | ||
125 | # Application specific properties | ||
126 | # Add your own application properties here, see the ApplicationProperties class | ||
127 | # to have type-safe configuration, like in the JHipsterProperties above | ||
128 | # | ||
129 | # More documentation is available at: | ||
130 | # https://www.jhipster.tech/common-application-properties/ | ||
131 | # =================================================================== | ||
132 | |||
133 | # application: |
File src/main/resources/config/application-tls.yml added (mode: 100644) (index 0000000..27c9cd8) | |||
1 | # =================================================================== | ||
2 | # Activate this profile to enable TLS and HTTP/2. | ||
3 | # | ||
4 | # JHipster has generated a self-signed certificate, which will be used to encrypt traffic. | ||
5 | # As your browser will not understand this certificate, you will need to import it. | ||
6 | # | ||
7 | # Another (easiest) solution with Chrome is to enable the "allow-insecure-localhost" flag | ||
8 | # at chrome://flags/#allow-insecure-localhost | ||
9 | # =================================================================== | ||
10 | server: | ||
11 | ssl: | ||
12 | key-store: classpath:config/tls/keystore.p12 | ||
13 | key-store-password: password | ||
14 | key-store-type: PKCS12 | ||
15 | key-alias: selfsigned | ||
16 | ciphers: TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384, TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256, TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA, TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384, TLS_DHE_RSA_WITH_AES_128_GCM_SHA256, TLS_DHE_RSA_WITH_AES_256_GCM_SHA384, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA256, TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 | ||
17 | enabled-protocols: TLSv1.2 | ||
18 | http2: | ||
19 | enabled: true |
File src/main/resources/config/application.yml added (mode: 100644) (index 0000000..a701c0e) | |||
1 | # =================================================================== | ||
2 | # Spring Boot configuration. | ||
3 | # | ||
4 | # This configuration will be overridden by the Spring profile you use, | ||
5 | # for example application-dev.yml if you use the "dev" profile. | ||
6 | # | ||
7 | # More information on profiles: https://www.jhipster.tech/profiles/ | ||
8 | # More information on configuration properties: https://www.jhipster.tech/common-application-properties/ | ||
9 | # =================================================================== | ||
10 | |||
11 | # =================================================================== | ||
12 | # Standard Spring Boot properties. | ||
13 | # Full reference is available at: | ||
14 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html | ||
15 | # =================================================================== | ||
16 | |||
17 | management: | ||
18 | endpoints: | ||
19 | web: | ||
20 | base-path: /management | ||
21 | exposure: | ||
22 | include: ['configprops', 'env', 'health', 'info', 'jhimetrics', 'logfile', 'loggers', 'prometheus', 'threaddump'] | ||
23 | endpoint: | ||
24 | health: | ||
25 | show-details: when_authorized | ||
26 | roles: 'ROLE_ADMIN' | ||
27 | jhimetrics: | ||
28 | enabled: true | ||
29 | info: | ||
30 | git: | ||
31 | mode: full | ||
32 | health: | ||
33 | mail: | ||
34 | enabled: false # When using the MailService, configure an SMTP server and set this to true | ||
35 | metrics: | ||
36 | export: | ||
37 | # Prometheus is the default metrics backend | ||
38 | prometheus: | ||
39 | enabled: true | ||
40 | step: 60 | ||
41 | enable: | ||
42 | http: true | ||
43 | jvm: true | ||
44 | logback: true | ||
45 | process: true | ||
46 | system: true | ||
47 | distribution: | ||
48 | percentiles-histogram: | ||
49 | all: true | ||
50 | percentiles: | ||
51 | all: 0, 0.5, 0.75, 0.95, 0.99, 1.0 | ||
52 | tags: | ||
53 | application: ${spring.application.name} | ||
54 | web: | ||
55 | server: | ||
56 | request: | ||
57 | autotime: | ||
58 | enabled: true | ||
59 | |||
60 | spring: | ||
61 | application: | ||
62 | name: honlap | ||
63 | profiles: | ||
64 | # The commented value for `active` can be replaced with valid Spring profiles to load. | ||
65 | # Otherwise, it will be filled in by maven when building the JAR file | ||
66 | # Either way, it can be overridden by `--spring.profiles.active` value passed in the commandline or `-Dspring.profiles.active` set in `JAVA_OPTS` | ||
67 | active: #spring.profiles.active# | ||
68 | jmx: | ||
69 | enabled: false | ||
70 | data: | ||
71 | jpa: | ||
72 | repositories: | ||
73 | bootstrap-mode: deferred | ||
74 | jpa: | ||
75 | open-in-view: false | ||
76 | properties: | ||
77 | hibernate.jdbc.time_zone: UTC | ||
78 | hibernate.id.new_generator_mappings: true | ||
79 | hibernate.connection.provider_disables_autocommit: true | ||
80 | hibernate.cache.use_second_level_cache: true | ||
81 | hibernate.cache.use_query_cache: false | ||
82 | hibernate.generate_statistics: false | ||
83 | # modify batch size as necessary | ||
84 | hibernate.jdbc.batch_size: 25 | ||
85 | hibernate.order_inserts: true | ||
86 | hibernate.order_updates: true | ||
87 | hibernate.query.fail_on_pagination_over_collection_fetch: true | ||
88 | hibernate.query.in_clause_parameter_padding: true | ||
89 | hibernate: | ||
90 | ddl-auto: none | ||
91 | naming: | ||
92 | physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy | ||
93 | implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy | ||
94 | messages: | ||
95 | basename: i18n/messages | ||
96 | main: | ||
97 | allow-bean-definition-overriding: true | ||
98 | mvc: | ||
99 | favicon: | ||
100 | enabled: false | ||
101 | task: | ||
102 | execution: | ||
103 | thread-name-prefix: honlap-task- | ||
104 | pool: | ||
105 | core-size: 2 | ||
106 | max-size: 50 | ||
107 | queue-capacity: 10000 | ||
108 | scheduling: | ||
109 | thread-name-prefix: honlap-scheduling- | ||
110 | pool: | ||
111 | size: 2 | ||
112 | thymeleaf: | ||
113 | mode: HTML | ||
114 | output: | ||
115 | ansi: | ||
116 | console-available: true | ||
117 | |||
118 | server: | ||
119 | servlet: | ||
120 | session: | ||
121 | cookie: | ||
122 | http-only: true | ||
123 | |||
124 | # Properties to be exposed on the /info management endpoint | ||
125 | info: | ||
126 | # Comma separated list of profiles that will trigger the ribbon to show | ||
127 | display-ribbon-on-profiles: 'dev' | ||
128 | |||
129 | # =================================================================== | ||
130 | # JHipster specific properties | ||
131 | # | ||
132 | # Full reference is available at: https://www.jhipster.tech/common-application-properties/ | ||
133 | # =================================================================== | ||
134 | |||
135 | jhipster: | ||
136 | clientApp: | ||
137 | name: 'honlapApp' | ||
138 | # By default CORS is disabled. Uncomment to enable. | ||
139 | # cors: | ||
140 | # allowed-origins: "*" | ||
141 | # allowed-methods: "*" | ||
142 | # allowed-headers: "*" | ||
143 | # exposed-headers: "Authorization,Link,X-Total-Count" | ||
144 | # allow-credentials: true | ||
145 | # max-age: 1800 | ||
146 | mail: | ||
147 | from: honlap@localhost | ||
148 | swagger: | ||
149 | default-include-pattern: /api/.* | ||
150 | title: honlap API | ||
151 | description: honlap API documentation | ||
152 | version: 0.0.1 | ||
153 | terms-of-service-url: | ||
154 | contact-name: | ||
155 | contact-url: | ||
156 | contact-email: | ||
157 | license: | ||
158 | license-url: | ||
159 | # =================================================================== | ||
160 | # Application specific properties | ||
161 | # Add your own application properties here, see the ApplicationProperties class | ||
162 | # to have type-safe configuration, like in the JHipsterProperties above | ||
163 | # | ||
164 | # More documentation is available at: | ||
165 | # https://www.jhipster.tech/common-application-properties/ | ||
166 | # =================================================================== | ||
167 | |||
168 | # application: |
File src/main/resources/config/liquibase/changelog/00000000000000_initial_schema.xml added (mode: 100644) (index 0000000..10ef5bb) | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <databaseChangeLog | ||
3 | xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
4 | xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" | ||
5 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
6 | xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd | ||
7 | http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd"> | ||
8 | |||
9 | <changeSet id="00000000000000" author="jhipster"> | ||
10 | <createSequence sequenceName="sequence_generator" startValue="1050" incrementBy="50"/> | ||
11 | </changeSet> | ||
12 | |||
13 | <!-- | ||
14 | JHipster core tables. | ||
15 | The initial schema has the '00000000000001' id, so that it is over-written if we re-generate it. | ||
16 | --> | ||
17 | <changeSet id="00000000000001" author="jhipster"> | ||
18 | <createTable tableName="auth_user"> | ||
19 | <column name="id" type="bigint" > | ||
20 | <constraints primaryKey="true" nullable="false"/> | ||
21 | </column> | ||
22 | <column name="login" type="varchar(50)"> | ||
23 | <constraints unique="true" nullable="false" uniqueConstraintName="ux_user_login"/> | ||
24 | </column> | ||
25 | <column name="password_hash" type="varchar(60)"/> | ||
26 | <column name="first_name" type="varchar(50)"/> | ||
27 | <column name="last_name" type="varchar(50)"/> | ||
28 | <column name="email" type="varchar(191)"> | ||
29 | <constraints unique="true" nullable="true" uniqueConstraintName="ux_user_email"/> | ||
30 | </column> | ||
31 | <column name="image_url" type="varchar(256)"/> | ||
32 | <column name="activated" type="boolean" valueBoolean="false"> | ||
33 | <constraints nullable="false" /> | ||
34 | </column> | ||
35 | <column name="lang_key" type="varchar(10)"/> | ||
36 | <column name="activation_key" type="varchar(20)"/> | ||
37 | <column name="reset_key" type="varchar(20)"/> | ||
38 | <column name="created_by" type="varchar(50)"> | ||
39 | <constraints nullable="false"/> | ||
40 | </column> | ||
41 | <column name="created_date" type="timestamp"/> | ||
42 | <column name="reset_date" type="timestamp"> | ||
43 | <constraints nullable="true"/> | ||
44 | </column> | ||
45 | <column name="last_modified_by" type="varchar(50)"/> | ||
46 | <column name="last_modified_date" type="timestamp"/> | ||
47 | </createTable> | ||
48 | |||
49 | <createTable tableName="auth_authority"> | ||
50 | <column name="name" type="varchar(50)"> | ||
51 | <constraints primaryKey="true" nullable="false"/> | ||
52 | </column> | ||
53 | </createTable> | ||
54 | |||
55 | <createTable tableName="auth_user_authority"> | ||
56 | <column name="user_id" type="bigint"> | ||
57 | <constraints nullable="false"/> | ||
58 | </column> | ||
59 | <column name="authority_name" type="varchar(50)"> | ||
60 | <constraints nullable="false"/> | ||
61 | </column> | ||
62 | </createTable> | ||
63 | |||
64 | <addPrimaryKey columnNames="user_id, authority_name" tableName="auth_user_authority"/> | ||
65 | |||
66 | <addForeignKeyConstraint baseColumnNames="authority_name" | ||
67 | baseTableName="auth_user_authority" | ||
68 | constraintName="fk_authority_name" | ||
69 | referencedColumnNames="name" | ||
70 | referencedTableName="auth_authority"/> | ||
71 | |||
72 | <addForeignKeyConstraint baseColumnNames="user_id" | ||
73 | baseTableName="auth_user_authority" | ||
74 | constraintName="fk_user_id" | ||
75 | referencedColumnNames="id" | ||
76 | referencedTableName="auth_user"/> | ||
77 | |||
78 | <addNotNullConstraint columnName="password_hash" | ||
79 | columnDataType="varchar(60)" | ||
80 | tableName="auth_user"/> | ||
81 | <loadData | ||
82 | file="config/liquibase/data/user.csv" | ||
83 | separator=";" | ||
84 | tableName="auth_user"> | ||
85 | <column name="id" type="numeric"/> | ||
86 | <column name="activated" type="boolean"/> | ||
87 | <column name="created_date" type="timestamp"/> | ||
88 | </loadData> | ||
89 | <dropDefaultValue tableName="auth_user" columnName="created_date" columnDataType="datetime"/> | ||
90 | <loadData | ||
91 | file="config/liquibase/data/authority.csv" | ||
92 | separator=";" | ||
93 | tableName="auth_authority"> | ||
94 | <column name="name" type="string"/> | ||
95 | </loadData> | ||
96 | |||
97 | <loadData | ||
98 | file="config/liquibase/data/user_authority.csv" | ||
99 | separator=";" | ||
100 | tableName="auth_user_authority"> | ||
101 | <column name="user_id" type="numeric"/> | ||
102 | </loadData> | ||
103 | <createTable tableName="auth_persistent_audit_event"> | ||
104 | <column name="event_id" type="bigint" > | ||
105 | <constraints primaryKey="true" nullable="false"/> | ||
106 | </column> | ||
107 | <column name="principal" type="varchar(50)"> | ||
108 | <constraints nullable="false" /> | ||
109 | </column> | ||
110 | <column name="event_date" type="timestamp"/> | ||
111 | <column name="event_type" type="varchar(255)"/> | ||
112 | </createTable> | ||
113 | |||
114 | <createTable tableName="auth_persistent_audit_evt_data"> | ||
115 | <column name="event_id" type="bigint"> | ||
116 | <constraints nullable="false"/> | ||
117 | </column> | ||
118 | <column name="name" type="varchar(150)"> | ||
119 | <constraints nullable="false"/> | ||
120 | </column> | ||
121 | <column name="value" type="varchar(255)"/> | ||
122 | </createTable> | ||
123 | <addPrimaryKey columnNames="event_id, name" tableName="auth_persistent_audit_evt_data"/> | ||
124 | |||
125 | <createIndex indexName="idx_persistent_audit_event" | ||
126 | tableName="auth_persistent_audit_event" | ||
127 | unique="false"> | ||
128 | <column name="principal" type="varchar(50)"/> | ||
129 | <column name="event_date" type="timestamp"/> | ||
130 | </createIndex> | ||
131 | |||
132 | <createIndex indexName="idx_persistent_audit_evt_data" | ||
133 | tableName="auth_persistent_audit_evt_data" | ||
134 | unique="false"> | ||
135 | <column name="event_id" type="bigint"/> | ||
136 | </createIndex> | ||
137 | |||
138 | <addForeignKeyConstraint baseColumnNames="event_id" | ||
139 | baseTableName="auth_persistent_audit_evt_data" | ||
140 | constraintName="fk_evt_pers_audit_evt_data" | ||
141 | referencedColumnNames="event_id" | ||
142 | referencedTableName="auth_persistent_audit_event"/> | ||
143 | </changeSet> | ||
144 | |||
145 | <changeSet author="jhipster" id="00000000000002" context="test"> | ||
146 | <createTable tableName="auth_date_time_wrapper"> | ||
147 | <column name="id" type="BIGINT"> | ||
148 | <constraints primaryKey="true" primaryKeyName="auth_date_time_wrapperPK"/> | ||
149 | </column> | ||
150 | <column name="instant" type="timestamp"/> | ||
151 | <column name="local_date_time" type="timestamp"/> | ||
152 | <column name="offset_date_time" type="timestamp"/> | ||
153 | <column name="zoned_date_time" type="timestamp"/> | ||
154 | <column name="local_time" type="time"/> | ||
155 | <column name="offset_time" type="time"/> | ||
156 | <column name="local_date" type="date"/> | ||
157 | </createTable> | ||
158 | </changeSet> | ||
159 | </databaseChangeLog> |
File src/main/resources/config/liquibase/changelog/20200326085000_added_entity_PieceOfNews.xml added (mode: 100644) (index 0000000..bdc5cd6) | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <databaseChangeLog | ||
3 | xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
4 | xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext" | ||
5 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
6 | xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd | ||
7 | http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd"> | ||
8 | |||
9 | |||
10 | <!-- | ||
11 | Added the entity PieceOfNews. | ||
12 | --> | ||
13 | <changeSet id="20200326085000-1" author="jhipster"> | ||
14 | <createTable tableName="piece_of_news" remarks="Hírek"> | ||
15 | <column name="id" type="bigint"> | ||
16 | <constraints primaryKey="true" nullable="false"/> | ||
17 | </column> | ||
18 | <column name="app_id" type="integer"> | ||
19 | <constraints nullable="false" /> | ||
20 | </column> | ||
21 | <column name="news_date" type="datetime"> | ||
22 | <constraints nullable="false" /> | ||
23 | </column> | ||
24 | <column name="headline" type="varchar(300)"> | ||
25 | <constraints nullable="false" /> | ||
26 | </column> | ||
27 | <column name="content" type="varchar(600)"> | ||
28 | <constraints nullable="false" /> | ||
29 | </column> | ||
30 | <column name="link" type="varchar(600)"> | ||
31 | <constraints nullable="false" /> | ||
32 | </column> | ||
33 | <column name="publish_date" type="datetime"> | ||
34 | <constraints nullable="true" /> | ||
35 | </column> | ||
36 | <column name="created_by" type="varchar(255)"> | ||
37 | <constraints nullable="true" /> | ||
38 | </column> | ||
39 | <column name="created_date" type="datetime"> | ||
40 | <constraints nullable="true" /> | ||
41 | </column> | ||
42 | <column name="last_modified_by" type="varchar(255)"> | ||
43 | <constraints nullable="true" /> | ||
44 | </column> | ||
45 | <column name="last_modified_date" type="datetime"> | ||
46 | <constraints nullable="true" /> | ||
47 | </column> | ||
48 | <!-- jhipster-needle-liquibase-add-column - JHipster will add columns here, do not remove--> | ||
49 | </createTable> | ||
50 | <dropDefaultValue tableName="piece_of_news" columnName="news_date" columnDataType="datetime"/> | ||
51 | <dropDefaultValue tableName="piece_of_news" columnName="publish_date" columnDataType="datetime"/> | ||
52 | <dropDefaultValue tableName="piece_of_news" columnName="created_date" columnDataType="datetime"/> | ||
53 | <dropDefaultValue tableName="piece_of_news" columnName="last_modified_date" columnDataType="datetime"/> | ||
54 | </changeSet> | ||
55 | |||
56 | <changeSet id="20200326085000-1-relations" author="jhipster"> | ||
57 | |||
58 | </changeSet> | ||
59 | <!-- jhipster-needle-liquibase-add-changeset - JHipster will add changesets here, do not remove--> | ||
60 | |||
61 | <!-- | ||
62 | Load sample data generated with Faker.js | ||
63 | - This data can be easily edited using a CSV editor (or even MS Excel) and | ||
64 | is located in the 'src/main/resources/config/liquibase/fake-data' directory | ||
65 | - By default this data is applied when running with the JHipster 'dev' profile. | ||
66 | This can be customized by adding or removing 'faker' in the 'spring.liquibase.contexts' | ||
67 | Spring Boot configuration key. | ||
68 | --> | ||
69 | <changeSet id="20200326085000-1-data" author="jhipster" context="faker"> | ||
70 | <loadData | ||
71 | file="config/liquibase/fake-data/piece_of_news.csv" | ||
72 | separator=";" | ||
73 | tableName="piece_of_news"> | ||
74 | <column name="id" type="numeric"/> | ||
75 | <column name="app_id" type="numeric"/> | ||
76 | <column name="news_date" type="datetime"/> | ||
77 | <column name="headline" type="string"/> | ||
78 | <column name="content" type="string"/> | ||
79 | <column name="link" type="string"/> | ||
80 | <column name="publish_date" type="datetime"/> | ||
81 | <column name="created_by" type="string"/> | ||
82 | <column name="created_date" type="datetime"/> | ||
83 | <column name="last_modified_by" type="string"/> | ||
84 | <column name="last_modified_date" type="datetime"/> | ||
85 | <!-- jhipster-needle-liquibase-add-loadcolumn - JHipster (and/or extensions) can add load columns here, do not remove--> | ||
86 | </loadData> | ||
87 | </changeSet> | ||
88 | |||
89 | </databaseChangeLog> |
File src/main/resources/config/liquibase/data/authority.csv added (mode: 100644) (index 0000000..af5c6df) | |||
1 | name | ||
2 | ROLE_ADMIN | ||
3 | ROLE_USER |
File src/main/resources/config/liquibase/data/user.csv added (mode: 100644) (index 0000000..3089c1b) | |||
1 | id;login;password_hash;first_name;last_name;email;image_url;activated;lang_key;created_by;last_modified_by | ||
2 | 1;system;$2a$10$mE.qmcV0mFU5NcKh73TZx.z4ueI/.bDWbj0T1BYyqP481kGGarKLG;System;System;system@localhost;;true;hu;system;system | ||
3 | 2;anonymoususer;$2a$10$j8S5d7Sr7.8VTOYNviDPOeWX8KcYILUVJBsYV83Y5NtECayypx9lO;Anonymous;User;anonymous@localhost;;true;hu;system;system | ||
4 | 3;admin;$2a$10$gSAhZrxMllrbgj/kkK9UceBPpChGWJA7SYIb1Mqo.n5aNLq1/oRrC;Administrator;Administrator;admin@localhost;;true;hu;system;system | ||
5 | 4;user;$2a$10$VEjxo0jq2YG9Rbk2HmX9S.k1uZBGYUHdUcid3g/vfiEl7lwWgOH/K;User;User;user@localhost;;true;hu;system;system |
File src/main/resources/config/liquibase/data/user_authority.csv added (mode: 100644) (index 0000000..06c5fee) | |||
1 | user_id;authority_name | ||
2 | 1;ROLE_ADMIN | ||
3 | 1;ROLE_USER | ||
4 | 3;ROLE_ADMIN | ||
5 | 3;ROLE_USER | ||
6 | 4;ROLE_USER |
File src/main/resources/config/liquibase/fake-data/piece_of_news.csv added (mode: 100644) (index 0000000..500c7bf) | |||
1 | id;app_id;news_date;headline;content;link;publish_date;created_by;created_date;last_modified_by;last_modified_date | ||
2 | 1;38858;2020-03-25T14:55:01;platforms Music action-items;Cambridgeshire;Florida streamline;2020-03-25T21:03:21;Personal Loan Account tangible Borders;2020-03-25T17:34:45;unleash;2020-03-25T11:34:00 | ||
3 | 2;599;2020-03-25T23:44:13;Hawaii;system engine Investment Account;Malta Soap multi-byte;2020-03-26T08:31:13;Serbian Dinar Cambridgeshire French Southern Territories;2020-03-25T11:48:41;Brand Designer;2020-03-25T23:57:00 | ||
4 | 3;68812;2020-03-25T18:59:45;Books calculate;cross-platform Cambridgeshire Knolls;Decentralized Ball;2020-03-25T16:47:26;Handmade transmit;2020-03-25T15:28:43;mobile;2020-03-25T18:58:38 | ||
5 | 4;30089;2020-03-26T01:55:42;neural iterate;Ergonomic Soft Table;invoice;2020-03-25T22:25:02;generate;2020-03-26T00:51:20;Cotton Burundi;2020-03-26T06:33:58 | ||
6 | 5;31763;2020-03-25T23:12:52;Sri Lanka Rupee;Dynamic Chief hard drive;Maine reboot orange;2020-03-25T17:13:52;Optimized;2020-03-25T19:06:11;Awesome Steel Tuna;2020-03-25T22:26:17 | ||
7 | 6;94138;2020-03-25T17:18:14;composite Executive indexing;frame;Tools Personal Loan Account Bedfordshire;2020-03-25T21:05:21;best-of-breed cultivate;2020-03-25T12:40:51;Metrics navigating;2020-03-25T22:50:17 | ||
8 | 7;88844;2020-03-25T21:09:19;Saint Pierre and Miquelon Stravenue XML;primary initiatives;e-business Books;2020-03-26T06:29:56;array redundant;2020-03-26T04:53:12;brand;2020-03-25T17:27:42 | ||
9 | 8;14466;2020-03-25T11:48:53;payment Bosnia and Herzegovina driver;envisioneer;system Markets;2020-03-26T03:03:46;engineer HTTP Games;2020-03-26T08:27:39;Kids;2020-03-26T00:00:39 | ||
10 | 9;98697;2020-03-26T08:06:27;withdrawal;payment encryption;Senior;2020-03-25T12:00:14;Small Metal Table 1080p;2020-03-25T09:44:31;Missouri;2020-03-25T19:08:41 | ||
11 | 10;46840;2020-03-25T10:51:37;port Analyst Mississippi;Auto Loan Account Outdoors Licensed Plastic Soap;Cambridgeshire Ergonomic Steel Mouse;2020-03-26T03:42:54;seamless Metal bandwidth;2020-03-25T14:00:17;Connecticut bypass Architect;2020-03-25T22:37:51 |
File src/main/resources/config/liquibase/master.xml added (mode: 100644) (index 0000000..d4c2562) | |||
1 | <?xml version="1.0" encoding="utf-8"?> | ||
2 | <databaseChangeLog | ||
3 | xmlns="http://www.liquibase.org/xml/ns/dbchangelog" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd"> | ||
6 | |||
7 | <property name="now" value="now()" dbms="h2"/> | ||
8 | <property name="now" value="current_timestamp" dbms="postgresql"/> | ||
9 | |||
10 | <property name="floatType" value="float4" dbms="postgresql, h2"/> | ||
11 | <property name="floatType" value="float" dbms="mysql, oracle, mssql, mariadb"/> | ||
12 | <property name="clobType" value="longvarchar" dbms="h2"/> | ||
13 | <property name="clobType" value="clob" dbms="mysql, oracle, mssql, mariadb, postgresql"/> | ||
14 | <property name="uuidType" value="uuid" dbms="h2, postgresql"/> | ||
15 | |||
16 | <include file="config/liquibase/changelog/00000000000000_initial_schema.xml" relativeToChangelogFile="false"/> | ||
17 | <include file="config/liquibase/changelog/20200326085000_added_entity_PieceOfNews.xml" relativeToChangelogFile="false"/> | ||
18 | <!-- jhipster-needle-liquibase-add-changelog - JHipster will add liquibase changelogs here --> | ||
19 | <!-- jhipster-needle-liquibase-add-constraints-changelog - JHipster will add liquibase constraints changelogs here --> | ||
20 | </databaseChangeLog> |
File src/main/resources/config/tls/keystore.p12 added (mode: 100644) (index 0000000..a9c8793) |
File src/main/resources/i18n/messages.properties added (mode: 100644) (index 0000000..e0f2f63) | |||
1 | # Error page | ||
2 | error.title=Your request cannot be processed | ||
3 | error.subtitle=Sorry, an error has occurred. | ||
4 | error.status=Status: | ||
5 | error.message=Message: | ||
6 | |||
7 | # Activation email | ||
8 | email.activation.title=honlap account activation is required | ||
9 | email.activation.greeting=Dear {0} | ||
10 | email.activation.text1=Your honlap account has been created, please click on the URL below to activate it: | ||
11 | email.activation.text2=Regards, | ||
12 | email.signature=honlap Team. | ||
13 | |||
14 | # Creation email | ||
15 | email.creation.text1=Your honlap account has been created, please click on the URL below to access it: | ||
16 | |||
17 | # Reset email | ||
18 | email.reset.title=honlap password reset | ||
19 | email.reset.greeting=Dear {0} | ||
20 | email.reset.text1=For your honlap account a password reset was requested, please click on the URL below to reset it: | ||
21 | email.reset.text2=Regards, |
File src/main/resources/i18n/messages_en.properties added (mode: 100644) (index 0000000..9b4d488) | |||
1 | # Error page | ||
2 | error.title=Your request cannot be processed | ||
3 | error.subtitle=Sorry, an error has occurred. | ||
4 | error.status=Status: | ||
5 | error.message=Message: | ||
6 | |||
7 | # Activation email | ||
8 | email.activation.title=honlap account activation | ||
9 | email.activation.greeting=Dear {0} | ||
10 | email.activation.text1=Your honlap account has been created, please click on the URL below to activate it: | ||
11 | email.activation.text2=Regards, | ||
12 | email.signature=honlap Team. | ||
13 | |||
14 | # Creation email | ||
15 | email.creation.text1=Your honlap account has been created, please click on the URL below to access it: | ||
16 | |||
17 | # Reset email | ||
18 | email.reset.title=honlap password reset | ||
19 | email.reset.greeting=Dear {0} | ||
20 | email.reset.text1=For your honlap account a password reset was requested, please click on the URL below to reset it: | ||
21 | email.reset.text2=Regards, |
File src/main/resources/i18n/messages_hu.properties added (mode: 100644) (index 0000000..2d72b58) | |||
1 | # Error page | ||
2 | error.title=A kérése nem hajtható végre | ||
3 | error.subtitle=Elnézést, hiba történt | ||
4 | error.status=Státusz: | ||
5 | error.message=Üzenet: | ||
6 | |||
7 | # Activation email | ||
8 | email.activation.title=honlap hozzáférés aktiválása. | ||
9 | email.activation.greeting=Tisztelt {0} | ||
10 | email.activation.text1=Az Ön honlap hozzáférése elkészült, kérjük kattintson az alább található linkre az aktiváláshoz. | ||
11 | email.activation.text2=Üdvözlettel, | ||
12 | email.signature=honlap csapat. | ||
13 | |||
14 | # Creation email | ||
15 | email.creation.text1=Az Ön honlap hozzáférése elkészült, kérjük kattintson az alább található linkre a belépéshez: | ||
16 | |||
17 | # Reset email | ||
18 | email.reset.title=honlap jelszó visszaállítás | ||
19 | email.reset.greeting=Tisztelt {0} | ||
20 | email.reset.text1=Az Ön honlap fiókjához jelszó-visszaállítót kértek, kérjük kattintson az alábbi linkre, hogy a jelszavát visszaállíthassa : | ||
21 | email.reset.text2=Üdvözlettel, |
File src/main/resources/logback-spring.xml added (mode: 100644) (index 0000000..1f90362) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE configuration> | ||
3 | |||
4 | <configuration scan="true"> | ||
5 | <include resource="org/springframework/boot/logging/logback/base.xml"/> | ||
6 | |||
7 | <!-- The FILE and ASYNC appenders are here as examples for a production configuration --> | ||
8 | <!-- | ||
9 | <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> | ||
10 | <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> | ||
11 | <fileNamePattern>logFile.%d{yyyy-MM-dd}.log</fileNamePattern> | ||
12 | <maxHistory>90</maxHistory> | ||
13 | </rollingPolicy> | ||
14 | <encoder> | ||
15 | <charset>utf-8</charset> | ||
16 | <Pattern>%d %-5level [%thread] %logger{0}: %msg%n</Pattern> | ||
17 | </encoder> | ||
18 | </appender> | ||
19 | |||
20 | <appender name="ASYNC" class="ch.qos.logback.classic.AsyncAppender"> | ||
21 | <queueSize>512</queueSize> | ||
22 | <appender-ref ref="FILE"/> | ||
23 | </appender> | ||
24 | |||
25 | <root level="${logging.level.root}"> | ||
26 | <appender-ref ref="ASYNC"/> | ||
27 | </root> | ||
28 | --> | ||
29 | |||
30 | <logger name="javax.activation" level="WARN"/> | ||
31 | <logger name="javax.mail" level="WARN"/> | ||
32 | <logger name="javax.management.remote" level="WARN"/> | ||
33 | <logger name="javax.xml.bind" level="WARN"/> | ||
34 | <logger name="ch.qos.logback" level="WARN"/> | ||
35 | <logger name="com.ryantenney" level="WARN"/> | ||
36 | <logger name="com.sun" level="WARN"/> | ||
37 | <logger name="com.zaxxer" level="WARN"/> | ||
38 | <logger name="io.undertow" level="WARN"/> | ||
39 | <logger name="io.undertow.websockets.jsr" level="ERROR"/> | ||
40 | <logger name="org.ehcache" level="WARN"/> | ||
41 | <logger name="org.apache" level="WARN"/> | ||
42 | <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> | ||
43 | <logger name="org.bson" level="WARN"/> | ||
44 | <logger name="org.hibernate.validator" level="WARN"/> | ||
45 | <logger name="org.hibernate" level="WARN"/> | ||
46 | <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> | ||
47 | <logger name="org.postgresql" level="WARN"/> | ||
48 | <logger name="org.springframework" level="WARN"/> | ||
49 | <logger name="org.springframework.web" level="WARN"/> | ||
50 | <logger name="org.springframework.security" level="WARN"/> | ||
51 | <logger name="org.springframework.cache" level="WARN"/> | ||
52 | <logger name="org.thymeleaf" level="WARN"/> | ||
53 | <logger name="org.xnio" level="WARN"/> | ||
54 | <logger name="springfox" level="WARN"/> | ||
55 | <logger name="sun.rmi" level="WARN"/> | ||
56 | <logger name="liquibase" level="WARN"/> | ||
57 | <logger name="LiquibaseSchemaResolver" level="INFO"/> | ||
58 | <logger name="springfox.documentation.schema.property" level="ERROR"/> | ||
59 | <logger name="sun.rmi.transport" level="WARN"/> | ||
60 | <!-- jhipster-needle-logback-add-log - JHipster will add a new log with level, Do not remove --> | ||
61 | |||
62 | <!-- https://logback.qos.ch/manual/configuration.html#shutdownHook and https://jira.qos.ch/browse/LOGBACK-1090 --> | ||
63 | <shutdownHook class="ch.qos.logback.core.hook.DelayingShutdownHook"/> | ||
64 | |||
65 | <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator"> | ||
66 | <resetJUL>true</resetJUL> | ||
67 | </contextListener> | ||
68 | |||
69 | </configuration> |
File src/main/resources/templates/error.html added (mode: 100644) (index 0000000..b703488) | |||
1 | <!DOCTYPE html> | ||
2 | <html xmlns:th="http://www.thymeleaf.org" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
3 | xsi:schemaLocation="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en"> | ||
4 | <head> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/> | ||
6 | <link rel="shortcut icon" href="${baseUrl}/favicon.ico" /> | ||
7 | <title>Your request cannot be processed</title> | ||
8 | <style> | ||
9 | ::-moz-selection { | ||
10 | background: #b3d4fc; | ||
11 | text-shadow: none; | ||
12 | } | ||
13 | |||
14 | ::selection { | ||
15 | background: #b3d4fc; | ||
16 | text-shadow: none; | ||
17 | } | ||
18 | |||
19 | html { | ||
20 | padding: 30px 10px; | ||
21 | font-size: 20px; | ||
22 | line-height: 1.4; | ||
23 | color: #737373; | ||
24 | background: #3E8ACC; | ||
25 | -webkit-text-size-adjust: 100%; | ||
26 | -ms-text-size-adjust: 100%; | ||
27 | } | ||
28 | |||
29 | html, | ||
30 | input { | ||
31 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; | ||
32 | } | ||
33 | |||
34 | body { | ||
35 | max-width: 1000px; | ||
36 | _width: 500px; | ||
37 | padding: 30px 20px 50px; | ||
38 | border: 1px solid #b3b3b3; | ||
39 | border-radius: 4px; | ||
40 | margin: 0 auto; | ||
41 | box-shadow: 0 1px 10px #a7a7a7, inset 0 1px 0 #fff; | ||
42 | background: #fcfcfc; | ||
43 | } | ||
44 | |||
45 | h1 { | ||
46 | margin: 0 10px; | ||
47 | font-size: 50px; | ||
48 | text-align: center; | ||
49 | } | ||
50 | |||
51 | h1 span { | ||
52 | color: #bbb; | ||
53 | } | ||
54 | |||
55 | h3 { | ||
56 | margin: 1.5em 0 0.5em; | ||
57 | } | ||
58 | |||
59 | p { | ||
60 | margin: 1em 0; | ||
61 | } | ||
62 | |||
63 | ul { | ||
64 | padding: 0 0 0 40px; | ||
65 | margin: 1em 0; | ||
66 | } | ||
67 | |||
68 | .container { | ||
69 | max-width: 800px; | ||
70 | _width: 380px; | ||
71 | margin: 0 auto; | ||
72 | } | ||
73 | </style> | ||
74 | </head> | ||
75 | <body> | ||
76 | <div class="container"> | ||
77 | <h1 th:text="#{error.title}">Your request cannot be processed <span>:(</span></h1> | ||
78 | |||
79 | <p th:text="#{error.subtitle}">Sorry, an error has occurred.</p> | ||
80 | |||
81 | <span th:text="#{error.status}">Status:</span> <span th:text="${error}"></span> (<span th:text="${error}"></span>)<br/> | ||
82 | <span th:if="${!#strings.isEmpty(message)}"> | ||
83 | <span th:text="#{error.message}">Message:</span> <span th:text="${message}"></span><br/> | ||
84 | </span> | ||
85 | </div> | ||
86 | </body> | ||
87 | </html> |
File src/main/resources/templates/mail/activationEmail.html added (mode: 100644) (index 0000000..f88aa94) | |||
1 | <!DOCTYPE html> | ||
2 | <html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en"> | ||
3 | <head> | ||
4 | <title th:text="#{email.activation.title}">JHipster activation</title> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
6 | <link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}" /> | ||
7 | </head> | ||
8 | <body> | ||
9 | <p th:text="#{email.activation.greeting(${user.login})}"> | ||
10 | Dear | ||
11 | </p> | ||
12 | <p th:text="#{email.activation.text1}"> | ||
13 | Your JHipster account has been created, please click on the URL below to activate it: | ||
14 | </p> | ||
15 | <p> | ||
16 | <a th:with="url=(@{|${baseUrl}/account/activate?key=${user.activationKey}|})" th:href="${url}" | ||
17 | th:text="${url}">Activation link</a> | ||
18 | </p> | ||
19 | <p> | ||
20 | <span th:text="#{email.activation.text2}">Regards, </span> | ||
21 | <br/> | ||
22 | <em th:text="#{email.signature}">JHipster.</em> | ||
23 | </p> | ||
24 | </body> | ||
25 | </html> |
File src/main/resources/templates/mail/creationEmail.html added (mode: 100644) (index 0000000..26d3fe4) | |||
1 | <!DOCTYPE html> | ||
2 | <html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en"> | ||
3 | <head> | ||
4 | <title th:text="#{email.activation.title}">JHipster creation</title> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
6 | <link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}" /> | ||
7 | </head> | ||
8 | <body> | ||
9 | <p th:text="#{email.activation.greeting(${user.login})}"> | ||
10 | Dear | ||
11 | </p> | ||
12 | <p th:text="#{email.creation.text1}"> | ||
13 | Your JHipster account has been created, please click on the URL below to access it: | ||
14 | </p> | ||
15 | <p> | ||
16 | <a th:with="url=(@{|${baseUrl}/account/reset/finish?key=${user.resetKey}|})" th:href="${url}" | ||
17 | th:text="${url}">Login link</a> | ||
18 | </p> | ||
19 | <p> | ||
20 | <span th:text="#{email.activation.text2}">Regards, </span> | ||
21 | <br/> | ||
22 | <em th:text="#{email.signature}">JHipster.</em> | ||
23 | </p> | ||
24 | </body> | ||
25 | </html> |
File src/main/resources/templates/mail/passwordResetEmail.html added (mode: 100644) (index 0000000..c5ae07f) | |||
1 | <!DOCTYPE html> | ||
2 | <html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en"> | ||
3 | <head> | ||
4 | <title th:text="#{email.reset.title}">JHipster password reset</title> | ||
5 | <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> | ||
6 | <link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}" /> | ||
7 | </head> | ||
8 | <body> | ||
9 | <p th:text="#{email.reset.greeting(${user.login})}"> | ||
10 | Dear | ||
11 | </p> | ||
12 | <p th:text="#{email.reset.text1}"> | ||
13 | For your JHipster account a password reset was requested, please click on the URL below to reset it: | ||
14 | </p> | ||
15 | <p> | ||
16 | <a th:with="url=(@{|${baseUrl}/account/reset/finish?key=${user.resetKey}|})" th:href="${url}" | ||
17 | th:text="${url}">Login link</a> | ||
18 | </p> | ||
19 | <p> | ||
20 | <span th:text="#{email.reset.text2}">Regards, </span> | ||
21 | <br/> | ||
22 | <em th:text="#{email.signature}">JHipster.</em> | ||
23 | </p> | ||
24 | </body> | ||
25 | </html> |
File src/main/webapp/404.html added (mode: 100644) (index 0000000..cf8bb74) | |||
1 | <!doctype html> | ||
2 | <html lang="hu"> | ||
3 | <head> | ||
4 | <meta charset="utf-8"> | ||
5 | <title>Page Not Found</title> | ||
6 | <meta name="viewport" content="width=device-width, initial-scale=1"> | ||
7 | <link rel="shortcut icon" href="favicon.ico" /> | ||
8 | <style> | ||
9 | |||
10 | * { | ||
11 | line-height: 1.2; | ||
12 | margin: 0; | ||
13 | } | ||
14 | |||
15 | html { | ||
16 | color: #888; | ||
17 | display: table; | ||
18 | font-family: sans-serif; | ||
19 | height: 100%; | ||
20 | text-align: center; | ||
21 | width: 100%; | ||
22 | } | ||
23 | |||
24 | body { | ||
25 | display: table-cell; | ||
26 | vertical-align: middle; | ||
27 | margin: 2em auto; | ||
28 | } | ||
29 | |||
30 | h1 { | ||
31 | color: #555; | ||
32 | font-size: 2em; | ||
33 | font-weight: 400; | ||
34 | } | ||
35 | |||
36 | p { | ||
37 | margin: 0 auto; | ||
38 | width: 280px; | ||
39 | } | ||
40 | |||
41 | @media only screen and (max-width: 280px) { | ||
42 | |||
43 | body, p { | ||
44 | width: 95%; | ||
45 | } | ||
46 | |||
47 | h1 { | ||
48 | font-size: 1.5em; | ||
49 | margin: 0 0 0.3em; | ||
50 | } | ||
51 | |||
52 | } | ||
53 | |||
54 | </style> | ||
55 | </head> | ||
56 | <body> | ||
57 | <h1>Page Not Found</h1> | ||
58 | <p>Sorry, but the page you were trying to view does not exist.</p> | ||
59 | </body> | ||
60 | </html> | ||
61 | <!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx --> |
File src/main/webapp/WEB-INF/web.xml added (mode: 100644) (index 0000000..f1611b5) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <web-app | ||
3 | xmlns="http://java.sun.com/xml/ns/javaee" | ||
4 | xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" | ||
5 | xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" | ||
6 | version="3.0"> | ||
7 | |||
8 | <mime-mapping> | ||
9 | <extension>html</extension> | ||
10 | <mime-type>text/html;charset=utf-8</mime-type> | ||
11 | </mime-mapping> | ||
12 | |||
13 | </web-app> |
File src/main/webapp/app/account/account.module.ts added (mode: 100644) (index 0000000..90fb55c) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | |||
4 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
5 | |||
6 | import { PasswordStrengthBarComponent } from './password/password-strength-bar.component'; | ||
7 | import { RegisterComponent } from './register/register.component'; | ||
8 | import { ActivateComponent } from './activate/activate.component'; | ||
9 | import { PasswordComponent } from './password/password.component'; | ||
10 | import { PasswordResetInitComponent } from './password-reset/init/password-reset-init.component'; | ||
11 | import { PasswordResetFinishComponent } from './password-reset/finish/password-reset-finish.component'; | ||
12 | import { SettingsComponent } from './settings/settings.component'; | ||
13 | import { accountState } from './account.route'; | ||
14 | |||
15 | @NgModule({ | ||
16 | imports: [HonlapSharedModule, RouterModule.forChild(accountState)], | ||
17 | declarations: [ | ||
18 | ActivateComponent, | ||
19 | RegisterComponent, | ||
20 | PasswordComponent, | ||
21 | PasswordStrengthBarComponent, | ||
22 | PasswordResetInitComponent, | ||
23 | PasswordResetFinishComponent, | ||
24 | SettingsComponent | ||
25 | ] | ||
26 | }) | ||
27 | export class AccountModule {} |
File src/main/webapp/app/account/account.route.ts added (mode: 100644) (index 0000000..3c15bb7) | |||
1 | import { Routes } from '@angular/router'; | ||
2 | |||
3 | import { activateRoute } from './activate/activate.route'; | ||
4 | import { passwordRoute } from './password/password.route'; | ||
5 | import { passwordResetFinishRoute } from './password-reset/finish/password-reset-finish.route'; | ||
6 | import { passwordResetInitRoute } from './password-reset/init/password-reset-init.route'; | ||
7 | import { registerRoute } from './register/register.route'; | ||
8 | import { settingsRoute } from './settings/settings.route'; | ||
9 | |||
10 | const ACCOUNT_ROUTES = [activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute]; | ||
11 | |||
12 | export const accountState: Routes = [ | ||
13 | { | ||
14 | path: '', | ||
15 | children: ACCOUNT_ROUTES | ||
16 | } | ||
17 | ]; |
File src/main/webapp/app/account/activate/activate.component.html added (mode: 100644) (index 0000000..92b942b) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-8"> | ||
4 | <h1 jhiTranslate="activate.title">Activation</h1> | ||
5 | |||
6 | <div class="alert alert-success" *ngIf="success"> | ||
7 | <span jhiTranslate="activate.messages.success"><strong>Your user account has been activated.</strong> Please </span> | ||
8 | <a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a>. | ||
9 | </div> | ||
10 | |||
11 | <div class="alert alert-danger" *ngIf="error" jhiTranslate="activate.messages.error"> | ||
12 | <strong>Your user could not be activated.</strong> Please use the registration form to sign up. | ||
13 | </div> | ||
14 | </div> | ||
15 | </div> | ||
16 | </div> |
File src/main/webapp/app/account/activate/activate.component.ts added (mode: 100644) (index 0000000..ff525da) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | import { flatMap } from 'rxjs/operators'; | ||
4 | |||
5 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
6 | import { ActivateService } from './activate.service'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-activate', | ||
10 | templateUrl: './activate.component.html' | ||
11 | }) | ||
12 | export class ActivateComponent implements OnInit { | ||
13 | error = false; | ||
14 | success = false; | ||
15 | |||
16 | constructor(private activateService: ActivateService, private loginModalService: LoginModalService, private route: ActivatedRoute) {} | ||
17 | |||
18 | ngOnInit(): void { | ||
19 | this.route.queryParams.pipe(flatMap(params => this.activateService.get(params.key))).subscribe( | ||
20 | () => (this.success = true), | ||
21 | () => (this.error = true) | ||
22 | ); | ||
23 | } | ||
24 | |||
25 | login(): void { | ||
26 | this.loginModalService.open(); | ||
27 | } | ||
28 | } |
File src/main/webapp/app/account/activate/activate.route.ts added (mode: 100644) (index 0000000..a988352) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { ActivateComponent } from './activate.component'; | ||
4 | |||
5 | export const activateRoute: Route = { | ||
6 | path: 'activate', | ||
7 | component: ActivateComponent, | ||
8 | data: { | ||
9 | authorities: [], | ||
10 | pageTitle: 'activate.title' | ||
11 | } | ||
12 | }; |
File src/main/webapp/app/account/activate/activate.service.ts added (mode: 100644) (index 0000000..9cac51e) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient, HttpParams } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | @Injectable({ providedIn: 'root' }) | ||
8 | export class ActivateService { | ||
9 | constructor(private http: HttpClient) {} | ||
10 | |||
11 | get(key: string): Observable<{}> { | ||
12 | return this.http.get(SERVER_API_URL + 'api/activate', { | ||
13 | params: new HttpParams().set('key', key) | ||
14 | }); | ||
15 | } | ||
16 | } |
File src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html added (mode: 100644) (index 0000000..9c5e5b9) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-4"> | ||
4 | <h1 jhiTranslate="reset.finish.title">Reset password</h1> | ||
5 | |||
6 | <div class="alert alert-danger" jhiTranslate="reset.finish.messages.keymissing" *ngIf="initialized && !key"> | ||
7 | <strong>The password reset key is missing.</strong> | ||
8 | </div> | ||
9 | |||
10 | <div class="alert alert-warning" *ngIf="key && !success"> | ||
11 | <span jhiTranslate="reset.finish.messages.info">Choose a new password</span> | ||
12 | </div> | ||
13 | |||
14 | <div class="alert alert-danger" *ngIf="error"> | ||
15 | <span jhiTranslate="reset.finish.messages.error">Your password couldn't be reset. Remember a password request is only valid for 24 hours.</span> | ||
16 | </div> | ||
17 | |||
18 | <div class="alert alert-success" *ngIf="success"> | ||
19 | <span jhiTranslate="reset.finish.messages.success"><strong>Your password has been reset.</strong> Please </span> | ||
20 | <a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a>. | ||
21 | </div> | ||
22 | |||
23 | <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch"> | ||
24 | The password and its confirmation do not match! | ||
25 | </div> | ||
26 | |||
27 | <div *ngIf="key && !success"> | ||
28 | <form name="form" role="form" (ngSubmit)="finishReset()" [formGroup]="passwordForm"> | ||
29 | <div class="form-group"> | ||
30 | <label class="form-control-label" for="newPassword" jhiTranslate="global.form.newpassword.label">New password</label> | ||
31 | <input type="password" class="form-control" id="newPassword" name="newPassword" | ||
32 | placeholder="{{ 'global.form.newpassword.placeholder' | translate }}" | ||
33 | formControlName="newPassword" #newPassword> | ||
34 | |||
35 | <div *ngIf="passwordForm.get('newPassword')!.invalid && (passwordForm.get('newPassword')!.dirty || passwordForm.get('newPassword')!.touched)"> | ||
36 | <small class="form-text text-danger" | ||
37 | *ngIf="passwordForm.get('newPassword')?.errors?.required" | ||
38 | jhiTranslate="global.messages.validate.newpassword.required"> | ||
39 | Your password is required. | ||
40 | </small> | ||
41 | |||
42 | <small class="form-text text-danger" | ||
43 | *ngIf="passwordForm.get('newPassword')?.errors?.minlength" | ||
44 | jhiTranslate="global.messages.validate.newpassword.minlength"> | ||
45 | Your password is required to be at least 4 characters. | ||
46 | </small> | ||
47 | |||
48 | <small class="form-text text-danger" | ||
49 | *ngIf="passwordForm.get('newPassword')?.errors?.maxlength" | ||
50 | jhiTranslate="global.messages.validate.newpassword.maxlength"> | ||
51 | Your password cannot be longer than 50 characters. | ||
52 | </small> | ||
53 | </div> | ||
54 | |||
55 | <auth-password-strength-bar [passwordToCheck]="passwordForm.get('newPassword')!.value"></auth-password-strength-bar> | ||
56 | </div> | ||
57 | |||
58 | <div class="form-group"> | ||
59 | <label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword.label">New password confirmation</label> | ||
60 | <input type="password" class="form-control" id="confirmPassword" name="confirmPassword" | ||
61 | placeholder="{{ 'global.form.confirmpassword.placeholder' | translate }}" | ||
62 | formControlName="confirmPassword"> | ||
63 | |||
64 | <div *ngIf="passwordForm.get('confirmPassword')!.invalid && (passwordForm.get('confirmPassword')!.dirty || passwordForm.get('confirmPassword')!.touched)"> | ||
65 | <small class="form-text text-danger" | ||
66 | *ngIf="passwordForm.get('confirmPassword')?.errors?.required" | ||
67 | jhiTranslate="global.messages.validate.confirmpassword.required"> | ||
68 | Your password confirmation is required. | ||
69 | </small> | ||
70 | |||
71 | <small class="form-text text-danger" | ||
72 | *ngIf="passwordForm.get('confirmPassword')?.errors?.minlength" | ||
73 | jhiTranslate="global.messages.validate.confirmpassword.minlength"> | ||
74 | Your password confirmation is required to be at least 4 characters. | ||
75 | </small> | ||
76 | |||
77 | <small class="form-text text-danger" | ||
78 | *ngIf="passwordForm.get('confirmPassword')?.errors?.maxlength" | ||
79 | jhiTranslate="global.messages.validate.confirmpassword.maxlength"> | ||
80 | Your password confirmation cannot be longer than 50 characters. | ||
81 | </small> | ||
82 | </div> | ||
83 | </div> | ||
84 | |||
85 | <button type="submit" [disabled]="passwordForm.invalid" class="btn btn-primary" jhiTranslate="reset.finish.form.button">Reset Password</button> | ||
86 | </form> | ||
87 | </div> | ||
88 | </div> | ||
89 | </div> | ||
90 | </div> |
File src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.ts added (mode: 100644) (index 0000000..11f940c) | |||
1 | import { Component, OnInit, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; | ||
2 | import { FormBuilder, Validators } from '@angular/forms'; | ||
3 | import { ActivatedRoute } from '@angular/router'; | ||
4 | |||
5 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
6 | import { PasswordResetFinishService } from './password-reset-finish.service'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-password-reset-finish', | ||
10 | templateUrl: './password-reset-finish.component.html' | ||
11 | }) | ||
12 | export class PasswordResetFinishComponent implements OnInit, AfterViewInit { | ||
13 | @ViewChild('newPassword', { static: false }) | ||
14 | newPassword?: ElementRef; | ||
15 | |||
16 | initialized = false; | ||
17 | doNotMatch = false; | ||
18 | error = false; | ||
19 | success = false; | ||
20 | key = ''; | ||
21 | |||
22 | passwordForm = this.fb.group({ | ||
23 | newPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]], | ||
24 | confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]] | ||
25 | }); | ||
26 | |||
27 | constructor( | ||
28 | private passwordResetFinishService: PasswordResetFinishService, | ||
29 | private loginModalService: LoginModalService, | ||
30 | private route: ActivatedRoute, | ||
31 | private fb: FormBuilder | ||
32 | ) {} | ||
33 | |||
34 | ngOnInit(): void { | ||
35 | this.route.queryParams.subscribe(params => { | ||
36 | if (params['key']) { | ||
37 | this.key = params['key']; | ||
38 | } | ||
39 | this.initialized = true; | ||
40 | }); | ||
41 | } | ||
42 | |||
43 | ngAfterViewInit(): void { | ||
44 | if (this.newPassword) { | ||
45 | this.newPassword.nativeElement.focus(); | ||
46 | } | ||
47 | } | ||
48 | |||
49 | finishReset(): void { | ||
50 | this.doNotMatch = false; | ||
51 | this.error = false; | ||
52 | |||
53 | const newPassword = this.passwordForm.get(['newPassword'])!.value; | ||
54 | const confirmPassword = this.passwordForm.get(['confirmPassword'])!.value; | ||
55 | |||
56 | if (newPassword !== confirmPassword) { | ||
57 | this.doNotMatch = true; | ||
58 | } else { | ||
59 | this.passwordResetFinishService.save(this.key, newPassword).subscribe( | ||
60 | () => (this.success = true), | ||
61 | () => (this.error = true) | ||
62 | ); | ||
63 | } | ||
64 | } | ||
65 | |||
66 | login(): void { | ||
67 | this.loginModalService.open(); | ||
68 | } | ||
69 | } |
File src/main/webapp/app/account/password-reset/finish/password-reset-finish.route.ts added (mode: 100644) (index 0000000..0cff2b0) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { PasswordResetFinishComponent } from './password-reset-finish.component'; | ||
4 | |||
5 | export const passwordResetFinishRoute: Route = { | ||
6 | path: 'reset/finish', | ||
7 | component: PasswordResetFinishComponent, | ||
8 | data: { | ||
9 | authorities: [], | ||
10 | pageTitle: 'global.menu.account.password' | ||
11 | } | ||
12 | }; |
File src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.ts added (mode: 100644) (index 0000000..2473629) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | @Injectable({ providedIn: 'root' }) | ||
8 | export class PasswordResetFinishService { | ||
9 | constructor(private http: HttpClient) {} | ||
10 | |||
11 | save(key: string, newPassword: string): Observable<{}> { | ||
12 | return this.http.post(SERVER_API_URL + 'api/account/reset-password/finish', { key, newPassword }); | ||
13 | } | ||
14 | } |
File src/main/webapp/app/account/password-reset/init/password-reset-init.component.html added (mode: 100644) (index 0000000..8396afa) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-8"> | ||
4 | <h1 jhiTranslate="reset.request.title">Reset your password</h1> | ||
5 | |||
6 | <auth-alert-error></auth-alert-error> | ||
7 | |||
8 | <div class="alert alert-warning" *ngIf="!success"> | ||
9 | <span jhiTranslate="reset.request.messages.info">Enter the email address you used to register.</span> | ||
10 | </div> | ||
11 | |||
12 | <div class="alert alert-success" *ngIf="success"> | ||
13 | <span jhiTranslate="reset.request.messages.success">Check your emails for details on how to reset your password.</span> | ||
14 | </div> | ||
15 | |||
16 | <form *ngIf="!success" name="form" role="form" (ngSubmit)="requestReset()" [formGroup]="resetRequestForm"> | ||
17 | <div class="form-group"> | ||
18 | <label class="form-control-label" for="email" jhiTranslate="global.form.email.label">Email</label> | ||
19 | <input type="email" class="form-control" id="email" name="email" placeholder="{{ 'global.form.email.placeholder' | translate }}" | ||
20 | formControlName="email" #email> | ||
21 | |||
22 | <div *ngIf="resetRequestForm.get('email')!.invalid && (resetRequestForm.get('email')!.dirty || resetRequestForm.get('email')!.touched)"> | ||
23 | <small class="form-text text-danger" | ||
24 | *ngIf="resetRequestForm.get('email')?.errors?.required" | ||
25 | jhiTranslate="global.messages.validate.email.required"> | ||
26 | Your email is required. | ||
27 | </small> | ||
28 | |||
29 | <small class="form-text text-danger" | ||
30 | *ngIf="resetRequestForm.get('email')?.errors?.email" | ||
31 | jhiTranslate="global.messages.validate.email.invalid"> | ||
32 | Your email is invalid. | ||
33 | </small> | ||
34 | |||
35 | <small class="form-text text-danger" | ||
36 | *ngIf="resetRequestForm.get('email')?.errors?.minlength" | ||
37 | jhiTranslate="global.messages.validate.email.minlength"> | ||
38 | Your email is required to be at least 5 characters. | ||
39 | </small> | ||
40 | |||
41 | <small class="form-text text-danger" | ||
42 | *ngIf="resetRequestForm.get('email')?.errors?.maxlength" | ||
43 | jhiTranslate="global.messages.validate.email.maxlength"> | ||
44 | Your email cannot be longer than 100 characters. | ||
45 | </small> | ||
46 | </div> | ||
47 | </div> | ||
48 | |||
49 | <button type="submit" [disabled]="resetRequestForm.invalid" class="btn btn-primary" jhiTranslate="reset.request.form.button">Reset</button> | ||
50 | </form> | ||
51 | </div> | ||
52 | </div> | ||
53 | </div> |
File src/main/webapp/app/account/password-reset/init/password-reset-init.component.ts added (mode: 100644) (index 0000000..700ad27) | |||
1 | import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; | ||
2 | import { FormBuilder, Validators } from '@angular/forms'; | ||
3 | |||
4 | import { PasswordResetInitService } from './password-reset-init.service'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-password-reset-init', | ||
8 | templateUrl: './password-reset-init.component.html' | ||
9 | }) | ||
10 | export class PasswordResetInitComponent implements AfterViewInit { | ||
11 | @ViewChild('email', { static: false }) | ||
12 | email?: ElementRef; | ||
13 | |||
14 | success = false; | ||
15 | resetRequestForm = this.fb.group({ | ||
16 | email: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(254), Validators.email]] | ||
17 | }); | ||
18 | |||
19 | constructor(private passwordResetInitService: PasswordResetInitService, private fb: FormBuilder) {} | ||
20 | |||
21 | ngAfterViewInit(): void { | ||
22 | if (this.email) { | ||
23 | this.email.nativeElement.focus(); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | requestReset(): void { | ||
28 | this.passwordResetInitService.save(this.resetRequestForm.get(['email'])!.value).subscribe(() => (this.success = true)); | ||
29 | } | ||
30 | } |
File src/main/webapp/app/account/password-reset/init/password-reset-init.route.ts added (mode: 100644) (index 0000000..887c77b) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { PasswordResetInitComponent } from './password-reset-init.component'; | ||
4 | |||
5 | export const passwordResetInitRoute: Route = { | ||
6 | path: 'reset/request', | ||
7 | component: PasswordResetInitComponent, | ||
8 | data: { | ||
9 | authorities: [], | ||
10 | pageTitle: 'global.menu.account.password' | ||
11 | } | ||
12 | }; |
File src/main/webapp/app/account/password-reset/init/password-reset-init.service.ts added (mode: 100644) (index 0000000..368500c) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | @Injectable({ providedIn: 'root' }) | ||
8 | export class PasswordResetInitService { | ||
9 | constructor(private http: HttpClient) {} | ||
10 | |||
11 | save(mail: string): Observable<{}> { | ||
12 | return this.http.post(SERVER_API_URL + 'api/account/reset-password/init', mail); | ||
13 | } | ||
14 | } |
File src/main/webapp/app/account/password/password-strength-bar.component.ts added (mode: 100644) (index 0000000..4e9b236) | |||
1 | import { Component, ElementRef, Input, Renderer2 } from '@angular/core'; | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'auth-password-strength-bar', | ||
5 | template: ` | ||
6 | <div id="strength"> | ||
7 | <small jhiTranslate="global.messages.validate.newpassword.strength">Password strength:</small> | ||
8 | <ul id="strengthBar"> | ||
9 | <li class="point"></li> | ||
10 | <li class="point"></li> | ||
11 | <li class="point"></li> | ||
12 | <li class="point"></li> | ||
13 | <li class="point"></li> | ||
14 | </ul> | ||
15 | </div> | ||
16 | `, | ||
17 | styleUrls: ['password-strength-bar.scss'] | ||
18 | }) | ||
19 | export class PasswordStrengthBarComponent { | ||
20 | colors = ['#F00', '#F90', '#FF0', '#9F0', '#0F0']; | ||
21 | |||
22 | constructor(private renderer: Renderer2, private elementRef: ElementRef) {} | ||
23 | |||
24 | measureStrength(p: string): number { | ||
25 | let force = 0; | ||
26 | const regex = /[$-/:-?{-~!"^_`[\]]/g; // " | ||
27 | const lowerLetters = /[a-z]+/.test(p); | ||
28 | const upperLetters = /[A-Z]+/.test(p); | ||
29 | const numbers = /[0-9]+/.test(p); | ||
30 | const symbols = regex.test(p); | ||
31 | |||
32 | const flags = [lowerLetters, upperLetters, numbers, symbols]; | ||
33 | const passedMatches = flags.filter((isMatchedFlag: boolean) => { | ||
34 | return isMatchedFlag === true; | ||
35 | }).length; | ||
36 | |||
37 | force += 2 * p.length + (p.length >= 10 ? 1 : 0); | ||
38 | force += passedMatches * 10; | ||
39 | |||
40 | // penalty (short password) | ||
41 | force = p.length <= 6 ? Math.min(force, 10) : force; | ||
42 | |||
43 | // penalty (poor variety of characters) | ||
44 | force = passedMatches === 1 ? Math.min(force, 10) : force; | ||
45 | force = passedMatches === 2 ? Math.min(force, 20) : force; | ||
46 | force = passedMatches === 3 ? Math.min(force, 40) : force; | ||
47 | |||
48 | return force; | ||
49 | } | ||
50 | |||
51 | getColor(s: number): { idx: number; color: string } { | ||
52 | let idx = 0; | ||
53 | if (s <= 10) { | ||
54 | idx = 0; | ||
55 | } else if (s <= 20) { | ||
56 | idx = 1; | ||
57 | } else if (s <= 30) { | ||
58 | idx = 2; | ||
59 | } else if (s <= 40) { | ||
60 | idx = 3; | ||
61 | } else { | ||
62 | idx = 4; | ||
63 | } | ||
64 | return { idx: idx + 1, color: this.colors[idx] }; | ||
65 | } | ||
66 | |||
67 | @Input() | ||
68 | set passwordToCheck(password: string) { | ||
69 | if (password) { | ||
70 | const c = this.getColor(this.measureStrength(password)); | ||
71 | const element = this.elementRef.nativeElement; | ||
72 | if (element.className) { | ||
73 | this.renderer.removeClass(element, element.className); | ||
74 | } | ||
75 | const lis = element.getElementsByTagName('li'); | ||
76 | for (let i = 0; i < lis.length; i++) { | ||
77 | if (i < c.idx) { | ||
78 | this.renderer.setStyle(lis[i], 'backgroundColor', c.color); | ||
79 | } else { | ||
80 | this.renderer.setStyle(lis[i], 'backgroundColor', '#DDD'); | ||
81 | } | ||
82 | } | ||
83 | } | ||
84 | } | ||
85 | } |
File src/main/webapp/app/account/password/password-strength-bar.scss added (mode: 100644) (index 0000000..67ce468) | |||
1 | /* ========================================================================== | ||
2 | start Password strength bar style | ||
3 | ========================================================================== */ | ||
4 | ul#strength { | ||
5 | display: inline; | ||
6 | list-style: none; | ||
7 | margin: 0; | ||
8 | margin-left: 15px; | ||
9 | padding: 0; | ||
10 | vertical-align: 2px; | ||
11 | } | ||
12 | |||
13 | .point { | ||
14 | background: #ddd; | ||
15 | border-radius: 2px; | ||
16 | display: inline-block; | ||
17 | height: 5px; | ||
18 | margin-right: 1px; | ||
19 | width: 20px; | ||
20 | &:last-child { | ||
21 | margin: 0 !important; | ||
22 | } | ||
23 | } |
File src/main/webapp/app/account/password/password.component.html added (mode: 100644) (index 0000000..8d7d425) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-8" *ngIf="account$ | async as account"> | ||
4 | <h2 jhiTranslate="password.title" [translateValues]="{ username: account.login }">Password for [<strong>{{ account.login }}</strong>]</h2> | ||
5 | |||
6 | <div class="alert alert-success" *ngIf="success" jhiTranslate="password.messages.success"> | ||
7 | <strong>Password changed!</strong> | ||
8 | </div> | ||
9 | |||
10 | <div class="alert alert-danger" *ngIf="error" jhiTranslate="password.messages.error"> | ||
11 | <strong>An error has occurred!</strong> The password could not be changed. | ||
12 | </div> | ||
13 | |||
14 | <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch"> | ||
15 | The password and its confirmation do not match! | ||
16 | </div> | ||
17 | |||
18 | <form name="form" role="form" (ngSubmit)="changePassword()" [formGroup]="passwordForm"> | ||
19 | <div class="form-group"> | ||
20 | <label class="form-control-label" for="currentPassword" jhiTranslate="global.form.currentpassword.label">Current password</label> | ||
21 | <input type="password" class="form-control" id="currentPassword" name="currentPassword" | ||
22 | placeholder="{{ 'global.form.currentpassword.placeholder' | translate }}" | ||
23 | formControlName="currentPassword"> | ||
24 | |||
25 | <div *ngIf="passwordForm.get('currentPassword')!.invalid && (passwordForm.get('currentPassword')!.dirty || passwordForm.get('currentPassword')!.touched)" > | ||
26 | <small class="form-text text-danger" | ||
27 | *ngIf="passwordForm.get('currentPassword')?.errors?.required" | ||
28 | jhiTranslate="global.messages.validate.newpassword.required"> | ||
29 | Your password is required. | ||
30 | </small> | ||
31 | </div> | ||
32 | </div> | ||
33 | |||
34 | <div class="form-group"> | ||
35 | <label class="form-control-label" for="newPassword" jhiTranslate="global.form.newpassword.label">New password</label> | ||
36 | <input type="password" class="form-control" id="newPassword" name="newPassword" | ||
37 | placeholder="{{ 'global.form.newpassword.placeholder' | translate }}" | ||
38 | formControlName="newPassword"> | ||
39 | |||
40 | <div *ngIf="passwordForm.get('newPassword')!.invalid && (passwordForm.get('newPassword')!.dirty || passwordForm.get('newPassword')!.touched)"> | ||
41 | <small class="form-text text-danger" | ||
42 | *ngIf="passwordForm.get('newPassword')?.errors?.required" | ||
43 | jhiTranslate="global.messages.validate.newpassword.required"> | ||
44 | Your password is required. | ||
45 | </small> | ||
46 | |||
47 | <small class="form-text text-danger" | ||
48 | *ngIf="passwordForm.get('newPassword')?.errors?.minlength" | ||
49 | jhiTranslate="global.messages.validate.newpassword.minlength"> | ||
50 | Your password is required to be at least 4 characters. | ||
51 | </small> | ||
52 | |||
53 | <small class="form-text text-danger" | ||
54 | *ngIf="passwordForm.get('newPassword')?.errors?.maxlength" | ||
55 | jhiTranslate="global.messages.validate.newpassword.maxlength"> | ||
56 | Your password cannot be longer than 50 characters. | ||
57 | </small> | ||
58 | </div> | ||
59 | |||
60 | <auth-password-strength-bar [passwordToCheck]="passwordForm.get('newPassword')!.value"></auth-password-strength-bar> | ||
61 | </div> | ||
62 | |||
63 | <div class="form-group"> | ||
64 | <label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword.label">New password confirmation</label> | ||
65 | <input type="password" class="form-control" id="confirmPassword" name="confirmPassword" | ||
66 | placeholder="{{ 'global.form.confirmpassword.placeholder' | translate }}" | ||
67 | formControlName="confirmPassword"> | ||
68 | |||
69 | <div *ngIf="passwordForm.get('confirmPassword')!.invalid && (passwordForm.get('confirmPassword')!.dirty || passwordForm.get('confirmPassword')!.touched)"> | ||
70 | <small class="form-text text-danger" | ||
71 | *ngIf="passwordForm.get('confirmPassword')?.errors?.required" | ||
72 | jhiTranslate="global.messages.validate.confirmpassword.required"> | ||
73 | Your confirmation password is required. | ||
74 | </small> | ||
75 | |||
76 | <small class="form-text text-danger" | ||
77 | *ngIf="passwordForm.get('confirmPassword')?.errors?.minlength" | ||
78 | jhiTranslate="global.messages.validate.confirmpassword.minlength"> | ||
79 | Your confirmation password is required to be at least 4 characters. | ||
80 | </small> | ||
81 | |||
82 | <small class="form-text text-danger" | ||
83 | *ngIf="passwordForm.get('confirmPassword')?.errors?.maxlength" | ||
84 | jhiTranslate="global.messages.validate.confirmpassword.maxlength"> | ||
85 | Your confirmation password cannot be longer than 50 characters. | ||
86 | </small> | ||
87 | </div> | ||
88 | </div> | ||
89 | |||
90 | <button type="submit" [disabled]="passwordForm.invalid" class="btn btn-primary" jhiTranslate="password.form.button">Save</button> | ||
91 | </form> | ||
92 | </div> | ||
93 | </div> | ||
94 | </div> |
File src/main/webapp/app/account/password/password.component.ts added (mode: 100644) (index 0000000..6fabe93) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, Validators } from '@angular/forms'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { AccountService } from 'app/core/auth/account.service'; | ||
6 | import { Account } from 'app/core/user/account.model'; | ||
7 | import { PasswordService } from './password.service'; | ||
8 | |||
9 | @Component({ | ||
10 | selector: 'auth-password', | ||
11 | templateUrl: './password.component.html' | ||
12 | }) | ||
13 | export class PasswordComponent implements OnInit { | ||
14 | doNotMatch = false; | ||
15 | error = false; | ||
16 | success = false; | ||
17 | account$?: Observable<Account | null>; | ||
18 | passwordForm = this.fb.group({ | ||
19 | currentPassword: ['', [Validators.required]], | ||
20 | newPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]], | ||
21 | confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]] | ||
22 | }); | ||
23 | |||
24 | constructor(private passwordService: PasswordService, private accountService: AccountService, private fb: FormBuilder) {} | ||
25 | |||
26 | ngOnInit(): void { | ||
27 | this.account$ = this.accountService.identity(); | ||
28 | } | ||
29 | |||
30 | changePassword(): void { | ||
31 | this.error = false; | ||
32 | this.success = false; | ||
33 | this.doNotMatch = false; | ||
34 | |||
35 | const newPassword = this.passwordForm.get(['newPassword'])!.value; | ||
36 | if (newPassword !== this.passwordForm.get(['confirmPassword'])!.value) { | ||
37 | this.doNotMatch = true; | ||
38 | } else { | ||
39 | this.passwordService.save(newPassword, this.passwordForm.get(['currentPassword'])!.value).subscribe( | ||
40 | () => (this.success = true), | ||
41 | () => (this.error = true) | ||
42 | ); | ||
43 | } | ||
44 | } | ||
45 | } |
File src/main/webapp/app/account/password/password.route.ts added (mode: 100644) (index 0000000..ab3b626) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; | ||
4 | import { PasswordComponent } from './password.component'; | ||
5 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
6 | |||
7 | export const passwordRoute: Route = { | ||
8 | path: 'password', | ||
9 | component: PasswordComponent, | ||
10 | data: { | ||
11 | authorities: [Authority.USER], | ||
12 | pageTitle: 'global.menu.account.password' | ||
13 | }, | ||
14 | canActivate: [UserRouteAccessService] | ||
15 | }; |
File src/main/webapp/app/account/password/password.service.ts added (mode: 100644) (index 0000000..13017f8) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | @Injectable({ providedIn: 'root' }) | ||
8 | export class PasswordService { | ||
9 | constructor(private http: HttpClient) {} | ||
10 | |||
11 | save(newPassword: string, currentPassword: string): Observable<{}> { | ||
12 | return this.http.post(SERVER_API_URL + 'api/account/change-password', { currentPassword, newPassword }); | ||
13 | } | ||
14 | } |
File src/main/webapp/app/account/register/register.component.html added (mode: 100644) (index 0000000..115cad5) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-8"> | ||
4 | <h1 jhiTranslate="register.title">Registration</h1> | ||
5 | |||
6 | <div class="alert alert-success" *ngIf="success" jhiTranslate="register.messages.success"> | ||
7 | <strong>Registration saved!</strong> Please check your email for confirmation. | ||
8 | </div> | ||
9 | |||
10 | <div class="alert alert-danger" *ngIf="error" jhiTranslate="register.messages.error.fail"> | ||
11 | <strong>Registration failed!</strong> Please try again later. | ||
12 | </div> | ||
13 | |||
14 | <div class="alert alert-danger" *ngIf="errorUserExists" jhiTranslate="register.messages.error.userexists"> | ||
15 | <strong>Login name already registered!</strong> Please choose another one. | ||
16 | </div> | ||
17 | |||
18 | <div class="alert alert-danger" *ngIf="errorEmailExists" jhiTranslate="register.messages.error.emailexists"> | ||
19 | <strong>Email is already in use!</strong> Please choose another one. | ||
20 | </div> | ||
21 | |||
22 | <div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch"> | ||
23 | The password and its confirmation do not match! | ||
24 | </div> | ||
25 | </div> | ||
26 | </div> | ||
27 | |||
28 | <div class="row justify-content-center"> | ||
29 | <div class="col-md-8"> | ||
30 | <form name="form" role="form" (ngSubmit)="register()" [formGroup]="registerForm" *ngIf="!success"> | ||
31 | <div class="form-group"> | ||
32 | <label class="form-control-label" for="login" jhiTranslate="global.form.username.label">Username</label> | ||
33 | <input type="text" class="form-control" id="login" name="login" placeholder="{{ 'global.form.username.placeholder' | translate }}" | ||
34 | formControlName="login" #login> | ||
35 | |||
36 | <div *ngIf="registerForm.get('login')!.invalid && (registerForm.get('login')!.dirty || registerForm.get('login')!.touched)"> | ||
37 | <small class="form-text text-danger" | ||
38 | *ngIf="registerForm.get('login')?.errors?.required" | ||
39 | jhiTranslate="register.messages.validate.login.required"> | ||
40 | Your username is required. | ||
41 | </small> | ||
42 | |||
43 | <small class="form-text text-danger" | ||
44 | *ngIf="registerForm.get('login')?.errors?.minlength" | ||
45 | jhiTranslate="register.messages.validate.login.minlength"> | ||
46 | Your username is required to be at least 1 character. | ||
47 | </small> | ||
48 | |||
49 | <small class="form-text text-danger" | ||
50 | *ngIf="registerForm.get('login')?.errors?.maxlength" | ||
51 | jhiTranslate="register.messages.validate.login.maxlength"> | ||
52 | Your username cannot be longer than 50 characters. | ||
53 | </small> | ||
54 | |||
55 | <small class="form-text text-danger" | ||
56 | *ngIf="registerForm.get('login')?.errors?.pattern" | ||
57 | jhiTranslate="register.messages.validate.login.pattern"> | ||
58 | Your username can only contain letters and digits. | ||
59 | </small> | ||
60 | </div> | ||
61 | </div> | ||
62 | |||
63 | <div class="form-group"> | ||
64 | <label class="form-control-label" for="email" jhiTranslate="global.form.email.label">Email</label> | ||
65 | <input type="email" class="form-control" id="email" name="email" placeholder="{{ 'global.form.email.placeholder' | translate }}" | ||
66 | formControlName="email"> | ||
67 | |||
68 | <div *ngIf="registerForm.get('email')!.invalid && (registerForm.get('email')!.dirty || registerForm.get('email')!.touched)"> | ||
69 | <small class="form-text text-danger" | ||
70 | *ngIf="registerForm.get('email')?.errors?.required" | ||
71 | jhiTranslate="global.messages.validate.email.required"> | ||
72 | Your email is required. | ||
73 | </small> | ||
74 | |||
75 | <small class="form-text text-danger" | ||
76 | *ngIf="registerForm.get('email')?.errors?.invalid" | ||
77 | jhiTranslate="global.messages.validate.email.invalid"> | ||
78 | Your email is invalid. | ||
79 | </small> | ||
80 | |||
81 | <small class="form-text text-danger" | ||
82 | *ngIf="registerForm.get('email')?.errors?.minlength" | ||
83 | jhiTranslate="global.messages.validate.email.minlength"> | ||
84 | Your email is required to be at least 5 characters. | ||
85 | </small> | ||
86 | |||
87 | <small class="form-text text-danger" | ||
88 | *ngIf="registerForm.get('email')?.errors?.maxlength" | ||
89 | jhiTranslate="global.messages.validate.email.maxlength"> | ||
90 | Your email cannot be longer than 100 characters. | ||
91 | </small> | ||
92 | </div> | ||
93 | </div> | ||
94 | |||
95 | <div class="form-group"> | ||
96 | <label class="form-control-label" for="password" jhiTranslate="global.form.newpassword.label">New password</label> | ||
97 | <input type="password" class="form-control" id="password" name="password" placeholder="{{ 'global.form.newpassword.placeholder' | translate }}" | ||
98 | formControlName="password"> | ||
99 | |||
100 | <div *ngIf="registerForm.get('password')!.invalid && (registerForm.get('password')!.dirty || registerForm.get('password')!.touched)"> | ||
101 | <small class="form-text text-danger" | ||
102 | *ngIf="registerForm.get('password')?.errors?.required" | ||
103 | jhiTranslate="global.messages.validate.newpassword.required"> | ||
104 | Your password is required. | ||
105 | </small> | ||
106 | |||
107 | <small class="form-text text-danger" | ||
108 | *ngIf="registerForm.get('password')?.errors?.minlength" | ||
109 | jhiTranslate="global.messages.validate.newpassword.minlength"> | ||
110 | Your password is required to be at least 4 characters. | ||
111 | </small> | ||
112 | |||
113 | <small class="form-text text-danger" | ||
114 | *ngIf="registerForm.get('password')?.errors?.maxlength" | ||
115 | jhiTranslate="global.messages.validate.newpassword.maxlength"> | ||
116 | Your password cannot be longer than 50 characters. | ||
117 | </small> | ||
118 | </div> | ||
119 | |||
120 | <auth-password-strength-bar [passwordToCheck]="registerForm.get('password')!.value"></auth-password-strength-bar> | ||
121 | </div> | ||
122 | |||
123 | <div class="form-group"> | ||
124 | <label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword.label">New password confirmation</label> | ||
125 | <input type="password" class="form-control" id="confirmPassword" name="confirmPassword" placeholder="{{ 'global.form.confirmpassword.placeholder' | translate }}" | ||
126 | formControlName="confirmPassword"> | ||
127 | |||
128 | <div *ngIf="registerForm.get('confirmPassword')!.invalid && (registerForm.get('confirmPassword')!.dirty || registerForm.get('confirmPassword')!.touched)"> | ||
129 | <small class="form-text text-danger" | ||
130 | *ngIf="registerForm.get('confirmPassword')?.errors?.required" | ||
131 | jhiTranslate="global.messages.validate.confirmpassword.required"> | ||
132 | Your confirmation password is required. | ||
133 | </small> | ||
134 | |||
135 | <small class="form-text text-danger" | ||
136 | *ngIf="registerForm.get('confirmPassword')?.errors?.minlength" | ||
137 | jhiTranslate="global.messages.validate.confirmpassword.minlength"> | ||
138 | Your confirmation password is required to be at least 4 characters. | ||
139 | </small> | ||
140 | |||
141 | <small class="form-text text-danger" | ||
142 | *ngIf="registerForm.get('confirmPassword')?.errors?.maxlength" | ||
143 | jhiTranslate="global.messages.validate.confirmpassword.maxlength"> | ||
144 | Your confirmation password cannot be longer than 50 characters. | ||
145 | </small> | ||
146 | </div> | ||
147 | </div> | ||
148 | |||
149 | <button type="submit" [disabled]="registerForm.invalid" class="btn btn-primary" jhiTranslate="register.form.button">Register</button> | ||
150 | </form> | ||
151 | |||
152 | <div class="mt-3 alert alert-warning"> | ||
153 | <span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span> | ||
154 | <a class="alert-link" (click)="openLogin()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span> | ||
155 | </div> | ||
156 | </div> | ||
157 | </div> | ||
158 | </div> |
File src/main/webapp/app/account/register/register.component.ts added (mode: 100644) (index 0000000..22f1808) | |||
1 | import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; | ||
2 | import { HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { FormBuilder, Validators } from '@angular/forms'; | ||
4 | import { JhiLanguageService } from 'ng-jhipster'; | ||
5 | |||
6 | import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/shared/constants/error.constants'; | ||
7 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
8 | import { RegisterService } from './register.service'; | ||
9 | |||
10 | @Component({ | ||
11 | selector: 'auth-register', | ||
12 | templateUrl: './register.component.html' | ||
13 | }) | ||
14 | export class RegisterComponent implements AfterViewInit { | ||
15 | @ViewChild('login', { static: false }) | ||
16 | login?: ElementRef; | ||
17 | |||
18 | doNotMatch = false; | ||
19 | error = false; | ||
20 | errorEmailExists = false; | ||
21 | errorUserExists = false; | ||
22 | success = false; | ||
23 | |||
24 | registerForm = this.fb.group({ | ||
25 | login: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(50), Validators.pattern('^[_.@A-Za-z0-9-]*$')]], | ||
26 | email: ['', [Validators.required, Validators.minLength(5), Validators.maxLength(254), Validators.email]], | ||
27 | password: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]], | ||
28 | confirmPassword: ['', [Validators.required, Validators.minLength(4), Validators.maxLength(50)]] | ||
29 | }); | ||
30 | |||
31 | constructor( | ||
32 | private languageService: JhiLanguageService, | ||
33 | private loginModalService: LoginModalService, | ||
34 | private registerService: RegisterService, | ||
35 | private fb: FormBuilder | ||
36 | ) {} | ||
37 | |||
38 | ngAfterViewInit(): void { | ||
39 | if (this.login) { | ||
40 | this.login.nativeElement.focus(); | ||
41 | } | ||
42 | } | ||
43 | |||
44 | register(): void { | ||
45 | this.doNotMatch = false; | ||
46 | this.error = false; | ||
47 | this.errorEmailExists = false; | ||
48 | this.errorUserExists = false; | ||
49 | |||
50 | const password = this.registerForm.get(['password'])!.value; | ||
51 | if (password !== this.registerForm.get(['confirmPassword'])!.value) { | ||
52 | this.doNotMatch = true; | ||
53 | } else { | ||
54 | const login = this.registerForm.get(['login'])!.value; | ||
55 | const email = this.registerForm.get(['email'])!.value; | ||
56 | this.registerService.save({ login, email, password, langKey: this.languageService.getCurrentLanguage() }).subscribe( | ||
57 | () => (this.success = true), | ||
58 | response => this.processError(response) | ||
59 | ); | ||
60 | } | ||
61 | } | ||
62 | |||
63 | openLogin(): void { | ||
64 | this.loginModalService.open(); | ||
65 | } | ||
66 | |||
67 | private processError(response: HttpErrorResponse): void { | ||
68 | if (response.status === 400 && response.error.type === LOGIN_ALREADY_USED_TYPE) { | ||
69 | this.errorUserExists = true; | ||
70 | } else if (response.status === 400 && response.error.type === EMAIL_ALREADY_USED_TYPE) { | ||
71 | this.errorEmailExists = true; | ||
72 | } else { | ||
73 | this.error = true; | ||
74 | } | ||
75 | } | ||
76 | } |
File src/main/webapp/app/account/register/register.route.ts added (mode: 100644) (index 0000000..f4ede9d) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { RegisterComponent } from './register.component'; | ||
4 | |||
5 | export const registerRoute: Route = { | ||
6 | path: 'register', | ||
7 | component: RegisterComponent, | ||
8 | data: { | ||
9 | authorities: [], | ||
10 | pageTitle: 'register.title' | ||
11 | } | ||
12 | }; |
File src/main/webapp/app/account/register/register.service.ts added (mode: 100644) (index 0000000..9a51915) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | import { IUser } from 'app/core/user/user.model'; | ||
7 | |||
8 | @Injectable({ providedIn: 'root' }) | ||
9 | export class RegisterService { | ||
10 | constructor(private http: HttpClient) {} | ||
11 | |||
12 | save(account: IUser): Observable<{}> { | ||
13 | return this.http.post(SERVER_API_URL + 'api/register', account); | ||
14 | } | ||
15 | } |
File src/main/webapp/app/account/settings/settings.component.html added (mode: 100644) (index 0000000..5077fb2) | |||
1 | <div> | ||
2 | <div class="row justify-content-center"> | ||
3 | <div class="col-md-8"> | ||
4 | <h2 jhiTranslate="settings.title" [translateValues]="{ username: account.login }" *ngIf="account">User settings for [<b>{{ account.login }}</b>]</h2> | ||
5 | |||
6 | <div class="alert alert-success" *ngIf="success" jhiTranslate="settings.messages.success"> | ||
7 | <strong>Settings saved!</strong> | ||
8 | </div> | ||
9 | |||
10 | <auth-alert-error></auth-alert-error> | ||
11 | |||
12 | <form name="form" role="form" (ngSubmit)="save()" [formGroup]="settingsForm" *ngIf="account" novalidate> | ||
13 | <div class="form-group"> | ||
14 | <label class="form-control-label" for="firstName" jhiTranslate="settings.form.firstname">First Name</label> | ||
15 | <input type="text" class="form-control" id="firstName" name="firstName" placeholder="{{ 'settings.form.firstname.placeholder' | translate }}" | ||
16 | formControlName="firstName"> | ||
17 | |||
18 | <div *ngIf="settingsForm.get('firstName')!.invalid && (settingsForm.get('firstName')!.dirty || settingsForm.get('firstName')!.touched)"> | ||
19 | <small class="form-text text-danger" | ||
20 | *ngIf="settingsForm.get('firstName')?.errors?.required" | ||
21 | jhiTranslate="settings.messages.validate.firstname.required"> | ||
22 | Your first name is required. | ||
23 | </small> | ||
24 | |||
25 | <small class="form-text text-danger" | ||
26 | *ngIf="settingsForm.get('firstName')?.errors?.minlength" | ||
27 | jhiTranslate="settings.messages.validate.firstname.minlength"> | ||
28 | Your first name is required to be at least 1 character. | ||
29 | </small> | ||
30 | |||
31 | <small class="form-text text-danger" | ||
32 | *ngIf="settingsForm.get('firstName')?.errors?.maxlength" | ||
33 | jhiTranslate="settings.messages.validate.firstname.maxlength"> | ||
34 | Your first name cannot be longer than 50 characters. | ||
35 | </small> | ||
36 | </div> | ||
37 | </div> | ||
38 | |||
39 | <div class="form-group"> | ||
40 | <label class="form-control-label" for="lastName" jhiTranslate="settings.form.lastname">Last Name</label> | ||
41 | <input type="text" class="form-control" id="lastName" name="lastName" placeholder="{{ 'settings.form.lastname.placeholder' | translate }}" | ||
42 | formControlName="lastName"> | ||
43 | |||
44 | <div *ngIf="settingsForm.get('lastName')!.invalid && (settingsForm.get('lastName')!.dirty || settingsForm.get('lastName')!.touched)"> | ||
45 | <small class="form-text text-danger" | ||
46 | *ngIf="settingsForm.get('lastName')?.errors?.required" | ||
47 | jhiTranslate="settings.messages.validate.lastname.required"> | ||
48 | Your last name is required. | ||
49 | </small> | ||
50 | |||
51 | <small class="form-text text-danger" | ||
52 | *ngIf="settingsForm.get('lastName')?.errors?.minlength" | ||
53 | jhiTranslate="settings.messages.validate.lastname.minlength"> | ||
54 | Your last name is required to be at least 1 character. | ||
55 | </small> | ||
56 | |||
57 | <small class="form-text text-danger" | ||
58 | *ngIf="settingsForm.get('lastName')?.errors?.maxlength" | ||
59 | jhiTranslate="settings.messages.validate.lastname.maxlength"> | ||
60 | Your last name cannot be longer than 50 characters. | ||
61 | </small> | ||
62 | </div> | ||
63 | </div> | ||
64 | |||
65 | <div class="form-group"> | ||
66 | <label class="form-control-label" for="email" jhiTranslate="global.form.email.label">Email</label> | ||
67 | <input type="email" class="form-control" id="email" name="email" placeholder="{{ 'global.form.email.placeholder' | translate }}" | ||
68 | formControlName="email"> | ||
69 | |||
70 | <div *ngIf="settingsForm.get('email')!.invalid && (settingsForm.get('email')!.dirty || settingsForm.get('email')!.touched)"> | ||
71 | <small class="form-text text-danger" | ||
72 | *ngIf="settingsForm.get('email')?.errors?.required" | ||
73 | jhiTranslate="global.messages.validate.email.required"> | ||
74 | Your email is required. | ||
75 | </small> | ||
76 | |||
77 | <small class="form-text text-danger" | ||
78 | *ngIf="settingsForm.get('email')?.errors?.email" | ||
79 | jhiTranslate="global.messages.validate.email.invalid"> | ||
80 | Your email is invalid. | ||
81 | </small> | ||
82 | |||
83 | <small class="form-text text-danger" | ||
84 | *ngIf="settingsForm.get('email')?.errors?.minlength" | ||
85 | jhiTranslate="global.messages.validate.email.minlength"> | ||
86 | Your email is required to be at least 5 characters. | ||
87 | </small> | ||
88 | |||
89 | <small class="form-text text-danger" | ||
90 | *ngIf="settingsForm.get('email')?.errors?.maxlength" | ||
91 | jhiTranslate="global.messages.validate.email.maxlength"> | ||
92 | Your email cannot be longer than 100 characters. | ||
93 | </small> | ||
94 | </div> | ||
95 | </div> | ||
96 | |||
97 | <div class="form-group" *ngIf="languages && languages.length > 0"> | ||
98 | <label for="langKey" jhiTranslate="settings.form.language">Language</label> | ||
99 | <select class="form-control" id="langKey" name="langKey" formControlName="langKey"> | ||
100 | <option *ngFor="let language of languages" [value]="language">{{ language | findLanguageFromKey }}</option> | ||
101 | </select> | ||
102 | </div> | ||
103 | |||
104 | <button type="submit" [disabled]="settingsForm.invalid" class="btn btn-primary" jhiTranslate="settings.form.button">Save</button> | ||
105 | </form> | ||
106 | </div> | ||
107 | </div> | ||
108 | </div> |
File src/main/webapp/app/account/settings/settings.component.ts added (mode: 100644) (index 0000000..fdec0c9) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, Validators } from '@angular/forms'; | ||
3 | import { JhiLanguageService } from 'ng-jhipster'; | ||
4 | |||
5 | import { AccountService } from 'app/core/auth/account.service'; | ||
6 | import { Account } from 'app/core/user/account.model'; | ||
7 | import { LANGUAGES } from 'app/core/language/language.constants'; | ||
8 | |||
9 | @Component({ | ||
10 | selector: 'auth-settings', | ||
11 | templateUrl: './settings.component.html' | ||
12 | }) | ||
13 | export class SettingsComponent implements OnInit { | ||
14 | account!: Account; | ||
15 | success = false; | ||
16 | languages = LANGUAGES; | ||
17 | settingsForm = this.fb.group({ | ||
18 | firstName: [undefined, [Validators.required, Validators.minLength(1), Validators.maxLength(50)]], | ||
19 | lastName: [undefined, [Validators.required, Validators.minLength(1), Validators.maxLength(50)]], | ||
20 | email: [undefined, [Validators.required, Validators.minLength(5), Validators.maxLength(254), Validators.email]], | ||
21 | langKey: [undefined] | ||
22 | }); | ||
23 | |||
24 | constructor(private accountService: AccountService, private fb: FormBuilder, private languageService: JhiLanguageService) {} | ||
25 | |||
26 | ngOnInit(): void { | ||
27 | this.accountService.identity().subscribe(account => { | ||
28 | if (account) { | ||
29 | this.settingsForm.patchValue({ | ||
30 | firstName: account.firstName, | ||
31 | lastName: account.lastName, | ||
32 | email: account.email, | ||
33 | langKey: account.langKey | ||
34 | }); | ||
35 | |||
36 | this.account = account; | ||
37 | } | ||
38 | }); | ||
39 | } | ||
40 | |||
41 | save(): void { | ||
42 | this.success = false; | ||
43 | |||
44 | this.account.firstName = this.settingsForm.get('firstName')!.value; | ||
45 | this.account.lastName = this.settingsForm.get('lastName')!.value; | ||
46 | this.account.email = this.settingsForm.get('email')!.value; | ||
47 | this.account.langKey = this.settingsForm.get('langKey')!.value; | ||
48 | |||
49 | this.accountService.save(this.account).subscribe(() => { | ||
50 | this.success = true; | ||
51 | |||
52 | this.accountService.authenticate(this.account); | ||
53 | |||
54 | if (this.account.langKey !== this.languageService.getCurrentLanguage()) { | ||
55 | this.languageService.changeLanguage(this.account.langKey); | ||
56 | } | ||
57 | }); | ||
58 | } | ||
59 | } |
File src/main/webapp/app/account/settings/settings.route.ts added (mode: 100644) (index 0000000..2deeda9) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; | ||
4 | import { SettingsComponent } from './settings.component'; | ||
5 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
6 | |||
7 | export const settingsRoute: Route = { | ||
8 | path: 'settings', | ||
9 | component: SettingsComponent, | ||
10 | data: { | ||
11 | authorities: [Authority.USER], | ||
12 | pageTitle: 'global.menu.account.settings' | ||
13 | }, | ||
14 | canActivate: [UserRouteAccessService] | ||
15 | }; |
File src/main/webapp/app/admin/admin-routing.module.ts added (mode: 100644) (index 0000000..f10ae68) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | /* jhipster-needle-add-admin-module-import - JHipster will add admin modules imports here */ | ||
4 | |||
5 | @NgModule({ | ||
6 | imports: [ | ||
7 | /* jhipster-needle-add-admin-module - JHipster will add admin modules here */ | ||
8 | RouterModule.forChild([ | ||
9 | { | ||
10 | path: 'user-management', | ||
11 | loadChildren: () => import('./user-management/user-management.module').then(m => m.UserManagementModule), | ||
12 | data: { | ||
13 | pageTitle: 'userManagement.home.title' | ||
14 | } | ||
15 | }, | ||
16 | { | ||
17 | path: 'audits', | ||
18 | loadChildren: () => import('./audits/audits.module').then(m => m.AuditsModule) | ||
19 | }, | ||
20 | { | ||
21 | path: 'configuration', | ||
22 | loadChildren: () => import('./configuration/configuration.module').then(m => m.ConfigurationModule) | ||
23 | }, | ||
24 | { | ||
25 | path: 'docs', | ||
26 | loadChildren: () => import('./docs/docs.module').then(m => m.DocsModule) | ||
27 | }, | ||
28 | { | ||
29 | path: 'health', | ||
30 | loadChildren: () => import('./health/health.module').then(m => m.HealthModule) | ||
31 | }, | ||
32 | { | ||
33 | path: 'logs', | ||
34 | loadChildren: () => import('./logs/logs.module').then(m => m.LogsModule) | ||
35 | }, | ||
36 | { | ||
37 | path: 'metrics', | ||
38 | loadChildren: () => import('./metrics/metrics.module').then(m => m.MetricsModule) | ||
39 | } | ||
40 | /* jhipster-needle-add-admin-route - JHipster will add admin routes here */ | ||
41 | ]) | ||
42 | ] | ||
43 | }) | ||
44 | export class AdminRoutingModule {} |
File src/main/webapp/app/admin/audits/audit-data.model.ts added (mode: 100644) (index 0000000..904d33d) | |||
1 | export class AuditData { | ||
2 | constructor(public remoteAddress: string, public sessionId: string) {} | ||
3 | } |
File src/main/webapp/app/admin/audits/audit.model.ts added (mode: 100644) (index 0000000..5c64107) | |||
1 | import { AuditData } from './audit-data.model'; | ||
2 | |||
3 | export class Audit { | ||
4 | constructor(public data: AuditData, public principal: string, public timestamp: string, public type: string) {} | ||
5 | } |
File src/main/webapp/app/admin/audits/audits.component.html added (mode: 100644) (index 0000000..3a15dae) | |||
1 | <div> | ||
2 | <h2 id="audits-page-heading" jhiTranslate="audits.title">Audits</h2> | ||
3 | |||
4 | <auth-alert-error></auth-alert-error> | ||
5 | |||
6 | <div class="row"> | ||
7 | <div class="col-md-5"> | ||
8 | <h4 jhiTranslate="audits.filter.title">Filter by date</h4> | ||
9 | |||
10 | <div class="input-group mb-3"> | ||
11 | <div class="input-group-prepend"> | ||
12 | <span class="input-group-text" jhiTranslate="audits.filter.from">from</span> | ||
13 | </div> | ||
14 | <input type="date" class="form-control" name="start" [(ngModel)]="fromDate" (ngModelChange)="transition()" required/> | ||
15 | |||
16 | <div class="input-group-append"> | ||
17 | <span class="input-group-text" jhiTranslate="audits.filter.to">To</span> | ||
18 | </div> | ||
19 | <input type="date" class="form-control" name="end" [(ngModel)]="toDate" (ngModelChange)="transition()" required/> | ||
20 | </div> | ||
21 | </div> | ||
22 | </div> | ||
23 | |||
24 | <div class="alert alert-warning" *ngIf="audits?.length === 0"> | ||
25 | <span jhiTranslate="audits.notFound">No audit found</span> | ||
26 | </div> | ||
27 | |||
28 | <div class="table-responsive" *ngIf="audits?.length > 0"> | ||
29 | <table class="table table-sm table-striped" aria-describedby="audits-page-heading"> | ||
30 | <thead [ngSwitch]="canLoad()"> | ||
31 | <tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="transition.bind(this)" *ngSwitchCase="true"> | ||
32 | <th scope="col" jhiSortBy="auditEventDate"><span jhiTranslate="audits.table.header.date">Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
33 | <th scope="col" jhiSortBy="principal"><span jhiTranslate="audits.table.header.principal">User</span> <fa-icon icon="sort"></fa-icon></th> | ||
34 | <th scope="col" jhiSortBy="auditEventType"><span jhiTranslate="audits.table.header.status">State</span> <fa-icon icon="sort"></fa-icon></th> | ||
35 | <th scope="col"><span jhiTranslate="audits.table.header.data">Extra data</span></th> | ||
36 | </tr> | ||
37 | <tr *ngSwitchCase="false"> | ||
38 | <th scope="col"><span jhiTranslate="audits.table.header.date">Date</span></th> | ||
39 | <th scope="col"><span jhiTranslate="audits.table.header.principal">User</span></th> | ||
40 | <th scope="col"><span jhiTranslate="audits.table.header.status">State</span></th> | ||
41 | <th scope="col"><span jhiTranslate="audits.table.header.data">Extra data</span></th> | ||
42 | </tr> | ||
43 | </thead> | ||
44 | <tbody> | ||
45 | <tr *ngFor="let audit of audits"> | ||
46 | <td><span>{{ audit.timestamp | date:'medium' }}</span></td> | ||
47 | <td><small>{{ audit.principal }}</small></td> | ||
48 | <td>{{ audit.type }}</td> | ||
49 | <td> | ||
50 | <span *ngIf="audit.data" ng-show="audit.data.message">{{ audit.data.message }}</span> | ||
51 | <span *ngIf="audit.data" ng-show="audit.data.remoteAddress"><span jhiTranslate="audits.table.data.remoteAddress">Remote Address</span> {{ audit.data.remoteAddress }}</span> | ||
52 | </td> | ||
53 | </tr> | ||
54 | </tbody> | ||
55 | </table> | ||
56 | </div> | ||
57 | |||
58 | <div *ngIf="audits?.length > 0"> | ||
59 | <div class="row justify-content-center"> | ||
60 | <jhi-item-count [page]="page" [total]="totalItems" [itemsPerPage]="itemsPerPage"></jhi-item-count> | ||
61 | </div> | ||
62 | |||
63 | <div class="row justify-content-center"> | ||
64 | <ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage(page)" [disabled]="!canLoad()"></ngb-pagination> | ||
65 | </div> | ||
66 | </div> | ||
67 | </div> |
File src/main/webapp/app/admin/audits/audits.component.ts added (mode: 100644) (index 0000000..3591209) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { HttpResponse, HttpHeaders } from '@angular/common/http'; | ||
3 | import { DatePipe } from '@angular/common'; | ||
4 | import { ActivatedRoute, Router } from '@angular/router'; | ||
5 | |||
6 | import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; | ||
7 | import { Audit } from './audit.model'; | ||
8 | import { AuditsService } from './audits.service'; | ||
9 | |||
10 | @Component({ | ||
11 | selector: 'auth-audit', | ||
12 | templateUrl: './audits.component.html' | ||
13 | }) | ||
14 | export class AuditsComponent implements OnInit { | ||
15 | audits?: Audit[]; | ||
16 | fromDate = ''; | ||
17 | itemsPerPage = ITEMS_PER_PAGE; | ||
18 | page!: number; | ||
19 | predicate!: string; | ||
20 | previousPage!: number; | ||
21 | ascending!: boolean; | ||
22 | toDate = ''; | ||
23 | totalItems = 0; | ||
24 | |||
25 | private dateFormat = 'yyyy-MM-dd'; | ||
26 | |||
27 | constructor( | ||
28 | private auditsService: AuditsService, | ||
29 | private activatedRoute: ActivatedRoute, | ||
30 | private datePipe: DatePipe, | ||
31 | private router: Router | ||
32 | ) {} | ||
33 | |||
34 | ngOnInit(): void { | ||
35 | this.toDate = this.today(); | ||
36 | this.fromDate = this.previousMonth(); | ||
37 | this.activatedRoute.data.subscribe(data => { | ||
38 | this.page = data['pagingParams'].page; | ||
39 | this.previousPage = data['pagingParams'].page; | ||
40 | this.ascending = data['pagingParams'].ascending; | ||
41 | this.predicate = data['pagingParams'].predicate; | ||
42 | this.loadData(); | ||
43 | }); | ||
44 | } | ||
45 | |||
46 | loadPage(page: number): void { | ||
47 | if (page !== this.previousPage) { | ||
48 | this.previousPage = page; | ||
49 | this.transition(); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | canLoad(): boolean { | ||
54 | return this.fromDate !== '' && this.toDate !== ''; | ||
55 | } | ||
56 | |||
57 | transition(): void { | ||
58 | if (this.canLoad()) { | ||
59 | this.router.navigate(['/admin/audits'], { | ||
60 | queryParams: { | ||
61 | page: this.page, | ||
62 | sort: this.predicate + ',' + (this.ascending ? 'asc' : 'desc') | ||
63 | } | ||
64 | }); | ||
65 | this.loadData(); | ||
66 | } | ||
67 | } | ||
68 | |||
69 | private previousMonth(): string { | ||
70 | let date = new Date(); | ||
71 | if (date.getMonth() === 0) { | ||
72 | date = new Date(date.getFullYear() - 1, 11, date.getDate()); | ||
73 | } else { | ||
74 | date = new Date(date.getFullYear(), date.getMonth() - 1, date.getDate()); | ||
75 | } | ||
76 | return this.datePipe.transform(date, this.dateFormat)!; | ||
77 | } | ||
78 | |||
79 | private today(): string { | ||
80 | // Today + 1 day - needed if the current day must be included | ||
81 | const date = new Date(); | ||
82 | date.setDate(date.getDate() + 1); | ||
83 | return this.datePipe.transform(date, this.dateFormat)!; | ||
84 | } | ||
85 | |||
86 | private loadData(): void { | ||
87 | this.auditsService | ||
88 | .query({ | ||
89 | page: this.page - 1, | ||
90 | size: this.itemsPerPage, | ||
91 | sort: this.sort(), | ||
92 | fromDate: this.fromDate, | ||
93 | toDate: this.toDate | ||
94 | }) | ||
95 | .subscribe((res: HttpResponse<Audit[]>) => this.onSuccess(res.body, res.headers)); | ||
96 | } | ||
97 | |||
98 | private sort(): string[] { | ||
99 | const result = [this.predicate + ',' + (this.ascending ? 'asc' : 'desc')]; | ||
100 | if (this.predicate !== 'id') { | ||
101 | result.push('id'); | ||
102 | } | ||
103 | return result; | ||
104 | } | ||
105 | |||
106 | private onSuccess(audits: Audit[] | null, headers: HttpHeaders): void { | ||
107 | this.totalItems = Number(headers.get('X-Total-Count')); | ||
108 | this.audits = audits || []; | ||
109 | } | ||
110 | } |
File src/main/webapp/app/admin/audits/audits.module.ts added (mode: 100644) (index 0000000..82fd28b) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { AuditsComponent } from './audits.component'; | ||
6 | |||
7 | import { auditsRoute } from './audits.route'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedModule, RouterModule.forChild([auditsRoute])], | ||
11 | declarations: [AuditsComponent] | ||
12 | }) | ||
13 | export class AuditsModule {} |
File src/main/webapp/app/admin/audits/audits.route.ts added (mode: 100644) (index 0000000..50576f5) | |||
1 | import { Route } from '@angular/router'; | ||
2 | import { JhiResolvePagingParams } from 'ng-jhipster'; | ||
3 | |||
4 | import { AuditsComponent } from './audits.component'; | ||
5 | |||
6 | export const auditsRoute: Route = { | ||
7 | path: '', | ||
8 | component: AuditsComponent, | ||
9 | resolve: { | ||
10 | pagingParams: JhiResolvePagingParams | ||
11 | }, | ||
12 | data: { | ||
13 | pageTitle: 'audits.title', | ||
14 | defaultSort: 'auditEventDate,desc' | ||
15 | } | ||
16 | }; |
File src/main/webapp/app/admin/audits/audits.service.ts added (mode: 100644) (index 0000000..d86bf47) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { createRequestOption, Pagination } from 'app/shared/util/request-util'; | ||
6 | import { SERVER_API_URL } from 'app/app.constants'; | ||
7 | import { Audit } from './audit.model'; | ||
8 | |||
9 | export interface AuditsQuery extends Pagination { | ||
10 | fromDate: string; | ||
11 | toDate: string; | ||
12 | } | ||
13 | |||
14 | @Injectable({ providedIn: 'root' }) | ||
15 | export class AuditsService { | ||
16 | constructor(private http: HttpClient) {} | ||
17 | |||
18 | query(req: AuditsQuery): Observable<HttpResponse<Audit[]>> { | ||
19 | const params: HttpParams = createRequestOption(req); | ||
20 | |||
21 | const requestURL = SERVER_API_URL + 'management/audits'; | ||
22 | |||
23 | return this.http.get<Audit[]>(requestURL, { | ||
24 | params, | ||
25 | observe: 'response' | ||
26 | }); | ||
27 | } | ||
28 | } |
File src/main/webapp/app/admin/configuration/configuration.component.html added (mode: 100644) (index 0000000..1002f7a) | |||
1 | <div *ngIf="allBeans"> | ||
2 | <h2 id="configuration-page-heading" jhiTranslate="configuration.title">Configuration</h2> | ||
3 | |||
4 | <span jhiTranslate="configuration.filter">Filter (by prefix)</span> <input type="text" [(ngModel)]="beansFilter" (ngModelChange)="filterAndSortBeans()" class="form-control"> | ||
5 | |||
6 | <h3 id="spring-configuration">Spring configuration</h3> | ||
7 | |||
8 | <table class="table table-striped table-bordered table-responsive d-table" aria-describedby="spring-configuration"> | ||
9 | <thead> | ||
10 | <tr jhiSort predicate="prefix" [(ascending)]="beansAscending" [callback]="filterAndSortBeans.bind(this)"> | ||
11 | <th jhiSortBy="prefix" scope="col" class="w-40"><span jhiTranslate="configuration.table.prefix">Prefix</span> <fa-icon icon="sort"></fa-icon></th> | ||
12 | <th scope="col" class="w-60"><span jhiTranslate="configuration.table.properties">Properties</span></th> | ||
13 | </tr> | ||
14 | </thead> | ||
15 | <tbody> | ||
16 | <tr *ngFor="let bean of beans"> | ||
17 | <td><span>{{ bean.prefix }}</span></td> | ||
18 | <td> | ||
19 | <div class="row" *ngFor="let property of bean.properties | keys"> | ||
20 | <div class="col-md-4">{{ property.key }}</div> | ||
21 | <div class="col-md-8"> | ||
22 | <span class="float-right badge-secondary break">{{ property.value | json }}</span> | ||
23 | </div> | ||
24 | </div> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </tbody> | ||
28 | </table> | ||
29 | |||
30 | <div *ngFor="let propertySource of propertySources; let i = index"> | ||
31 | <h4 [id]="'property-source-' + i"><span>{{ propertySource.name }}</span></h4> | ||
32 | |||
33 | <table class="table table-sm table-striped table-bordered table-responsive d-table" [attr.aria-describedby]="'property-source-' + i"><!-- //NOSONAR --> | ||
34 | <thead> | ||
35 | <tr> | ||
36 | <th scope="col" class="w-40">Property</th> | ||
37 | <th scope="col" class="w-60">Value</th> | ||
38 | </tr> | ||
39 | </thead> | ||
40 | <tbody> | ||
41 | <tr *ngFor="let property of propertySource.properties | keys"> | ||
42 | <td class="break">{{ property.key }}</td> | ||
43 | <td class="break"> | ||
44 | <span class="float-right badge-secondary break">{{ property.value.value }}</span> | ||
45 | </td> | ||
46 | </tr> | ||
47 | </tbody> | ||
48 | </table> | ||
49 | </div> | ||
50 | </div> |
File src/main/webapp/app/admin/configuration/configuration.component.ts added (mode: 100644) (index 0000000..0b07b39) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | |||
3 | import { ConfigurationService, Bean, PropertySource } from './configuration.service'; | ||
4 | |||
5 | @Component({ | ||
6 | selector: 'auth-configuration', | ||
7 | templateUrl: './configuration.component.html' | ||
8 | }) | ||
9 | export class ConfigurationComponent implements OnInit { | ||
10 | allBeans!: Bean[]; | ||
11 | beans: Bean[] = []; | ||
12 | beansFilter = ''; | ||
13 | beansAscending = true; | ||
14 | propertySources: PropertySource[] = []; | ||
15 | |||
16 | constructor(private configurationService: ConfigurationService) {} | ||
17 | |||
18 | ngOnInit(): void { | ||
19 | this.configurationService.getBeans().subscribe(beans => { | ||
20 | this.allBeans = beans; | ||
21 | this.filterAndSortBeans(); | ||
22 | }); | ||
23 | |||
24 | this.configurationService.getPropertySources().subscribe(propertySources => (this.propertySources = propertySources)); | ||
25 | } | ||
26 | |||
27 | filterAndSortBeans(): void { | ||
28 | this.beans = this.allBeans | ||
29 | .filter(bean => !this.beansFilter || bean.prefix.toLowerCase().includes(this.beansFilter.toLowerCase())) | ||
30 | .sort((a, b) => (a.prefix < b.prefix ? (this.beansAscending ? -1 : 1) : this.beansAscending ? 1 : -1)); | ||
31 | } | ||
32 | } |
File src/main/webapp/app/admin/configuration/configuration.module.ts added (mode: 100644) (index 0000000..2a02331) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { ConfigurationComponent } from './configuration.component'; | ||
6 | |||
7 | import { configurationRoute } from './configuration.route'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedModule, RouterModule.forChild([configurationRoute])], | ||
11 | declarations: [ConfigurationComponent] | ||
12 | }) | ||
13 | export class ConfigurationModule {} |
File src/main/webapp/app/admin/configuration/configuration.route.ts added (mode: 100644) (index 0000000..17238c9) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { ConfigurationComponent } from './configuration.component'; | ||
4 | |||
5 | export const configurationRoute: Route = { | ||
6 | path: '', | ||
7 | component: ConfigurationComponent, | ||
8 | data: { | ||
9 | pageTitle: 'configuration.title' | ||
10 | } | ||
11 | }; |
File src/main/webapp/app/admin/configuration/configuration.service.ts added (mode: 100644) (index 0000000..69ea43a) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | import { map } from 'rxjs/operators'; | ||
5 | |||
6 | import { SERVER_API_URL } from 'app/app.constants'; | ||
7 | |||
8 | export interface ConfigProps { | ||
9 | contexts: Contexts; | ||
10 | } | ||
11 | |||
12 | export interface Contexts { | ||
13 | [key: string]: Context; | ||
14 | } | ||
15 | |||
16 | export interface Context { | ||
17 | beans: Beans; | ||
18 | parentId?: any; | ||
19 | } | ||
20 | |||
21 | export interface Beans { | ||
22 | [key: string]: Bean; | ||
23 | } | ||
24 | |||
25 | export interface Bean { | ||
26 | prefix: string; | ||
27 | properties: any; | ||
28 | } | ||
29 | |||
30 | export interface Env { | ||
31 | activeProfiles?: string[]; | ||
32 | propertySources: PropertySource[]; | ||
33 | } | ||
34 | |||
35 | export interface PropertySource { | ||
36 | name: string; | ||
37 | properties: Properties; | ||
38 | } | ||
39 | |||
40 | export interface Properties { | ||
41 | [key: string]: Property; | ||
42 | } | ||
43 | |||
44 | export interface Property { | ||
45 | value: string; | ||
46 | origin?: string; | ||
47 | } | ||
48 | |||
49 | @Injectable({ providedIn: 'root' }) | ||
50 | export class ConfigurationService { | ||
51 | constructor(private http: HttpClient) {} | ||
52 | |||
53 | getBeans(): Observable<Bean[]> { | ||
54 | return this.http.get<ConfigProps>(SERVER_API_URL + 'management/configprops').pipe( | ||
55 | map(configProps => | ||
56 | Object.values( | ||
57 | Object.values(configProps.contexts) | ||
58 | .map(context => context.beans) | ||
59 | .reduce((allBeans: Beans, contextBeans: Beans) => ({ ...allBeans, ...contextBeans })) | ||
60 | ) | ||
61 | ) | ||
62 | ); | ||
63 | } | ||
64 | |||
65 | getPropertySources(): Observable<PropertySource[]> { | ||
66 | return this.http.get<Env>(SERVER_API_URL + 'management/env').pipe(map(env => env.propertySources)); | ||
67 | } | ||
68 | } |
File src/main/webapp/app/admin/docs/docs.component.html added (mode: 100644) (index 0000000..9d1600b) | |||
1 | <iframe src="swagger-ui/index.html" width="100%" height="900" seamless | ||
2 | target="_top" title="Swagger UI" class="border-0"></iframe> |
File src/main/webapp/app/admin/docs/docs.component.ts added (mode: 100644) (index 0000000..4b6d528) | |||
1 | import { Component } from '@angular/core'; | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'auth-docs', | ||
5 | templateUrl: './docs.component.html', | ||
6 | styleUrls: ['docs.scss'] | ||
7 | }) | ||
8 | export class DocsComponent {} |
File src/main/webapp/app/admin/docs/docs.module.ts added (mode: 100644) (index 0000000..dfb0bbc) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { DocsComponent } from './docs.component'; | ||
6 | |||
7 | import { docsRoute } from './docs.route'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedModule, RouterModule.forChild([docsRoute])], | ||
11 | declarations: [DocsComponent] | ||
12 | }) | ||
13 | export class DocsModule {} |
File src/main/webapp/app/admin/docs/docs.route.ts added (mode: 100644) (index 0000000..b2aead9) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { DocsComponent } from './docs.component'; | ||
4 | |||
5 | export const docsRoute: Route = { | ||
6 | path: '', | ||
7 | component: DocsComponent, | ||
8 | data: { | ||
9 | pageTitle: 'global.menu.admin.apidocs' | ||
10 | } | ||
11 | }; |
File src/main/webapp/app/admin/docs/docs.scss added (mode: 100644) (index 0000000..541c3d7) | |||
1 | @import '~bootstrap/scss/functions'; | ||
2 | @import '~bootstrap/scss/variables'; | ||
3 | |||
4 | iframe { | ||
5 | background: white; | ||
6 | } |
File src/main/webapp/app/admin/health/health-modal.component.html added (mode: 100644) (index 0000000..5556f47) | |||
1 | <div class="modal-header"> | ||
2 | <h4 class="modal-title" id="showHealthLabel" *ngIf="health"> | ||
3 | {{ 'health.indicator.' + health.key | translate }} | ||
4 | </h4> | ||
5 | |||
6 | <button aria-label="Close" data-dismiss="modal" class="close" type="button" (click)="dismiss()"> | ||
7 | <span aria-hidden="true">×</span> | ||
8 | </button> | ||
9 | </div> | ||
10 | |||
11 | <div class="modal-body pad"> | ||
12 | <div *ngIf="health"> | ||
13 | <h5 jhiTranslate="health.details.properties">Properties</h5> | ||
14 | |||
15 | <div class="table-responsive"> | ||
16 | <table class="table table-striped" aria-describedby="showHealthLabel"> | ||
17 | <thead> | ||
18 | <tr> | ||
19 | <th scope="col" class="text-left" jhiTranslate="health.details.name">Name</th> | ||
20 | <th scope="col" class="text-left" jhiTranslate="health.details.value">Value</th> | ||
21 | </tr> | ||
22 | </thead> | ||
23 | <tbody> | ||
24 | <tr *ngFor="let healthDetail of health.value.details | keys"> | ||
25 | <td class="text-left">{{ healthDetail.key }}</td> | ||
26 | <td class="text-left">{{ readableValue(healthDetail.value) }}</td> | ||
27 | </tr> | ||
28 | </tbody> | ||
29 | </table> | ||
30 | </div> | ||
31 | </div> | ||
32 | </div> | ||
33 | |||
34 | <div class="modal-footer"> | ||
35 | <button data-dismiss="modal" class="btn btn-secondary float-left" type="button" (click)="dismiss()">Done</button> | ||
36 | </div> |
File src/main/webapp/app/admin/health/health-modal.component.ts added (mode: 100644) (index 0000000..7655094) | |||
1 | import { Component } from '@angular/core'; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | |||
4 | import { HealthKey, HealthDetails } from './health.service'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-health-modal', | ||
8 | templateUrl: './health-modal.component.html' | ||
9 | }) | ||
10 | export class HealthModalComponent { | ||
11 | health?: { key: HealthKey; value: HealthDetails }; | ||
12 | |||
13 | constructor(public activeModal: NgbActiveModal) {} | ||
14 | |||
15 | readableValue(value: any): string { | ||
16 | if (this.health && this.health.key === 'diskSpace') { | ||
17 | // Should display storage space in an human readable unit | ||
18 | const val = value / 1073741824; | ||
19 | if (val > 1) { | ||
20 | // Value | ||
21 | return val.toFixed(2) + ' GB'; | ||
22 | } else { | ||
23 | return (value / 1048576).toFixed(2) + ' MB'; | ||
24 | } | ||
25 | } | ||
26 | |||
27 | if (typeof value === 'object') { | ||
28 | return JSON.stringify(value); | ||
29 | } else { | ||
30 | return value.toString(); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | dismiss(): void { | ||
35 | this.activeModal.dismiss(); | ||
36 | } | ||
37 | } |
File src/main/webapp/app/admin/health/health.component.html added (mode: 100644) (index 0000000..b686fcb) | |||
1 | <div> | ||
2 | <h2> | ||
3 | <span id="health-page-heading" jhiTranslate="health.title">Health Checks</span> | ||
4 | |||
5 | <button class="btn btn-primary float-right" (click)="refresh()"> | ||
6 | <fa-icon icon="sync"></fa-icon> <span jhiTranslate="health.refresh.button">Refresh</span> | ||
7 | </button> | ||
8 | </h2> | ||
9 | |||
10 | <div class="table-responsive"> | ||
11 | <table id="healthCheck" class="table table-striped" aria-describedby="health-page-heading"> | ||
12 | <thead> | ||
13 | <tr> | ||
14 | <th scope="col" jhiTranslate="health.table.service">Service Name</th> | ||
15 | <th scope="col" class="text-center" jhiTranslate="health.table.status">Status</th> | ||
16 | <th scope="col" class="text-center" jhiTranslate="health.details.details">Details</th> | ||
17 | </tr> | ||
18 | </thead> | ||
19 | <tbody *ngIf="health"> | ||
20 | <tr *ngFor="let componentHealth of health.components | keys"> | ||
21 | <td> | ||
22 | {{ 'health.indicator.' + componentHealth.key | translate }} | ||
23 | </td> | ||
24 | <td class="text-center"> | ||
25 | <span class="badge" [ngClass]="getBadgeClass(componentHealth.value.status)" jhiTranslate="{{ 'health.status.' + componentHealth.value.status }}"> | ||
26 | {{ componentHealth.value.status }} | ||
27 | </span> | ||
28 | </td> | ||
29 | <td class="text-center"> | ||
30 | <a class="hand" (click)="showHealth(componentHealth)" *ngIf="componentHealth.value.details"> | ||
31 | <fa-icon icon="eye"></fa-icon> | ||
32 | </a> | ||
33 | </td> | ||
34 | </tr> | ||
35 | </tbody> | ||
36 | </table> | ||
37 | </div> | ||
38 | </div> |
File src/main/webapp/app/admin/health/health.component.ts added (mode: 100644) (index 0000000..9c07604) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||
4 | |||
5 | import { HealthService, HealthStatus, Health, HealthKey, HealthDetails } from './health.service'; | ||
6 | import { HealthModalComponent } from './health-modal.component'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-health', | ||
10 | templateUrl: './health.component.html' | ||
11 | }) | ||
12 | export class HealthComponent implements OnInit { | ||
13 | health?: Health; | ||
14 | |||
15 | constructor(private modalService: NgbModal, private healthService: HealthService) {} | ||
16 | |||
17 | ngOnInit(): void { | ||
18 | this.refresh(); | ||
19 | } | ||
20 | |||
21 | getBadgeClass(statusState: HealthStatus): string { | ||
22 | if (statusState === 'UP') { | ||
23 | return 'badge-success'; | ||
24 | } else { | ||
25 | return 'badge-danger'; | ||
26 | } | ||
27 | } | ||
28 | |||
29 | refresh(): void { | ||
30 | this.healthService.checkHealth().subscribe( | ||
31 | health => (this.health = health), | ||
32 | (error: HttpErrorResponse) => { | ||
33 | if (error.status === 503) { | ||
34 | this.health = error.error; | ||
35 | } | ||
36 | } | ||
37 | ); | ||
38 | } | ||
39 | |||
40 | showHealth(health: { key: HealthKey; value: HealthDetails }): void { | ||
41 | const modalRef = this.modalService.open(HealthModalComponent); | ||
42 | modalRef.componentInstance.health = health; | ||
43 | } | ||
44 | } |
File src/main/webapp/app/admin/health/health.module.ts added (mode: 100644) (index 0000000..ab9a921) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { HealthComponent } from './health.component'; | ||
6 | import { HealthModalComponent } from './health-modal.component'; | ||
7 | |||
8 | import { healthRoute } from './health.route'; | ||
9 | |||
10 | @NgModule({ | ||
11 | imports: [HonlapSharedModule, RouterModule.forChild([healthRoute])], | ||
12 | declarations: [HealthComponent, HealthModalComponent], | ||
13 | entryComponents: [HealthModalComponent] | ||
14 | }) | ||
15 | export class HealthModule {} |
File src/main/webapp/app/admin/health/health.route.ts added (mode: 100644) (index 0000000..1055dcc) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { HealthComponent } from './health.component'; | ||
4 | |||
5 | export const healthRoute: Route = { | ||
6 | path: '', | ||
7 | component: HealthComponent, | ||
8 | data: { | ||
9 | pageTitle: 'health.title' | ||
10 | } | ||
11 | }; |
File src/main/webapp/app/admin/health/health.service.ts added (mode: 100644) (index 0000000..25005f6) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | export type HealthStatus = 'UP' | 'DOWN' | 'UNKNOWN' | 'OUT_OF_SERVICE'; | ||
8 | |||
9 | export type HealthKey = 'diskSpace' | 'mail' | 'ping' | 'db'; | ||
10 | |||
11 | export interface Health { | ||
12 | status: HealthStatus; | ||
13 | components: { | ||
14 | [key in HealthKey]?: HealthDetails; | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | export interface HealthDetails { | ||
19 | status: HealthStatus; | ||
20 | details: any; | ||
21 | } | ||
22 | |||
23 | @Injectable({ providedIn: 'root' }) | ||
24 | export class HealthService { | ||
25 | constructor(private http: HttpClient) {} | ||
26 | |||
27 | checkHealth(): Observable<Health> { | ||
28 | return this.http.get<Health>(SERVER_API_URL + 'management/health'); | ||
29 | } | ||
30 | } |
File src/main/webapp/app/admin/logs/log.model.ts added (mode: 100644) (index 0000000..83f2e15) | |||
1 | export type Level = 'TRACE' | 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'OFF'; | ||
2 | |||
3 | export interface Logger { | ||
4 | configuredLevel: Level | null; | ||
5 | effectiveLevel: Level; | ||
6 | } | ||
7 | |||
8 | export interface LoggersResponse { | ||
9 | levels: Level[]; | ||
10 | loggers: { [key: string]: Logger }; | ||
11 | } | ||
12 | |||
13 | export class Log { | ||
14 | constructor(public name: string, public level: Level) {} | ||
15 | } |
File src/main/webapp/app/admin/logs/logs.component.html added (mode: 100644) (index 0000000..b0473e3) | |||
1 | <div class="table-responsive" *ngIf="loggers"> | ||
2 | <h2 id="logs-page-heading" jhiTranslate="logs.title">Logs</h2> | ||
3 | |||
4 | <p jhiTranslate="logs.nbloggers" [translateValues]="{ total: loggers.length }">There are {{ loggers.length }} loggers.</p> | ||
5 | |||
6 | <span jhiTranslate="logs.filter">Filter</span> <input type="text" [(ngModel)]="filter" class="form-control"> | ||
7 | |||
8 | <table class="table table-sm table-striped table-bordered" aria-describedby="logs-page-heading"> | ||
9 | <thead> | ||
10 | <tr title="click to order"> | ||
11 | <th scope="col" (click)="orderProp = 'name'; reverse=!reverse"><span jhiTranslate="logs.table.name">Name</span></th> | ||
12 | <th scope="col" (click)="orderProp = 'level'; reverse=!reverse"><span jhiTranslate="logs.table.level">Level</span></th> | ||
13 | </tr> | ||
14 | </thead> | ||
15 | |||
16 | <tr *ngFor="let logger of (loggers | pureFilter:filter:'name' | orderBy:orderProp:reverse)"> | ||
17 | <td><small>{{ logger.name | slice:0:140 }}</small></td> | ||
18 | <td> | ||
19 | <button (click)="changeLevel(logger.name, 'TRACE')" [ngClass]="(logger.level=='TRACE') ? 'btn-primary' : 'btn-light'" class="btn btn-sm">TRACE</button> | ||
20 | <button (click)="changeLevel(logger.name, 'DEBUG')" [ngClass]="(logger.level=='DEBUG') ? 'btn-success' : 'btn-light'" class="btn btn-sm">DEBUG</button> | ||
21 | <button (click)="changeLevel(logger.name, 'INFO')" [ngClass]="(logger.level=='INFO') ? 'btn-info' : 'btn-light'" class="btn btn-sm">INFO</button> | ||
22 | <button (click)="changeLevel(logger.name, 'WARN')" [ngClass]="(logger.level=='WARN') ? 'btn-warning' : 'btn-light'" class="btn btn-sm">WARN</button> | ||
23 | <button (click)="changeLevel(logger.name, 'ERROR')" [ngClass]="(logger.level=='ERROR') ? 'btn-danger' : 'btn-light'" class="btn btn-sm">ERROR</button> | ||
24 | <button (click)="changeLevel(logger.name, 'OFF')" [ngClass]="(logger.level=='OFF') ? 'btn-secondary' : 'btn-light'" class="btn btn-sm">OFF</button> | ||
25 | </td> | ||
26 | </tr> | ||
27 | </table> | ||
28 | </div> |
File src/main/webapp/app/admin/logs/logs.component.ts added (mode: 100644) (index 0000000..c41dc22) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | |||
3 | import { Log, LoggersResponse, Logger, Level } from './log.model'; | ||
4 | import { LogsService } from './logs.service'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-logs', | ||
8 | templateUrl: './logs.component.html' | ||
9 | }) | ||
10 | export class LogsComponent implements OnInit { | ||
11 | loggers?: Log[]; | ||
12 | filter = ''; | ||
13 | orderProp = 'name'; | ||
14 | reverse = false; | ||
15 | |||
16 | constructor(private logsService: LogsService) {} | ||
17 | |||
18 | ngOnInit(): void { | ||
19 | this.findAndExtractLoggers(); | ||
20 | } | ||
21 | |||
22 | changeLevel(name: string, level: Level): void { | ||
23 | this.logsService.changeLevel(name, level).subscribe(() => this.findAndExtractLoggers()); | ||
24 | } | ||
25 | |||
26 | private findAndExtractLoggers(): void { | ||
27 | this.logsService | ||
28 | .findAll() | ||
29 | .subscribe( | ||
30 | (response: LoggersResponse) => | ||
31 | (this.loggers = Object.entries(response.loggers).map((logger: [string, Logger]) => new Log(logger[0], logger[1].effectiveLevel))) | ||
32 | ); | ||
33 | } | ||
34 | } |
File src/main/webapp/app/admin/logs/logs.module.ts added (mode: 100644) (index 0000000..6e519be) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { LogsComponent } from './logs.component'; | ||
6 | |||
7 | import { logsRoute } from './logs.route'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedModule, RouterModule.forChild([logsRoute])], | ||
11 | declarations: [LogsComponent] | ||
12 | }) | ||
13 | export class LogsModule {} |
File src/main/webapp/app/admin/logs/logs.route.ts added (mode: 100644) (index 0000000..d1cf024) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { LogsComponent } from './logs.component'; | ||
4 | |||
5 | export const logsRoute: Route = { | ||
6 | path: '', | ||
7 | component: LogsComponent, | ||
8 | data: { | ||
9 | pageTitle: 'logs.title' | ||
10 | } | ||
11 | }; |
File src/main/webapp/app/admin/logs/logs.service.ts added (mode: 100644) (index 0000000..dc9956d) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | import { LoggersResponse, Level } from './log.model'; | ||
7 | |||
8 | @Injectable({ providedIn: 'root' }) | ||
9 | export class LogsService { | ||
10 | constructor(private http: HttpClient) {} | ||
11 | |||
12 | changeLevel(name: string, configuredLevel: Level): Observable<{}> { | ||
13 | return this.http.post(SERVER_API_URL + 'management/loggers/' + name, { configuredLevel }); | ||
14 | } | ||
15 | |||
16 | findAll(): Observable<LoggersResponse> { | ||
17 | return this.http.get<LoggersResponse>(SERVER_API_URL + 'management/loggers'); | ||
18 | } | ||
19 | } |
File src/main/webapp/app/admin/metrics/metrics.component.html added (mode: 100644) (index 0000000..731a7a9) | |||
1 | <div> | ||
2 | <h2> | ||
3 | <span id="metrics-page-heading" jhiTranslate="metrics.title">Application Metrics</span> | ||
4 | |||
5 | <button class="btn btn-primary float-right" (click)="refresh()"> | ||
6 | <fa-icon icon="sync"></fa-icon> <span jhiTranslate="metrics.refresh.button">Refresh</span> | ||
7 | </button> | ||
8 | </h2> | ||
9 | |||
10 | <h3 jhiTranslate="metrics.jvm.title">JVM Metrics</h3> | ||
11 | |||
12 | <div class="row" *ngIf="metrics && !updatingMetrics"> | ||
13 | <jhi-jvm-memory | ||
14 | class="col-md-4" | ||
15 | [updating]="updatingMetrics" | ||
16 | [jvmMemoryMetrics]="metrics.jvm"> | ||
17 | </jhi-jvm-memory> | ||
18 | |||
19 | <jhi-jvm-threads | ||
20 | class="col-md-4" | ||
21 | [threadData]="threads"> | ||
22 | </jhi-jvm-threads> | ||
23 | |||
24 | <jhi-metrics-system | ||
25 | class="col-md-4" | ||
26 | [updating]="updatingMetrics" | ||
27 | [systemMetrics]="metrics.processMetrics"> | ||
28 | </jhi-metrics-system> | ||
29 | </div> | ||
30 | |||
31 | <div *ngIf="metrics && metricsKeyExists('garbageCollector')"> | ||
32 | <h3 jhiTranslate="metrics.jvm.gc.title">Garbage collector statistics</h3> | ||
33 | |||
34 | <jhi-metrics-garbagecollector | ||
35 | [updating]="updatingMetrics" | ||
36 | [garbageCollectorMetrics]="metrics.garbageCollector"> | ||
37 | </jhi-metrics-garbagecollector> | ||
38 | </div> | ||
39 | |||
40 | <div class="well well-lg" *ngIf="updatingMetrics" jhiTranslate="metrics.updating">Updating...</div> | ||
41 | |||
42 | <jhi-metrics-request | ||
43 | *ngIf="metrics && metricsKeyExists('http.server.requests')" | ||
44 | [updating]="updatingMetrics" | ||
45 | [requestMetrics]="metrics['http.server.requests']"> | ||
46 | </jhi-metrics-request> | ||
47 | |||
48 | <jhi-metrics-endpoints-requests | ||
49 | *ngIf="metrics && metricsKeyExists('services')" | ||
50 | [updating]="updatingMetrics" | ||
51 | [endpointsRequestsMetrics]="metrics.services"> | ||
52 | </jhi-metrics-endpoints-requests> | ||
53 | |||
54 | <jhi-metrics-cache | ||
55 | *ngIf="metrics && metricsKeyExists('cache')" | ||
56 | [updating]="updatingMetrics" | ||
57 | [cacheMetrics]="metrics.cache"> | ||
58 | </jhi-metrics-cache> | ||
59 | |||
60 | <jhi-metrics-datasource | ||
61 | *ngIf="metrics && metricsKeyExistsAndObjectNotEmpty('databases')" | ||
62 | [updating]="updatingMetrics" | ||
63 | [datasourceMetrics]="metrics.databases"> | ||
64 | </jhi-metrics-datasource> | ||
65 | </div> |
File src/main/webapp/app/admin/metrics/metrics.component.ts added (mode: 100644) (index 0000000..0c49b71) | |||
1 | import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core'; | ||
2 | import { flatMap } from 'rxjs/operators'; | ||
3 | |||
4 | import { MetricsService, Metrics, MetricsKey, ThreadDump, Thread } from './metrics.service'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-metrics', | ||
8 | templateUrl: './metrics.component.html', | ||
9 | changeDetection: ChangeDetectionStrategy.OnPush | ||
10 | }) | ||
11 | export class MetricsComponent implements OnInit { | ||
12 | metrics?: Metrics; | ||
13 | threads?: Thread[]; | ||
14 | updatingMetrics = true; | ||
15 | |||
16 | constructor(private metricsService: MetricsService, private changeDetector: ChangeDetectorRef) {} | ||
17 | |||
18 | ngOnInit(): void { | ||
19 | this.refresh(); | ||
20 | } | ||
21 | |||
22 | refresh(): void { | ||
23 | this.updatingMetrics = true; | ||
24 | this.metricsService | ||
25 | .getMetrics() | ||
26 | .pipe( | ||
27 | flatMap( | ||
28 | () => this.metricsService.threadDump(), | ||
29 | (metrics: Metrics, threadDump: ThreadDump) => { | ||
30 | this.metrics = metrics; | ||
31 | this.threads = threadDump.threads; | ||
32 | this.updatingMetrics = false; | ||
33 | this.changeDetector.detectChanges(); | ||
34 | } | ||
35 | ) | ||
36 | ) | ||
37 | .subscribe(); | ||
38 | } | ||
39 | |||
40 | metricsKeyExists(key: MetricsKey): boolean { | ||
41 | return this.metrics && this.metrics[key]; | ||
42 | } | ||
43 | |||
44 | metricsKeyExistsAndObjectNotEmpty(key: MetricsKey): boolean { | ||
45 | return this.metrics && this.metrics[key] && JSON.stringify(this.metrics[key]) !== '{}'; | ||
46 | } | ||
47 | } |
File src/main/webapp/app/admin/metrics/metrics.module.ts added (mode: 100644) (index 0000000..c64edda) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
4 | |||
5 | import { MetricsComponent } from './metrics.component'; | ||
6 | |||
7 | import { metricsRoute } from './metrics.route'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedModule, RouterModule.forChild([metricsRoute])], | ||
11 | declarations: [MetricsComponent] | ||
12 | }) | ||
13 | export class MetricsModule {} |
File src/main/webapp/app/admin/metrics/metrics.route.ts added (mode: 100644) (index 0000000..f85fd61) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { MetricsComponent } from './metrics.component'; | ||
4 | |||
5 | export const metricsRoute: Route = { | ||
6 | path: '', | ||
7 | component: MetricsComponent, | ||
8 | data: { | ||
9 | pageTitle: 'metrics.title' | ||
10 | } | ||
11 | }; |
File src/main/webapp/app/admin/metrics/metrics.service.ts added (mode: 100644) (index 0000000..a8d0c99) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | export type MetricsKey = 'jvm' | 'http.server.requests' | 'cache' | 'services' | 'databases' | 'garbageCollector' | 'processMetrics'; | ||
8 | export type Metrics = { [key in MetricsKey]: any }; | ||
9 | export type Thread = any; | ||
10 | export type ThreadDump = { threads: Thread[] }; | ||
11 | |||
12 | @Injectable({ providedIn: 'root' }) | ||
13 | export class MetricsService { | ||
14 | constructor(private http: HttpClient) {} | ||
15 | |||
16 | getMetrics(): Observable<Metrics> { | ||
17 | return this.http.get<Metrics>(SERVER_API_URL + 'management/jhimetrics'); | ||
18 | } | ||
19 | |||
20 | threadDump(): Observable<ThreadDump> { | ||
21 | return this.http.get<ThreadDump>(SERVER_API_URL + 'management/threaddump'); | ||
22 | } | ||
23 | } |
File src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.html added (mode: 100644) (index 0000000..778e450) | |||
1 | <form *ngIf="user" name="deleteForm" (ngSubmit)="confirmDelete(user?.login!)"> | ||
2 | <div class="modal-header"> | ||
3 | <h4 class="modal-title" jhiTranslate="entity.delete.title">Confirm delete operation</h4> | ||
4 | |||
5 | <button type="button" class="close" data-dismiss="modal" aria-hidden="true" (click)="cancel()">×</button> | ||
6 | </div> | ||
7 | |||
8 | <div class="modal-body"> | ||
9 | <auth-alert-error></auth-alert-error> | ||
10 | |||
11 | <p jhiTranslate="userManagement.delete.question" [translateValues]="{ login: user.login }">Are you sure you want to delete this User?</p> | ||
12 | </div> | ||
13 | |||
14 | <div class="modal-footer"> | ||
15 | <button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="cancel()"> | ||
16 | <fa-icon icon="ban"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancel</span> | ||
17 | </button> | ||
18 | |||
19 | <button type="submit" class="btn btn-danger"> | ||
20 | <fa-icon icon="times"></fa-icon> <span jhiTranslate="entity.action.delete">Delete</span> | ||
21 | </button> | ||
22 | </div> | ||
23 | </form> |
File src/main/webapp/app/admin/user-management/user-management-delete-dialog.component.ts added (mode: 100644) (index 0000000..86674f4) | |||
1 | import { Component } from '@angular/core'; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | import { JhiEventManager } from 'ng-jhipster'; | ||
4 | |||
5 | import { User } from 'app/core/user/user.model'; | ||
6 | import { UserService } from 'app/core/user/user.service'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-user-mgmt-delete-dialog', | ||
10 | templateUrl: './user-management-delete-dialog.component.html' | ||
11 | }) | ||
12 | export class UserManagementDeleteDialogComponent { | ||
13 | user?: User; | ||
14 | |||
15 | constructor(private userService: UserService, public activeModal: NgbActiveModal, private eventManager: JhiEventManager) {} | ||
16 | |||
17 | cancel(): void { | ||
18 | this.activeModal.dismiss(); | ||
19 | } | ||
20 | |||
21 | confirmDelete(login: string): void { | ||
22 | this.userService.delete(login).subscribe(() => { | ||
23 | this.eventManager.broadcast('userListModification'); | ||
24 | this.activeModal.close(); | ||
25 | }); | ||
26 | } | ||
27 | } |
File src/main/webapp/app/admin/user-management/user-management-detail.component.html added (mode: 100644) (index 0000000..10fb558) | |||
1 | <div class="row justify-content-center"> | ||
2 | <div class="col-8"> | ||
3 | <div *ngIf="user"> | ||
4 | <h2> | ||
5 | <span jhiTranslate="userManagement.detail.title">User</span> [<b>{{ user.login }}</b>] | ||
6 | </h2> | ||
7 | |||
8 | <dl class="row-md jh-entity-details"> | ||
9 | <dt><span jhiTranslate="userManagement.login">Login</span></dt> | ||
10 | <dd> | ||
11 | <span>{{ user.login }}</span> | ||
12 | <jhi-boolean | ||
13 | [value]="user.activated" | ||
14 | [textTrue]="'userManagement.activated' | translate" | ||
15 | [textFalse]="'userManagement.deactivated' | translate"> | ||
16 | </jhi-boolean> | ||
17 | </dd> | ||
18 | |||
19 | <dt><span jhiTranslate="userManagement.firstName">First Name</span></dt> | ||
20 | <dd>{{ user.firstName }}</dd> | ||
21 | |||
22 | <dt><span jhiTranslate="userManagement.lastName">Last Name</span></dt> | ||
23 | <dd>{{ user.lastName }}</dd> | ||
24 | |||
25 | <dt><span jhiTranslate="userManagement.email">Email</span></dt> | ||
26 | <dd>{{ user.email }}</dd> | ||
27 | |||
28 | <dt><span jhiTranslate="userManagement.langKey">Lang Key</span></dt> | ||
29 | <dd>{{ user.langKey }}</dd> | ||
30 | |||
31 | <dt><span jhiTranslate="userManagement.createdBy">Created By</span></dt> | ||
32 | <dd>{{ user.createdBy }}</dd> | ||
33 | |||
34 | <dt><span jhiTranslate="userManagement.createdDate">Created Date</span></dt> | ||
35 | <dd>{{ user.createdDate | date:'dd/MM/yy HH:mm' }}</dd> | ||
36 | |||
37 | <dt><span jhiTranslate="userManagement.lastModifiedBy">Last Modified By</span></dt> | ||
38 | <dd>{{ user.lastModifiedBy }}</dd> | ||
39 | |||
40 | <dt><span jhiTranslate="userManagement.lastModifiedDate">Last Modified Date</span></dt> | ||
41 | <dd>{{ user.lastModifiedDate | date:'dd/MM/yy HH:mm' }}</dd> | ||
42 | |||
43 | <dt><span jhiTranslate="userManagement.profiles">Profiles</span></dt> | ||
44 | <dd> | ||
45 | <ul class="list-unstyled"> | ||
46 | <li *ngFor="let authority of user.authorities"> | ||
47 | <span class="badge badge-info">{{ authority }}</span> | ||
48 | </li> | ||
49 | </ul> | ||
50 | </dd> | ||
51 | </dl> | ||
52 | |||
53 | <button type="submit" routerLink="../../" class="btn btn-info"> | ||
54 | <fa-icon icon="arrow-left"></fa-icon> <span jhiTranslate="entity.action.back">Back</span> | ||
55 | </button> | ||
56 | </div> | ||
57 | </div> | ||
58 | </div> |
File src/main/webapp/app/admin/user-management/user-management-detail.component.ts added (mode: 100644) (index 0000000..22b4198) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | |||
4 | import { User } from 'app/core/user/user.model'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-user-mgmt-detail', | ||
8 | templateUrl: './user-management-detail.component.html' | ||
9 | }) | ||
10 | export class UserManagementDetailComponent implements OnInit { | ||
11 | user: User | null = null; | ||
12 | |||
13 | constructor(private route: ActivatedRoute) {} | ||
14 | |||
15 | ngOnInit(): void { | ||
16 | this.route.data.subscribe(({ user }) => (this.user = user)); | ||
17 | } | ||
18 | } |
File src/main/webapp/app/admin/user-management/user-management-update.component.html added (mode: 100644) (index 0000000..16b6620) | |||
1 | <div class="row justify-content-center"> | ||
2 | <div class="col-8"> | ||
3 | <form name="editForm" role="form" novalidate (ngSubmit)="save()" [formGroup]="editForm"> | ||
4 | <h2 id="myUserLabel" jhiTranslate="userManagement.home.createOrEditLabel"> | ||
5 | Create or edit a User | ||
6 | </h2> | ||
7 | |||
8 | <div *ngIf="user"> | ||
9 | <auth-alert-error></auth-alert-error> | ||
10 | |||
11 | <div class="form-group" [hidden]="!user.id"> | ||
12 | <label jhiTranslate="global.field.id">ID</label> | ||
13 | <input type="text" class="form-control" name="id" formControlName="id" readonly> | ||
14 | </div> | ||
15 | |||
16 | <div class="form-group"> | ||
17 | <label class="form-control-label" jhiTranslate="userManagement.login">Login</label> | ||
18 | <input type="text" class="form-control" name="login" | ||
19 | formControlName="login"> | ||
20 | |||
21 | <div *ngIf="editForm.get('login')!.invalid && (editForm.get('login')!.dirty || editForm.get('login')!.touched)"> | ||
22 | <small class="form-text text-danger" | ||
23 | *ngIf="editForm.get('login')?.errors?.required" | ||
24 | jhiTranslate="entity.validation.required"> | ||
25 | This field is required. | ||
26 | </small> | ||
27 | |||
28 | <small class="form-text text-danger" | ||
29 | *ngIf="editForm.get('login')?.errors?.maxlength" | ||
30 | jhiTranslate="entity.validation.maxlength" | ||
31 | [translateValues]="{ max: 50 }"> | ||
32 | This field cannot be longer than 50 characters. | ||
33 | </small> | ||
34 | |||
35 | <small class="form-text text-danger" | ||
36 | *ngIf="editForm.get('login')?.errors?.pattern" | ||
37 | jhiTranslate="entity.validation.patternLogin"> | ||
38 | This field can only contain letters, digits and e-mail addresses. | ||
39 | </small> | ||
40 | </div> | ||
41 | </div> | ||
42 | |||
43 | <div class="form-group"> | ||
44 | <label class="form-control-label" jhiTranslate="userManagement.firstName">First Name</label> | ||
45 | <input type="text" class="form-control" name="firstName" | ||
46 | formControlName="firstName"> | ||
47 | |||
48 | <div *ngIf="editForm.get('firstName')!.invalid && (editForm.get('firstName')!.dirty || editForm.get('firstName')!.touched)"> | ||
49 | <small class="form-text text-danger" | ||
50 | *ngIf="editForm.get('firstName')?.errors?.maxlength" | ||
51 | jhiTranslate="entity.validation.maxlength" | ||
52 | [translateValues]="{ max: 50 }"> | ||
53 | This field cannot be longer than 50 characters. | ||
54 | </small> | ||
55 | </div> | ||
56 | </div> | ||
57 | |||
58 | <div class="form-group"> | ||
59 | <label jhiTranslate="userManagement.lastName">Last Name</label> | ||
60 | <input type="text" class="form-control" name="lastName" | ||
61 | formControlName="lastName"> | ||
62 | |||
63 | <div *ngIf="editForm.get('lastName')!.invalid && (editForm.get('lastName')!.dirty || editForm.get('lastName')!.touched)"> | ||
64 | <small class="form-text text-danger" | ||
65 | *ngIf="editForm.get('lastName')?.errors?.maxlength" | ||
66 | jhiTranslate="entity.validation.maxlength" | ||
67 | [translateValues]="{ max: 50 }"> | ||
68 | This field cannot be longer than 50 characters. | ||
69 | </small> | ||
70 | </div> | ||
71 | </div> | ||
72 | |||
73 | <div class="form-group"> | ||
74 | <label class="form-control-label" jhiTranslate="userManagement.email">Email</label> | ||
75 | <input type="email" class="form-control" name="email" formControlName="email"> | ||
76 | |||
77 | <div *ngIf="editForm.get('email')!.invalid && (editForm.get('email')!.dirty || editForm.get('email')!.touched)"> | ||
78 | <small class="form-text text-danger" | ||
79 | *ngIf="editForm.get('email')?.errors?.required" | ||
80 | jhiTranslate="entity.validation.required"> | ||
81 | This field is required. | ||
82 | </small> | ||
83 | |||
84 | <small class="form-text text-danger" | ||
85 | *ngIf="editForm.get('email')?.errors?.maxlength" | ||
86 | jhiTranslate="entity.validation.maxlength" | ||
87 | [translateValues]="{ max: 100 }"> | ||
88 | This field cannot be longer than 100 characters. | ||
89 | </small> | ||
90 | |||
91 | <small class="form-text text-danger" | ||
92 | *ngIf="editForm.get('email')?.errors?.minlength" | ||
93 | jhiTranslate="entity.validation.minlength" | ||
94 | [translateValues]="{ min: 5 }"> | ||
95 | This field is required to be at least 5 characters. | ||
96 | </small> | ||
97 | |||
98 | <small class="form-text text-danger" | ||
99 | *ngIf="editForm.get('email')?.errors?.email" | ||
100 | jhiTranslate="global.messages.validate.email.invalid"> | ||
101 | Your email is invalid. | ||
102 | </small> | ||
103 | </div> | ||
104 | </div> | ||
105 | |||
106 | <div class="form-check"> | ||
107 | <label class="form-check-label" for="activated"> | ||
108 | <input class="form-check-input" [attr.disabled]="user.id === undefined ? 'disabled' : null" | ||
109 | type="checkbox" id="activated" name="activated" formControlName="activated"> | ||
110 | <span jhiTranslate="userManagement.activated">Activated</span> | ||
111 | </label> | ||
112 | </div> | ||
113 | |||
114 | <div class="form-group" *ngIf="languages && languages.length > 0"> | ||
115 | <label jhiTranslate="userManagement.langKey">Lang Key</label> | ||
116 | <select class="form-control" id="langKey" name="langKey" formControlName="langKey"> | ||
117 | <option *ngFor="let language of languages" [value]="language">{{ language | findLanguageFromKey }}</option> | ||
118 | </select> | ||
119 | </div> | ||
120 | |||
121 | <div class="form-group"> | ||
122 | <label jhiTranslate="userManagement.profiles">Profiles</label> | ||
123 | <select class="form-control" multiple name="authority" formControlName="authorities"> | ||
124 | <option *ngFor="let authority of authorities" [value]="authority">{{ authority }}</option> | ||
125 | </select> | ||
126 | </div> | ||
127 | </div> | ||
128 | |||
129 | <div *ngIf="user"> | ||
130 | <button type="button" class="btn btn-secondary" (click)="previousState()"> | ||
131 | <fa-icon icon="ban"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancel</span> | ||
132 | </button> | ||
133 | |||
134 | <button type="submit" [disabled]="editForm.invalid || isSaving" class="btn btn-primary"> | ||
135 | <fa-icon icon="save"></fa-icon> <span jhiTranslate="entity.action.save">Save</span> | ||
136 | </button> | ||
137 | </div> | ||
138 | </form> | ||
139 | </div> | ||
140 | </div> |
File src/main/webapp/app/admin/user-management/user-management-update.component.ts added (mode: 100644) (index 0000000..6e04cbe) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { FormBuilder, Validators } from '@angular/forms'; | ||
3 | import { ActivatedRoute } from '@angular/router'; | ||
4 | |||
5 | import { LANGUAGES } from 'app/core/language/language.constants'; | ||
6 | import { User } from 'app/core/user/user.model'; | ||
7 | import { UserService } from 'app/core/user/user.service'; | ||
8 | |||
9 | @Component({ | ||
10 | selector: 'auth-user-mgmt-update', | ||
11 | templateUrl: './user-management-update.component.html' | ||
12 | }) | ||
13 | export class UserManagementUpdateComponent implements OnInit { | ||
14 | user!: User; | ||
15 | languages = LANGUAGES; | ||
16 | authorities: string[] = []; | ||
17 | isSaving = false; | ||
18 | |||
19 | editForm = this.fb.group({ | ||
20 | id: [], | ||
21 | login: ['', [Validators.required, Validators.minLength(1), Validators.maxLength(50), Validators.pattern('^[_.@A-Za-z0-9-]*')]], | ||
22 | firstName: ['', [Validators.maxLength(50)]], | ||
23 | lastName: ['', [Validators.maxLength(50)]], | ||
24 | email: ['', [Validators.minLength(5), Validators.maxLength(254), Validators.email]], | ||
25 | activated: [], | ||
26 | langKey: [], | ||
27 | authorities: [] | ||
28 | }); | ||
29 | |||
30 | constructor(private userService: UserService, private route: ActivatedRoute, private fb: FormBuilder) {} | ||
31 | |||
32 | ngOnInit(): void { | ||
33 | this.route.data.subscribe(({ user }) => { | ||
34 | if (user) { | ||
35 | this.user = user; | ||
36 | if (this.user.id === undefined) { | ||
37 | this.user.activated = true; | ||
38 | } | ||
39 | this.updateForm(user); | ||
40 | } | ||
41 | }); | ||
42 | this.userService.authorities().subscribe(authorities => { | ||
43 | this.authorities = authorities; | ||
44 | }); | ||
45 | } | ||
46 | |||
47 | previousState(): void { | ||
48 | window.history.back(); | ||
49 | } | ||
50 | |||
51 | save(): void { | ||
52 | this.isSaving = true; | ||
53 | this.updateUser(this.user); | ||
54 | if (this.user.id !== undefined) { | ||
55 | this.userService.update(this.user).subscribe( | ||
56 | () => this.onSaveSuccess(), | ||
57 | () => this.onSaveError() | ||
58 | ); | ||
59 | } else { | ||
60 | this.userService.create(this.user).subscribe( | ||
61 | () => this.onSaveSuccess(), | ||
62 | () => this.onSaveError() | ||
63 | ); | ||
64 | } | ||
65 | } | ||
66 | |||
67 | private updateForm(user: User): void { | ||
68 | this.editForm.patchValue({ | ||
69 | id: user.id, | ||
70 | login: user.login, | ||
71 | firstName: user.firstName, | ||
72 | lastName: user.lastName, | ||
73 | email: user.email, | ||
74 | activated: user.activated, | ||
75 | langKey: user.langKey, | ||
76 | authorities: user.authorities | ||
77 | }); | ||
78 | } | ||
79 | |||
80 | private updateUser(user: User): void { | ||
81 | user.login = this.editForm.get(['login'])!.value; | ||
82 | user.firstName = this.editForm.get(['firstName'])!.value; | ||
83 | user.lastName = this.editForm.get(['lastName'])!.value; | ||
84 | user.email = this.editForm.get(['email'])!.value; | ||
85 | user.activated = this.editForm.get(['activated'])!.value; | ||
86 | user.langKey = this.editForm.get(['langKey'])!.value; | ||
87 | user.authorities = this.editForm.get(['authorities'])!.value; | ||
88 | } | ||
89 | |||
90 | private onSaveSuccess(): void { | ||
91 | this.isSaving = false; | ||
92 | this.previousState(); | ||
93 | } | ||
94 | |||
95 | private onSaveError(): void { | ||
96 | this.isSaving = false; | ||
97 | } | ||
98 | } |
File src/main/webapp/app/admin/user-management/user-management.component.html added (mode: 100644) (index 0000000..21b53e9) | |||
1 | <div> | ||
2 | <h2> | ||
3 | <span id="user-management-page-heading" jhiTranslate="userManagement.home.title">Users</span> | ||
4 | |||
5 | <button class="btn btn-primary float-right jh-create-entity" [routerLink]="['./new']"> | ||
6 | <fa-icon icon="plus"></fa-icon> <span jhiTranslate="userManagement.home.createLabel">Create a new User</span> | ||
7 | </button> | ||
8 | </h2> | ||
9 | |||
10 | <auth-alert-error></auth-alert-error> | ||
11 | |||
12 | <auth-alert></auth-alert> | ||
13 | |||
14 | <div class="table-responsive" *ngIf="users"> | ||
15 | <table class="table table-striped" aria-describedby="user-management-page-heading"> | ||
16 | <thead> | ||
17 | <tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="transition.bind(this)"> | ||
18 | <th scope="col" jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon icon="sort"></fa-icon></th> | ||
19 | <th scope="col" jhiSortBy="login"><span jhiTranslate="userManagement.login">Login</span> <fa-icon icon="sort"></fa-icon></th> | ||
20 | <th scope="col" jhiSortBy="email"><span jhiTranslate="userManagement.email">Email</span> <fa-icon icon="sort"></fa-icon></th> | ||
21 | <th scope="col"></th> | ||
22 | <th scope="col" jhiSortBy="langKey"> <span jhiTranslate="userManagement.langKey">Lang Key</span> <fa-icon icon="sort"></fa-icon></th> | ||
23 | <th scope="col"><span jhiTranslate="userManagement.profiles">Profiles</span></th> | ||
24 | <th scope="col" jhiSortBy="createdDate"><span jhiTranslate="userManagement.createdDate">Created Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
25 | <th scope="col" jhiSortBy="lastModifiedBy"><span jhiTranslate="userManagement.lastModifiedBy">Last Modified By</span> <fa-icon icon="sort"></fa-icon></th> | ||
26 | <th scope="col" jhiSortBy="lastModifiedDate"><span jhiTranslate="userManagement.lastModifiedDate">Last Modified Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
27 | <th scope="col"></th> | ||
28 | </tr> | ||
29 | </thead> | ||
30 | <tbody *ngIf="users"> | ||
31 | <tr *ngFor="let user of users; trackBy: trackIdentity"> | ||
32 | <td><a [routerLink]="['./', user.login, 'view']">{{ user.id }}</a></td> | ||
33 | <td>{{ user.login }}</td> | ||
34 | <td>{{ user.email }}</td> | ||
35 | <td> | ||
36 | <button class="btn btn-danger btn-sm" (click)="setActive(user, true)" *ngIf="!user.activated" | ||
37 | jhiTranslate="userManagement.deactivated">Deactivated</button> | ||
38 | <button class="btn btn-success btn-sm" (click)="setActive(user, false)" *ngIf="user.activated" | ||
39 | [disabled]="!currentAccount || currentAccount.login === user.login" jhiTranslate="userManagement.activated">Activated</button> | ||
40 | </td> | ||
41 | <td>{{ user.langKey }}</td> | ||
42 | <td> | ||
43 | <div *ngFor="let authority of user.authorities"> | ||
44 | <span class="badge badge-info">{{ authority }}</span> | ||
45 | </div> | ||
46 | </td> | ||
47 | <td>{{ user.createdDate | date:'dd/MM/yy HH:mm' }}</td> | ||
48 | <td>{{ user.lastModifiedBy }}</td> | ||
49 | <td>{{ user.lastModifiedDate | date:'dd/MM/yy HH:mm' }}</td> | ||
50 | <td class="text-right"> | ||
51 | <div class="btn-group"> | ||
52 | <button type="submit" | ||
53 | [routerLink]="['./', user.login, 'view']" | ||
54 | class="btn btn-info btn-sm"> | ||
55 | <fa-icon icon="eye"></fa-icon> | ||
56 | <span class="d-none d-md-inline" jhiTranslate="entity.action.view">View</span> | ||
57 | </button> | ||
58 | |||
59 | <button type="submit" | ||
60 | [routerLink]="['./', user.login, 'edit']" | ||
61 | queryParamsHandling="merge" | ||
62 | class="btn btn-primary btn-sm"> | ||
63 | <fa-icon icon="pencil-alt"></fa-icon> | ||
64 | <span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit</span> | ||
65 | </button> | ||
66 | |||
67 | <button type="button" (click)="deleteUser(user)" | ||
68 | class="btn btn-danger btn-sm" [disabled]="!currentAccount || currentAccount.login === user.login"> | ||
69 | <fa-icon icon="times"></fa-icon> | ||
70 | <span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span> | ||
71 | </button> | ||
72 | </div> | ||
73 | </td> | ||
74 | </tr> | ||
75 | </tbody> | ||
76 | </table> | ||
77 | </div> | ||
78 | |||
79 | <div *ngIf="users"> | ||
80 | <div class="row justify-content-center"> | ||
81 | <jhi-item-count [page]="page" [total]="totalItems" [itemsPerPage]="itemsPerPage"></jhi-item-count> | ||
82 | </div> | ||
83 | |||
84 | <div class="row justify-content-center"> | ||
85 | <ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage(page)"></ngb-pagination> | ||
86 | </div> | ||
87 | </div> | ||
88 | </div> |
File src/main/webapp/app/admin/user-management/user-management.component.ts added (mode: 100644) (index 0000000..17bfcd9) | |||
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||
2 | import { HttpResponse, HttpHeaders } from '@angular/common/http'; | ||
3 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||
4 | import { Subscription } from 'rxjs'; | ||
5 | import { flatMap } from 'rxjs/operators'; | ||
6 | import { ActivatedRoute, Router } from '@angular/router'; | ||
7 | import { JhiEventManager } from 'ng-jhipster'; | ||
8 | |||
9 | import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; | ||
10 | import { AccountService } from 'app/core/auth/account.service'; | ||
11 | import { Account } from 'app/core/user/account.model'; | ||
12 | import { UserService } from 'app/core/user/user.service'; | ||
13 | import { User } from 'app/core/user/user.model'; | ||
14 | import { UserManagementDeleteDialogComponent } from './user-management-delete-dialog.component'; | ||
15 | |||
16 | @Component({ | ||
17 | selector: 'auth-user-mgmt', | ||
18 | templateUrl: './user-management.component.html' | ||
19 | }) | ||
20 | export class UserManagementComponent implements OnInit, OnDestroy { | ||
21 | currentAccount: Account | null = null; | ||
22 | users: User[] | null = null; | ||
23 | userListSubscription?: Subscription; | ||
24 | totalItems = 0; | ||
25 | itemsPerPage = ITEMS_PER_PAGE; | ||
26 | page!: number; | ||
27 | predicate!: string; | ||
28 | previousPage!: number; | ||
29 | ascending!: boolean; | ||
30 | |||
31 | constructor( | ||
32 | private userService: UserService, | ||
33 | private accountService: AccountService, | ||
34 | private activatedRoute: ActivatedRoute, | ||
35 | private router: Router, | ||
36 | private eventManager: JhiEventManager, | ||
37 | private modalService: NgbModal | ||
38 | ) {} | ||
39 | |||
40 | ngOnInit(): void { | ||
41 | this.activatedRoute.data | ||
42 | .pipe( | ||
43 | flatMap( | ||
44 | () => this.accountService.identity(), | ||
45 | (data, account) => { | ||
46 | this.page = data.pagingParams.page; | ||
47 | this.previousPage = data.pagingParams.page; | ||
48 | this.ascending = data.pagingParams.ascending; | ||
49 | this.predicate = data.pagingParams.predicate; | ||
50 | this.currentAccount = account; | ||
51 | this.loadAll(); | ||
52 | this.userListSubscription = this.eventManager.subscribe('userListModification', () => this.loadAll()); | ||
53 | } | ||
54 | ) | ||
55 | ) | ||
56 | .subscribe(); | ||
57 | } | ||
58 | |||
59 | ngOnDestroy(): void { | ||
60 | if (this.userListSubscription) { | ||
61 | this.eventManager.destroy(this.userListSubscription); | ||
62 | } | ||
63 | } | ||
64 | |||
65 | setActive(user: User, isActivated: boolean): void { | ||
66 | this.userService.update({ ...user, activated: isActivated }).subscribe(() => this.loadAll()); | ||
67 | } | ||
68 | |||
69 | trackIdentity(index: number, item: User): any { | ||
70 | return item.id; | ||
71 | } | ||
72 | |||
73 | loadPage(page: number): void { | ||
74 | if (page !== this.previousPage) { | ||
75 | this.previousPage = page; | ||
76 | this.transition(); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | transition(): void { | ||
81 | this.router.navigate(['./'], { | ||
82 | relativeTo: this.activatedRoute.parent, | ||
83 | queryParams: { | ||
84 | page: this.page, | ||
85 | sort: this.predicate + ',' + (this.ascending ? 'asc' : 'desc') | ||
86 | } | ||
87 | }); | ||
88 | this.loadAll(); | ||
89 | } | ||
90 | |||
91 | deleteUser(user: User): void { | ||
92 | const modalRef = this.modalService.open(UserManagementDeleteDialogComponent, { size: 'lg', backdrop: 'static' }); | ||
93 | modalRef.componentInstance.user = user; | ||
94 | } | ||
95 | |||
96 | private loadAll(): void { | ||
97 | this.userService | ||
98 | .query({ | ||
99 | page: this.page - 1, | ||
100 | size: this.itemsPerPage, | ||
101 | sort: this.sort() | ||
102 | }) | ||
103 | .subscribe((res: HttpResponse<User[]>) => this.onSuccess(res.body, res.headers)); | ||
104 | } | ||
105 | |||
106 | private sort(): string[] { | ||
107 | const result = [this.predicate + ',' + (this.ascending ? 'asc' : 'desc')]; | ||
108 | if (this.predicate !== 'id') { | ||
109 | result.push('id'); | ||
110 | } | ||
111 | return result; | ||
112 | } | ||
113 | |||
114 | private onSuccess(users: User[] | null, headers: HttpHeaders): void { | ||
115 | this.totalItems = Number(headers.get('X-Total-Count')); | ||
116 | this.users = users; | ||
117 | } | ||
118 | } |
File src/main/webapp/app/admin/user-management/user-management.module.ts added (mode: 100644) (index 0000000..be3e024) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | |||
4 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
5 | import { UserManagementComponent } from './user-management.component'; | ||
6 | import { UserManagementDetailComponent } from './user-management-detail.component'; | ||
7 | import { UserManagementUpdateComponent } from './user-management-update.component'; | ||
8 | import { UserManagementDeleteDialogComponent } from './user-management-delete-dialog.component'; | ||
9 | import { userManagementRoute } from './user-management.route'; | ||
10 | |||
11 | @NgModule({ | ||
12 | imports: [HonlapSharedModule, RouterModule.forChild(userManagementRoute)], | ||
13 | declarations: [ | ||
14 | UserManagementComponent, | ||
15 | UserManagementDetailComponent, | ||
16 | UserManagementUpdateComponent, | ||
17 | UserManagementDeleteDialogComponent | ||
18 | ], | ||
19 | entryComponents: [UserManagementDeleteDialogComponent] | ||
20 | }) | ||
21 | export class UserManagementModule {} |
File src/main/webapp/app/admin/user-management/user-management.route.ts added (mode: 100644) (index 0000000..5a5c566) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Resolve, ActivatedRouteSnapshot, Routes } from '@angular/router'; | ||
3 | import { Observable, of } from 'rxjs'; | ||
4 | import { JhiResolvePagingParams } from 'ng-jhipster'; | ||
5 | |||
6 | import { User, IUser } from 'app/core/user/user.model'; | ||
7 | import { UserService } from 'app/core/user/user.service'; | ||
8 | import { UserManagementComponent } from './user-management.component'; | ||
9 | import { UserManagementDetailComponent } from './user-management-detail.component'; | ||
10 | import { UserManagementUpdateComponent } from './user-management-update.component'; | ||
11 | |||
12 | @Injectable({ providedIn: 'root' }) | ||
13 | export class UserManagementResolve implements Resolve<IUser> { | ||
14 | constructor(private service: UserService) {} | ||
15 | |||
16 | resolve(route: ActivatedRouteSnapshot): Observable<IUser> { | ||
17 | const id = route.params['login']; | ||
18 | if (id) { | ||
19 | return this.service.find(id); | ||
20 | } | ||
21 | return of(new User()); | ||
22 | } | ||
23 | } | ||
24 | |||
25 | export const userManagementRoute: Routes = [ | ||
26 | { | ||
27 | path: '', | ||
28 | component: UserManagementComponent, | ||
29 | resolve: { | ||
30 | pagingParams: JhiResolvePagingParams | ||
31 | }, | ||
32 | data: { | ||
33 | defaultSort: 'id,asc' | ||
34 | } | ||
35 | }, | ||
36 | { | ||
37 | path: ':login/view', | ||
38 | component: UserManagementDetailComponent, | ||
39 | resolve: { | ||
40 | user: UserManagementResolve | ||
41 | } | ||
42 | }, | ||
43 | { | ||
44 | path: 'new', | ||
45 | component: UserManagementUpdateComponent, | ||
46 | resolve: { | ||
47 | user: UserManagementResolve | ||
48 | } | ||
49 | }, | ||
50 | { | ||
51 | path: ':login/edit', | ||
52 | component: UserManagementUpdateComponent, | ||
53 | resolve: { | ||
54 | user: UserManagementResolve | ||
55 | } | ||
56 | } | ||
57 | ]; |
File src/main/webapp/app/app-routing.module.ts added (mode: 100644) (index 0000000..3c06b52) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | import { errorRoute } from './layouts/error/error.route'; | ||
4 | import { navbarRoute } from './layouts/navbar/navbar.route'; | ||
5 | import { DEBUG_INFO_ENABLED } from 'app/app.constants'; | ||
6 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
7 | |||
8 | import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; | ||
9 | |||
10 | const LAYOUT_ROUTES = [navbarRoute, ...errorRoute]; | ||
11 | |||
12 | @NgModule({ | ||
13 | imports: [ | ||
14 | RouterModule.forRoot( | ||
15 | [ | ||
16 | { | ||
17 | path: 'admin', | ||
18 | data: { | ||
19 | authorities: [Authority.ADMIN] | ||
20 | }, | ||
21 | canActivate: [UserRouteAccessService], | ||
22 | loadChildren: () => import('./admin/admin-routing.module').then(m => m.AdminRoutingModule) | ||
23 | }, | ||
24 | { | ||
25 | path: 'account', | ||
26 | loadChildren: () => import('./account/account.module').then(m => m.AccountModule) | ||
27 | }, | ||
28 | ...LAYOUT_ROUTES | ||
29 | ], | ||
30 | { enableTracing: DEBUG_INFO_ENABLED } | ||
31 | ) | ||
32 | ], | ||
33 | exports: [RouterModule] | ||
34 | }) | ||
35 | export class HonlapAppRoutingModule {} |
File src/main/webapp/app/app.constants.ts added (mode: 100644) (index 0000000..4b34b65) | |||
1 | // These constants are injected via webpack environment variables. | ||
2 | // You can add more variables in webpack.common.js or in profile specific webpack.<dev|prod>.js files. | ||
3 | // If you change the values in the webpack config files, you need to re run webpack to update the application | ||
4 | |||
5 | export const VERSION = process.env.VERSION; | ||
6 | export const DEBUG_INFO_ENABLED = Boolean(process.env.DEBUG_INFO_ENABLED); | ||
7 | export const SERVER_API_URL = process.env.SERVER_API_URL; | ||
8 | export const BUILD_TIMESTAMP = process.env.BUILD_TIMESTAMP; |
File src/main/webapp/app/app.main.ts added (mode: 100644) (index 0000000..0573d94) | |||
1 | import './polyfills'; | ||
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; | ||
3 | import { ProdConfig } from './blocks/config/prod.config'; | ||
4 | import { HonlapAppModule } from './app.module'; | ||
5 | |||
6 | ProdConfig(); | ||
7 | |||
8 | if (module['hot']) { | ||
9 | module['hot'].accept(); | ||
10 | } | ||
11 | |||
12 | platformBrowserDynamic() | ||
13 | .bootstrapModule(HonlapAppModule, { preserveWhitespaces: true }) | ||
14 | // eslint-disable-next-line no-console | ||
15 | .then(() => console.log('Application started')) | ||
16 | .catch(err => console.error(err)); |
File src/main/webapp/app/app.module.ts added (mode: 100644) (index 0000000..6a96676) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { BrowserModule } from '@angular/platform-browser'; | ||
3 | |||
4 | import './vendor'; | ||
5 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
6 | import { HonlapCoreModule } from 'app/core/core.module'; | ||
7 | import { HonlapAppRoutingModule } from './app-routing.module'; | ||
8 | import { HonlapHomeModule } from './home/home.module'; | ||
9 | import { HonlapEntityModule } from './entities/entity.module'; | ||
10 | // jhipster-needle-angular-add-module-import JHipster will add new module here | ||
11 | import { MainComponent } from './layouts/main/main.component'; | ||
12 | import { NavbarComponent } from './layouts/navbar/navbar.component'; | ||
13 | import { FooterComponent } from './layouts/footer/footer.component'; | ||
14 | import { PageRibbonComponent } from './layouts/profiles/page-ribbon.component'; | ||
15 | import { ActiveMenuDirective } from './layouts/navbar/active-menu.directive'; | ||
16 | import { ErrorComponent } from './layouts/error/error.component'; | ||
17 | |||
18 | @NgModule({ | ||
19 | imports: [ | ||
20 | BrowserModule, | ||
21 | HonlapSharedModule, | ||
22 | HonlapCoreModule, | ||
23 | HonlapHomeModule, | ||
24 | // jhipster-needle-angular-add-module JHipster will add new module here | ||
25 | HonlapEntityModule, | ||
26 | HonlapAppRoutingModule | ||
27 | ], | ||
28 | declarations: [MainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent], | ||
29 | bootstrap: [MainComponent] | ||
30 | }) | ||
31 | export class HonlapAppModule {} |
File src/main/webapp/app/blocks/config/prod.config.ts added (mode: 100644) (index 0000000..b1ccef1) | |||
1 | import { enableProdMode } from '@angular/core'; | ||
2 | import { DEBUG_INFO_ENABLED } from 'app/app.constants'; | ||
3 | |||
4 | export function ProdConfig(): void { | ||
5 | // disable debug data on prod profile to improve performance | ||
6 | if (!DEBUG_INFO_ENABLED) { | ||
7 | enableProdMode(); | ||
8 | } | ||
9 | } |
File src/main/webapp/app/blocks/config/uib-pagination.config.ts added (mode: 100644) (index 0000000..002c5cf) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; | ||
4 | |||
5 | @Injectable({ providedIn: 'root' }) | ||
6 | export class PaginationConfig { | ||
7 | constructor(config: NgbPaginationConfig) { | ||
8 | config.boundaryLinks = true; | ||
9 | config.maxSize = 5; | ||
10 | config.pageSize = ITEMS_PER_PAGE; | ||
11 | config.size = 'sm'; | ||
12 | } | ||
13 | } |
File src/main/webapp/app/blocks/interceptor/auth-expired.interceptor.ts added (mode: 100644) (index 0000000..a9fa62b) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | import { tap } from 'rxjs/operators'; | ||
5 | import { Router } from '@angular/router'; | ||
6 | |||
7 | import { LoginService } from 'app/core/login/login.service'; | ||
8 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
9 | import { StateStorageService } from 'app/core/auth/state-storage.service'; | ||
10 | |||
11 | @Injectable() | ||
12 | export class AuthExpiredInterceptor implements HttpInterceptor { | ||
13 | constructor( | ||
14 | private loginService: LoginService, | ||
15 | private loginModalService: LoginModalService, | ||
16 | private stateStorageService: StateStorageService, | ||
17 | private router: Router | ||
18 | ) {} | ||
19 | |||
20 | intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
21 | return next.handle(request).pipe( | ||
22 | tap(null, (err: HttpErrorResponse) => { | ||
23 | if (err.status === 401 && err.url && !err.url.includes('api/account')) { | ||
24 | this.stateStorageService.storeUrl(this.router.routerState.snapshot.url); | ||
25 | this.loginService.logout(); | ||
26 | this.router.navigate(['']); | ||
27 | this.loginModalService.open(); | ||
28 | } | ||
29 | }) | ||
30 | ); | ||
31 | } | ||
32 | } |
File src/main/webapp/app/blocks/interceptor/auth.interceptor.ts added (mode: 100644) (index 0000000..3dd7aff) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Observable } from 'rxjs'; | ||
3 | import { LocalStorageService, SessionStorageService } from 'ngx-webstorage'; | ||
4 | import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; | ||
5 | |||
6 | import { SERVER_API_URL } from 'app/app.constants'; | ||
7 | |||
8 | @Injectable() | ||
9 | export class AuthInterceptor implements HttpInterceptor { | ||
10 | constructor(private localStorage: LocalStorageService, private sessionStorage: SessionStorageService) {} | ||
11 | |||
12 | intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
13 | if (!request || !request.url || (request.url.startsWith('http') && !(SERVER_API_URL && request.url.startsWith(SERVER_API_URL)))) { | ||
14 | return next.handle(request); | ||
15 | } | ||
16 | |||
17 | const token = this.localStorage.retrieve('authenticationToken') || this.sessionStorage.retrieve('authenticationToken'); | ||
18 | if (token) { | ||
19 | request = request.clone({ | ||
20 | setHeaders: { | ||
21 | Authorization: 'Bearer ' + token | ||
22 | } | ||
23 | }); | ||
24 | } | ||
25 | return next.handle(request); | ||
26 | } | ||
27 | } |
File src/main/webapp/app/blocks/interceptor/errorhandler.interceptor.ts added (mode: 100644) (index 0000000..bc6314e) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { JhiEventManager, JhiEventWithContent } from 'ng-jhipster'; | ||
3 | import { HttpInterceptor, HttpRequest, HttpErrorResponse, HttpHandler, HttpEvent } from '@angular/common/http'; | ||
4 | import { Observable } from 'rxjs'; | ||
5 | import { tap } from 'rxjs/operators'; | ||
6 | |||
7 | @Injectable() | ||
8 | export class ErrorHandlerInterceptor implements HttpInterceptor { | ||
9 | constructor(private eventManager: JhiEventManager) {} | ||
10 | |||
11 | intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
12 | return next.handle(request).pipe( | ||
13 | tap(null, (err: HttpErrorResponse) => { | ||
14 | if (!(err.status === 401 && (err.message === '' || (err.url && err.url.includes('api/account'))))) { | ||
15 | this.eventManager.broadcast(new JhiEventWithContent('honlapApp.httpError', err)); | ||
16 | } | ||
17 | }) | ||
18 | ); | ||
19 | } | ||
20 | } |
File src/main/webapp/app/blocks/interceptor/notification.interceptor.ts added (mode: 100644) (index 0000000..5eb735b) | |||
1 | import { JhiAlertService } from 'ng-jhipster'; | ||
2 | import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent } from '@angular/common/http'; | ||
3 | import { Injectable } from '@angular/core'; | ||
4 | import { Observable } from 'rxjs'; | ||
5 | import { tap } from 'rxjs/operators'; | ||
6 | |||
7 | @Injectable() | ||
8 | export class NotificationInterceptor implements HttpInterceptor { | ||
9 | constructor(private alertService: JhiAlertService) {} | ||
10 | |||
11 | intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { | ||
12 | return next.handle(request).pipe( | ||
13 | tap((event: HttpEvent<any>) => { | ||
14 | if (event instanceof HttpResponse) { | ||
15 | let alert: string | null = null; | ||
16 | let alertParams: string | null = null; | ||
17 | |||
18 | event.headers.keys().forEach(entry => { | ||
19 | if (entry.toLowerCase().endsWith('app-alert')) { | ||
20 | alert = event.headers.get(entry); | ||
21 | } else if (entry.toLowerCase().endsWith('app-params')) { | ||
22 | alertParams = decodeURIComponent(event.headers.get(entry)!.replace(/\+/g, ' ')); | ||
23 | } | ||
24 | }); | ||
25 | |||
26 | if (alert) { | ||
27 | this.alertService.success(alert, { param: alertParams }); | ||
28 | } | ||
29 | } | ||
30 | }) | ||
31 | ); | ||
32 | } | ||
33 | } |
File src/main/webapp/app/core/auth/account.service.ts added (mode: 100644) (index 0000000..8af48d3) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Router } from '@angular/router'; | ||
3 | import { HttpClient } from '@angular/common/http'; | ||
4 | import { JhiLanguageService } from 'ng-jhipster'; | ||
5 | import { SessionStorageService } from 'ngx-webstorage'; | ||
6 | import { Observable, ReplaySubject, of } from 'rxjs'; | ||
7 | import { shareReplay, tap, catchError } from 'rxjs/operators'; | ||
8 | import { StateStorageService } from 'app/core/auth/state-storage.service'; | ||
9 | |||
10 | import { SERVER_API_URL } from 'app/app.constants'; | ||
11 | import { Account } from 'app/core/user/account.model'; | ||
12 | |||
13 | @Injectable({ providedIn: 'root' }) | ||
14 | export class AccountService { | ||
15 | private userIdentity: Account | null = null; | ||
16 | private authenticationState = new ReplaySubject<Account | null>(1); | ||
17 | private accountCache$?: Observable<Account | null>; | ||
18 | |||
19 | constructor( | ||
20 | private languageService: JhiLanguageService, | ||
21 | private sessionStorage: SessionStorageService, | ||
22 | private http: HttpClient, | ||
23 | private stateStorageService: StateStorageService, | ||
24 | private router: Router | ||
25 | ) {} | ||
26 | |||
27 | save(account: Account): Observable<{}> { | ||
28 | return this.http.post(SERVER_API_URL + 'api/account', account); | ||
29 | } | ||
30 | |||
31 | authenticate(identity: Account | null): void { | ||
32 | this.userIdentity = identity; | ||
33 | this.authenticationState.next(this.userIdentity); | ||
34 | } | ||
35 | |||
36 | hasAnyAuthority(authorities: string[] | string): boolean { | ||
37 | if (!this.userIdentity || !this.userIdentity.authorities) { | ||
38 | return false; | ||
39 | } | ||
40 | if (!Array.isArray(authorities)) { | ||
41 | authorities = [authorities]; | ||
42 | } | ||
43 | return this.userIdentity.authorities.some((authority: string) => authorities.includes(authority)); | ||
44 | } | ||
45 | |||
46 | identity(force?: boolean): Observable<Account | null> { | ||
47 | if (!this.accountCache$ || force || !this.isAuthenticated()) { | ||
48 | this.accountCache$ = this.fetch().pipe( | ||
49 | catchError(() => { | ||
50 | return of(null); | ||
51 | }), | ||
52 | tap((account: Account | null) => { | ||
53 | this.authenticate(account); | ||
54 | |||
55 | // After retrieve the account info, the language will be changed to | ||
56 | // the user's preferred language configured in the account setting | ||
57 | if (account && account.langKey) { | ||
58 | const langKey = this.sessionStorage.retrieve('locale') || account.langKey; | ||
59 | this.languageService.changeLanguage(langKey); | ||
60 | } | ||
61 | |||
62 | if (account) { | ||
63 | this.navigateToStoredUrl(); | ||
64 | } | ||
65 | }), | ||
66 | shareReplay() | ||
67 | ); | ||
68 | } | ||
69 | return this.accountCache$; | ||
70 | } | ||
71 | |||
72 | isAuthenticated(): boolean { | ||
73 | return this.userIdentity !== null; | ||
74 | } | ||
75 | |||
76 | getAuthenticationState(): Observable<Account | null> { | ||
77 | return this.authenticationState.asObservable(); | ||
78 | } | ||
79 | |||
80 | getImageUrl(): string { | ||
81 | return this.userIdentity ? this.userIdentity.imageUrl : ''; | ||
82 | } | ||
83 | |||
84 | private fetch(): Observable<Account> { | ||
85 | return this.http.get<Account>(SERVER_API_URL + 'api/account'); | ||
86 | } | ||
87 | |||
88 | private navigateToStoredUrl(): void { | ||
89 | // previousState can be set in the authExpiredInterceptor and in the userRouteAccessService | ||
90 | // if login is successful, go to stored previousState and clear previousState | ||
91 | const previousUrl = this.stateStorageService.getUrl(); | ||
92 | if (previousUrl) { | ||
93 | this.stateStorageService.clearUrl(); | ||
94 | this.router.navigateByUrl(previousUrl); | ||
95 | } | ||
96 | } | ||
97 | } |
File src/main/webapp/app/core/auth/auth-jwt.service.ts added (mode: 100644) (index 0000000..5fb3e6f) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | import { map } from 'rxjs/operators'; | ||
5 | import { LocalStorageService, SessionStorageService } from 'ngx-webstorage'; | ||
6 | |||
7 | import { SERVER_API_URL } from 'app/app.constants'; | ||
8 | import { Login } from 'app/core/login/login.model'; | ||
9 | |||
10 | type JwtToken = { | ||
11 | id_token: string; | ||
12 | }; | ||
13 | |||
14 | @Injectable({ providedIn: 'root' }) | ||
15 | export class AuthServerProvider { | ||
16 | constructor(private http: HttpClient, private $localStorage: LocalStorageService, private $sessionStorage: SessionStorageService) {} | ||
17 | |||
18 | getToken(): string { | ||
19 | return this.$localStorage.retrieve('authenticationToken') || this.$sessionStorage.retrieve('authenticationToken') || ''; | ||
20 | } | ||
21 | |||
22 | login(credentials: Login): Observable<void> { | ||
23 | return this.http | ||
24 | .post<JwtToken>(SERVER_API_URL + 'api/authenticate', credentials) | ||
25 | .pipe(map(response => this.authenticateSuccess(response, credentials.rememberMe))); | ||
26 | } | ||
27 | |||
28 | logout(): Observable<void> { | ||
29 | return new Observable(observer => { | ||
30 | this.$localStorage.clear('authenticationToken'); | ||
31 | this.$sessionStorage.clear('authenticationToken'); | ||
32 | observer.complete(); | ||
33 | }); | ||
34 | } | ||
35 | |||
36 | private authenticateSuccess(response: JwtToken, rememberMe: boolean): void { | ||
37 | const jwt = response.id_token; | ||
38 | if (rememberMe) { | ||
39 | this.$localStorage.store('authenticationToken', jwt); | ||
40 | } else { | ||
41 | this.$sessionStorage.store('authenticationToken', jwt); | ||
42 | } | ||
43 | } | ||
44 | } |
File src/main/webapp/app/core/auth/csrf.service.ts added (mode: 100644) (index 0000000..d436d88) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { CookieService } from 'ngx-cookie'; | ||
3 | |||
4 | @Injectable({ providedIn: 'root' }) | ||
5 | export class CSRFService { | ||
6 | constructor(private cookieService: CookieService) {} | ||
7 | |||
8 | getCSRF(name = 'XSRF-TOKEN'): string { | ||
9 | return this.cookieService.get(name); | ||
10 | } | ||
11 | } |
File src/main/webapp/app/core/auth/state-storage.service.ts added (mode: 100644) (index 0000000..5d8861d) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { SessionStorageService } from 'ngx-webstorage'; | ||
3 | |||
4 | @Injectable({ providedIn: 'root' }) | ||
5 | export class StateStorageService { | ||
6 | private previousUrlKey = 'previousUrl'; | ||
7 | |||
8 | constructor(private $sessionStorage: SessionStorageService) {} | ||
9 | |||
10 | storeUrl(url: string): void { | ||
11 | this.$sessionStorage.store(this.previousUrlKey, url); | ||
12 | } | ||
13 | |||
14 | getUrl(): string | null | undefined { | ||
15 | return this.$sessionStorage.retrieve(this.previousUrlKey); | ||
16 | } | ||
17 | |||
18 | clearUrl(): void { | ||
19 | this.$sessionStorage.clear(this.previousUrlKey); | ||
20 | } | ||
21 | } |
File src/main/webapp/app/core/auth/user-route-access-service.ts added (mode: 100644) (index 0000000..30d7b7e) | |||
1 | import { Injectable, isDevMode } from '@angular/core'; | ||
2 | import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | import { map } from 'rxjs/operators'; | ||
5 | |||
6 | import { AccountService } from 'app/core/auth/account.service'; | ||
7 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
8 | import { StateStorageService } from './state-storage.service'; | ||
9 | |||
10 | @Injectable({ providedIn: 'root' }) | ||
11 | export class UserRouteAccessService implements CanActivate { | ||
12 | constructor( | ||
13 | private router: Router, | ||
14 | private loginModalService: LoginModalService, | ||
15 | private accountService: AccountService, | ||
16 | private stateStorageService: StateStorageService | ||
17 | ) {} | ||
18 | |||
19 | canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> { | ||
20 | const authorities = route.data['authorities']; | ||
21 | // We need to call the checkLogin / and so the accountService.identity() function, to ensure, | ||
22 | // that the client has a principal too, if they already logged in by the server. | ||
23 | // This could happen on a page refresh. | ||
24 | return this.checkLogin(authorities, state.url); | ||
25 | } | ||
26 | |||
27 | checkLogin(authorities: string[], url: string): Observable<boolean> { | ||
28 | return this.accountService.identity().pipe( | ||
29 | map(account => { | ||
30 | if (!authorities || authorities.length === 0) { | ||
31 | return true; | ||
32 | } | ||
33 | |||
34 | if (account) { | ||
35 | const hasAnyAuthority = this.accountService.hasAnyAuthority(authorities); | ||
36 | if (hasAnyAuthority) { | ||
37 | return true; | ||
38 | } | ||
39 | if (isDevMode()) { | ||
40 | console.error('User has not any of required authorities: ', authorities); | ||
41 | } | ||
42 | this.router.navigate(['accessdenied']); | ||
43 | return false; | ||
44 | } | ||
45 | |||
46 | this.stateStorageService.storeUrl(url); | ||
47 | this.router.navigate(['']); | ||
48 | this.loginModalService.open(); | ||
49 | return false; | ||
50 | }) | ||
51 | ); | ||
52 | } | ||
53 | } |
File src/main/webapp/app/core/core.module.ts added (mode: 100644) (index 0000000..fb93c9d) | |||
1 | import { NgModule, LOCALE_ID } from '@angular/core'; | ||
2 | import { DatePipe, registerLocaleData } from '@angular/common'; | ||
3 | import { HttpClient, HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http'; | ||
4 | import { Title } from '@angular/platform-browser'; | ||
5 | import { FaIconLibrary } from '@fortawesome/angular-fontawesome'; | ||
6 | import { CookieModule } from 'ngx-cookie'; | ||
7 | import { TranslateModule, TranslateLoader, MissingTranslationHandler } from '@ngx-translate/core'; | ||
8 | import { NgxWebstorageModule } from 'ngx-webstorage'; | ||
9 | import { NgJhipsterModule, translatePartialLoader, missingTranslationHandler, JhiConfigService, JhiLanguageService } from 'ng-jhipster'; | ||
10 | import locale from '@angular/common/locales/hu'; | ||
11 | |||
12 | import * as moment from 'moment'; | ||
13 | import { NgbDateAdapter, NgbDatepickerConfig } from '@ng-bootstrap/ng-bootstrap'; | ||
14 | import { NgbDateMomentAdapter } from 'app/shared/util/datepicker-adapter'; | ||
15 | |||
16 | import { AuthInterceptor } from 'app/blocks/interceptor/auth.interceptor'; | ||
17 | import { AuthExpiredInterceptor } from 'app/blocks/interceptor/auth-expired.interceptor'; | ||
18 | import { ErrorHandlerInterceptor } from 'app/blocks/interceptor/errorhandler.interceptor'; | ||
19 | import { NotificationInterceptor } from 'app/blocks/interceptor/notification.interceptor'; | ||
20 | |||
21 | import { fontAwesomeIcons } from './icons/font-awesome-icons'; | ||
22 | |||
23 | @NgModule({ | ||
24 | imports: [ | ||
25 | HttpClientModule, | ||
26 | CookieModule.forRoot(), | ||
27 | NgxWebstorageModule.forRoot({ prefix: 'auth', separator: '-' }), | ||
28 | NgJhipsterModule.forRoot({ | ||
29 | // set below to true to make alerts look like toast | ||
30 | alertAsToast: false, | ||
31 | alertTimeout: 5000, | ||
32 | i18nEnabled: true, | ||
33 | defaultI18nLang: 'hu' | ||
34 | }), | ||
35 | TranslateModule.forRoot({ | ||
36 | loader: { | ||
37 | provide: TranslateLoader, | ||
38 | useFactory: translatePartialLoader, | ||
39 | deps: [HttpClient] | ||
40 | }, | ||
41 | missingTranslationHandler: { | ||
42 | provide: MissingTranslationHandler, | ||
43 | useFactory: missingTranslationHandler, | ||
44 | deps: [JhiConfigService] | ||
45 | } | ||
46 | }) | ||
47 | ], | ||
48 | providers: [ | ||
49 | Title, | ||
50 | { | ||
51 | provide: LOCALE_ID, | ||
52 | useValue: 'hu' | ||
53 | }, | ||
54 | { provide: NgbDateAdapter, useClass: NgbDateMomentAdapter }, | ||
55 | DatePipe, | ||
56 | { | ||
57 | provide: HTTP_INTERCEPTORS, | ||
58 | useClass: AuthInterceptor, | ||
59 | multi: true | ||
60 | }, | ||
61 | { | ||
62 | provide: HTTP_INTERCEPTORS, | ||
63 | useClass: AuthExpiredInterceptor, | ||
64 | multi: true | ||
65 | }, | ||
66 | { | ||
67 | provide: HTTP_INTERCEPTORS, | ||
68 | useClass: ErrorHandlerInterceptor, | ||
69 | multi: true | ||
70 | }, | ||
71 | { | ||
72 | provide: HTTP_INTERCEPTORS, | ||
73 | useClass: NotificationInterceptor, | ||
74 | multi: true | ||
75 | } | ||
76 | ] | ||
77 | }) | ||
78 | export class HonlapCoreModule { | ||
79 | constructor(iconLibrary: FaIconLibrary, dpConfig: NgbDatepickerConfig, languageService: JhiLanguageService) { | ||
80 | registerLocaleData(locale); | ||
81 | iconLibrary.addIcons(...fontAwesomeIcons); | ||
82 | dpConfig.minDate = { year: moment().year() - 100, month: 1, day: 1 }; | ||
83 | languageService.init(); | ||
84 | } | ||
85 | } |
File src/main/webapp/app/core/icons/font-awesome-icons.ts added (mode: 100644) (index 0000000..2892ed2) | |||
1 | import { | ||
2 | faUser, | ||
3 | faSort, | ||
4 | faSortUp, | ||
5 | faSortDown, | ||
6 | faSync, | ||
7 | faEye, | ||
8 | faBan, | ||
9 | faTimes, | ||
10 | faArrowLeft, | ||
11 | faSave, | ||
12 | faPlus, | ||
13 | faPencilAlt, | ||
14 | faBars, | ||
15 | faThList, | ||
16 | faUserPlus, | ||
17 | faRoad, | ||
18 | faTachometerAlt, | ||
19 | faHeart, | ||
20 | faList, | ||
21 | faBell, | ||
22 | faBook, | ||
23 | faHdd, | ||
24 | faFlag, | ||
25 | faWrench, | ||
26 | faLock, | ||
27 | faCloud, | ||
28 | faSignOutAlt, | ||
29 | faSignInAlt, | ||
30 | faCalendarAlt, | ||
31 | faSearch, | ||
32 | faTrashAlt, | ||
33 | faAsterisk, | ||
34 | faTasks, | ||
35 | faHome | ||
36 | // jhipster-needle-add-icon-import | ||
37 | } from '@fortawesome/free-solid-svg-icons'; | ||
38 | |||
39 | export const fontAwesomeIcons = [ | ||
40 | faUser, | ||
41 | faSort, | ||
42 | faSortUp, | ||
43 | faSortDown, | ||
44 | faSync, | ||
45 | faEye, | ||
46 | faBan, | ||
47 | faTimes, | ||
48 | faArrowLeft, | ||
49 | faSave, | ||
50 | faPlus, | ||
51 | faPencilAlt, | ||
52 | faBars, | ||
53 | faHome, | ||
54 | faThList, | ||
55 | faUserPlus, | ||
56 | faRoad, | ||
57 | faTachometerAlt, | ||
58 | faHeart, | ||
59 | faList, | ||
60 | faBell, | ||
61 | faTasks, | ||
62 | faBook, | ||
63 | faHdd, | ||
64 | faFlag, | ||
65 | faWrench, | ||
66 | faLock, | ||
67 | faCloud, | ||
68 | faSignOutAlt, | ||
69 | faSignInAlt, | ||
70 | faCalendarAlt, | ||
71 | faSearch, | ||
72 | faTrashAlt, | ||
73 | faAsterisk | ||
74 | // jhipster-needle-add-icon-import | ||
75 | ]; |
File src/main/webapp/app/core/language/language.constants.ts added (mode: 100644) (index 0000000..ef98095) | |||
1 | /* | ||
2 | Languages codes are ISO_639-1 codes, see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes | ||
3 | They are written in English to avoid character encoding issues (not a perfect solution) | ||
4 | */ | ||
5 | export const LANGUAGES: string[] = [ | ||
6 | 'hu', | ||
7 | 'en' | ||
8 | // jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array | ||
9 | ]; |
File src/main/webapp/app/core/login/login-modal.service.ts added (mode: 100644) (index 0000000..73af6ae) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | |||
4 | import { LoginModalComponent } from 'app/shared/login/login.component'; | ||
5 | |||
6 | @Injectable({ providedIn: 'root' }) | ||
7 | export class LoginModalService { | ||
8 | private isOpen = false; | ||
9 | |||
10 | constructor(private modalService: NgbModal) {} | ||
11 | |||
12 | open(): void { | ||
13 | if (this.isOpen) { | ||
14 | return; | ||
15 | } | ||
16 | this.isOpen = true; | ||
17 | const modalRef: NgbModalRef = this.modalService.open(LoginModalComponent); | ||
18 | modalRef.result.finally(() => (this.isOpen = false)); | ||
19 | } | ||
20 | } |
File src/main/webapp/app/core/login/login.model.ts added (mode: 100644) (index 0000000..422fce9) | |||
1 | export class Login { | ||
2 | constructor(public username: string, public password: string, public rememberMe: boolean) {} | ||
3 | } |
File src/main/webapp/app/core/login/login.service.ts added (mode: 100644) (index 0000000..600f4f7) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { Observable } from 'rxjs'; | ||
3 | import { flatMap } from 'rxjs/operators'; | ||
4 | |||
5 | import { Account } from 'app/core/user/account.model'; | ||
6 | import { AccountService } from 'app/core/auth/account.service'; | ||
7 | import { AuthServerProvider } from 'app/core/auth/auth-jwt.service'; | ||
8 | import { Login } from './login.model'; | ||
9 | |||
10 | @Injectable({ providedIn: 'root' }) | ||
11 | export class LoginService { | ||
12 | constructor(private accountService: AccountService, private authServerProvider: AuthServerProvider) {} | ||
13 | |||
14 | login(credentials: Login): Observable<Account | null> { | ||
15 | return this.authServerProvider.login(credentials).pipe(flatMap(() => this.accountService.identity(true))); | ||
16 | } | ||
17 | |||
18 | logout(): void { | ||
19 | this.authServerProvider.logout().subscribe(null, null, () => this.accountService.authenticate(null)); | ||
20 | } | ||
21 | } |
File src/main/webapp/app/core/user/account.model.ts added (mode: 100644) (index 0000000..4d2c833) | |||
1 | export class Account { | ||
2 | constructor( | ||
3 | public activated: boolean, | ||
4 | public authorities: string[], | ||
5 | public email: string, | ||
6 | public firstName: string, | ||
7 | public langKey: string, | ||
8 | public lastName: string, | ||
9 | public login: string, | ||
10 | public imageUrl: string | ||
11 | ) {} | ||
12 | } |
File src/main/webapp/app/core/user/user.model.ts added (mode: 100644) (index 0000000..585f7ed) | |||
1 | export interface IUser { | ||
2 | id?: any; | ||
3 | login?: string; | ||
4 | firstName?: string; | ||
5 | lastName?: string; | ||
6 | email?: string; | ||
7 | activated?: boolean; | ||
8 | langKey?: string; | ||
9 | authorities?: string[]; | ||
10 | createdBy?: string; | ||
11 | createdDate?: Date; | ||
12 | lastModifiedBy?: string; | ||
13 | lastModifiedDate?: Date; | ||
14 | password?: string; | ||
15 | } | ||
16 | |||
17 | export class User implements IUser { | ||
18 | constructor( | ||
19 | public id?: any, | ||
20 | public login?: string, | ||
21 | public firstName?: string, | ||
22 | public lastName?: string, | ||
23 | public email?: string, | ||
24 | public activated?: boolean, | ||
25 | public langKey?: string, | ||
26 | public authorities?: string[], | ||
27 | public createdBy?: string, | ||
28 | public createdDate?: Date, | ||
29 | public lastModifiedBy?: string, | ||
30 | public lastModifiedDate?: Date, | ||
31 | public password?: string | ||
32 | ) {} | ||
33 | } |
File src/main/webapp/app/core/user/user.service.ts added (mode: 100644) (index 0000000..b598769) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient, HttpResponse } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | |||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | import { createRequestOption, Pagination } from 'app/shared/util/request-util'; | ||
7 | import { IUser } from './user.model'; | ||
8 | |||
9 | @Injectable({ providedIn: 'root' }) | ||
10 | export class UserService { | ||
11 | public resourceUrl = SERVER_API_URL + 'api/users'; | ||
12 | |||
13 | constructor(private http: HttpClient) {} | ||
14 | |||
15 | create(user: IUser): Observable<IUser> { | ||
16 | return this.http.post<IUser>(this.resourceUrl, user); | ||
17 | } | ||
18 | |||
19 | update(user: IUser): Observable<IUser> { | ||
20 | return this.http.put<IUser>(this.resourceUrl, user); | ||
21 | } | ||
22 | |||
23 | find(login: string): Observable<IUser> { | ||
24 | return this.http.get<IUser>(`${this.resourceUrl}/${login}`); | ||
25 | } | ||
26 | |||
27 | query(req?: Pagination): Observable<HttpResponse<IUser[]>> { | ||
28 | const options = createRequestOption(req); | ||
29 | return this.http.get<IUser[]>(this.resourceUrl, { params: options, observe: 'response' }); | ||
30 | } | ||
31 | |||
32 | delete(login: string): Observable<{}> { | ||
33 | return this.http.delete(`${this.resourceUrl}/${login}`); | ||
34 | } | ||
35 | |||
36 | authorities(): Observable<string[]> { | ||
37 | return this.http.get<string[]>(SERVER_API_URL + 'api/users/authorities'); | ||
38 | } | ||
39 | } |
File src/main/webapp/app/entities/entity.module.ts added (mode: 100644) (index 0000000..f87e452) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | |||
4 | @NgModule({ | ||
5 | imports: [ | ||
6 | RouterModule.forChild([ | ||
7 | { | ||
8 | path: 'piece-of-news', | ||
9 | loadChildren: () => import('./piece-of-news/piece-of-news.module').then(m => m.HonlapPieceOfNewsModule) | ||
10 | } | ||
11 | /* jhipster-needle-add-entity-route - JHipster will add entity modules routes here */ | ||
12 | ]) | ||
13 | ] | ||
14 | }) | ||
15 | export class HonlapEntityModule {} |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-delete-dialog.component.html added (mode: 100644) (index 0000000..7cb3250) | |||
1 | <form *ngIf="pieceOfNews" name="deleteForm" (ngSubmit)="confirmDelete(pieceOfNews?.id!)"> | ||
2 | <div class="modal-header"> | ||
3 | <h4 class="modal-title" jhiTranslate="entity.delete.title">Confirm delete operation</h4> | ||
4 | |||
5 | <button type="button" class="close" data-dismiss="modal" aria-hidden="true" | ||
6 | (click)="cancel()">×</button> | ||
7 | </div> | ||
8 | |||
9 | <div class="modal-body"> | ||
10 | <auth-alert-error></auth-alert-error> | ||
11 | |||
12 | <p id="auth-delete-pieceOfNews-heading" jhiTranslate="honlapApp.pieceOfNews.delete.question" [translateValues]="{ id: pieceOfNews.id }">Are you sure you want to delete this Piece Of News?</p> | ||
13 | </div> | ||
14 | |||
15 | <div class="modal-footer"> | ||
16 | <button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="cancel()"> | ||
17 | <fa-icon icon="ban"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancel</span> | ||
18 | </button> | ||
19 | |||
20 | <button id="auth-confirm-delete-pieceOfNews" type="submit" class="btn btn-danger"> | ||
21 | <fa-icon icon="times"></fa-icon> <span jhiTranslate="entity.action.delete">Delete</span> | ||
22 | </button> | ||
23 | </div> | ||
24 | </form> |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-delete-dialog.component.ts added (mode: 100644) (index 0000000..e290acb) | |||
1 | import { Component } from '@angular/core'; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | import { JhiEventManager } from 'ng-jhipster'; | ||
4 | |||
5 | import { IPieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
6 | import { PieceOfNewsService } from './piece-of-news.service'; | ||
7 | |||
8 | @Component({ | ||
9 | templateUrl: './piece-of-news-delete-dialog.component.html' | ||
10 | }) | ||
11 | export class PieceOfNewsDeleteDialogComponent { | ||
12 | pieceOfNews?: IPieceOfNews; | ||
13 | |||
14 | constructor( | ||
15 | protected pieceOfNewsService: PieceOfNewsService, | ||
16 | public activeModal: NgbActiveModal, | ||
17 | protected eventManager: JhiEventManager | ||
18 | ) {} | ||
19 | |||
20 | cancel(): void { | ||
21 | this.activeModal.dismiss(); | ||
22 | } | ||
23 | |||
24 | confirmDelete(id: number): void { | ||
25 | this.pieceOfNewsService.delete(id).subscribe(() => { | ||
26 | this.eventManager.broadcast('pieceOfNewsListModification'); | ||
27 | this.activeModal.close(); | ||
28 | }); | ||
29 | } | ||
30 | } |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-detail.component.html added (mode: 100644) (index 0000000..6a71a4a) | |||
1 | <div class="row justify-content-center"> | ||
2 | <div class="col-8"> | ||
3 | <div *ngIf="pieceOfNews"> | ||
4 | <h2><span jhiTranslate="honlapApp.pieceOfNews.detail.title">Piece Of News</span> {{ pieceOfNews.id }}</h2> | ||
5 | |||
6 | <hr> | ||
7 | |||
8 | <auth-alert-error></auth-alert-error> | ||
9 | |||
10 | <dl class="row-md jh-entity-details"> | ||
11 | <dt><span jhiTranslate="honlapApp.pieceOfNews.appId">App Id</span></dt> | ||
12 | <dd> | ||
13 | <span>{{ pieceOfNews.appId }}</span> | ||
14 | </dd> | ||
15 | <dt><span jhiTranslate="honlapApp.pieceOfNews.newsDate">News Date</span></dt> | ||
16 | <dd> | ||
17 | <span>{{ pieceOfNews.newsDate }}</span> | ||
18 | </dd> | ||
19 | <dt><span jhiTranslate="honlapApp.pieceOfNews.headline">Headline</span></dt> | ||
20 | <dd> | ||
21 | <span>{{ pieceOfNews.headline }}</span> | ||
22 | </dd> | ||
23 | <dt><span jhiTranslate="honlapApp.pieceOfNews.content">Content</span></dt> | ||
24 | <dd> | ||
25 | <span>{{ pieceOfNews.content }}</span> | ||
26 | </dd> | ||
27 | <dt><span jhiTranslate="honlapApp.pieceOfNews.link">Link</span></dt> | ||
28 | <dd> | ||
29 | <span>{{ pieceOfNews.link }}</span> | ||
30 | </dd> | ||
31 | <dt><span jhiTranslate="honlapApp.pieceOfNews.publishDate">Publish Date</span></dt> | ||
32 | <dd> | ||
33 | <span>{{ pieceOfNews.publishDate }}</span> | ||
34 | </dd> | ||
35 | <dt><span jhiTranslate="honlapApp.pieceOfNews.createdBy">Created By</span></dt> | ||
36 | <dd> | ||
37 | <span>{{ pieceOfNews.createdBy }}</span> | ||
38 | </dd> | ||
39 | <dt><span jhiTranslate="honlapApp.pieceOfNews.createdDate">Created Date</span></dt> | ||
40 | <dd> | ||
41 | <span>{{ pieceOfNews.createdDate }}</span> | ||
42 | </dd> | ||
43 | <dt><span jhiTranslate="honlapApp.pieceOfNews.lastModifiedBy">Last Modified By</span></dt> | ||
44 | <dd> | ||
45 | <span>{{ pieceOfNews.lastModifiedBy }}</span> | ||
46 | </dd> | ||
47 | <dt><span jhiTranslate="honlapApp.pieceOfNews.lastModifiedDate">Last Modified Date</span></dt> | ||
48 | <dd> | ||
49 | <span>{{ pieceOfNews.lastModifiedDate }}</span> | ||
50 | </dd> | ||
51 | </dl> | ||
52 | |||
53 | <button type="submit" | ||
54 | (click)="previousState()" | ||
55 | class="btn btn-info"> | ||
56 | <fa-icon icon="arrow-left"></fa-icon> <span jhiTranslate="entity.action.back">Back</span> | ||
57 | </button> | ||
58 | |||
59 | <button type="button" | ||
60 | [routerLink]="['/piece-of-news', pieceOfNews.id, 'edit']" | ||
61 | class="btn btn-primary"> | ||
62 | <fa-icon icon="pencil-alt"></fa-icon> <span jhiTranslate="entity.action.edit">Edit</span> | ||
63 | </button> | ||
64 | </div> | ||
65 | </div> | ||
66 | </div> |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-detail.component.ts added (mode: 100644) (index 0000000..dd811ce) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | |||
4 | import { IPieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-piece-of-news-detail', | ||
8 | templateUrl: './piece-of-news-detail.component.html' | ||
9 | }) | ||
10 | export class PieceOfNewsDetailComponent implements OnInit { | ||
11 | pieceOfNews: IPieceOfNews | null = null; | ||
12 | |||
13 | constructor(protected activatedRoute: ActivatedRoute) {} | ||
14 | |||
15 | ngOnInit(): void { | ||
16 | this.activatedRoute.data.subscribe(({ pieceOfNews }) => (this.pieceOfNews = pieceOfNews)); | ||
17 | } | ||
18 | |||
19 | previousState(): void { | ||
20 | window.history.back(); | ||
21 | } | ||
22 | } |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-update.component.html added (mode: 100644) (index 0000000..fb873dd) | |||
1 | <div class="row justify-content-center"> | ||
2 | <div class="col-8"> | ||
3 | <form name="editForm" role="form" novalidate (ngSubmit)="save()" [formGroup]="editForm"> | ||
4 | <h2 id="auth-piece-of-news-heading" jhiTranslate="honlapApp.pieceOfNews.home.createOrEditLabel">Create or edit a Piece Of News</h2> | ||
5 | |||
6 | <div> | ||
7 | <auth-alert-error></auth-alert-error> | ||
8 | |||
9 | <div class="form-group" [hidden]="!editForm.get('id')!.value"> | ||
10 | <label for="id" jhiTranslate="global.field.id">ID</label> | ||
11 | <input type="text" class="form-control" id="id" name="id" formControlName="id" readonly /> | ||
12 | </div> | ||
13 | |||
14 | <div class="form-group"> | ||
15 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.appId" for="field_appId">App Id</label> | ||
16 | <input type="number" class="form-control" name="appId" id="field_appId" | ||
17 | formControlName="appId"/> | ||
18 | <div *ngIf="editForm.get('appId')!.invalid && (editForm.get('appId')!.dirty || editForm.get('appId')!.touched)"> | ||
19 | <small class="form-text text-danger" | ||
20 | *ngIf="editForm.get('appId')?.errors?.required" jhiTranslate="entity.validation.required"> | ||
21 | This field is required. | ||
22 | </small> | ||
23 | <small class="form-text text-danger" | ||
24 | [hidden]="!editForm.get('appId')?.errors?.number" jhiTranslate="entity.validation.number"> | ||
25 | This field should be a number. | ||
26 | </small> | ||
27 | </div> | ||
28 | </div> | ||
29 | |||
30 | <div class="form-group"> | ||
31 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.newsDate" for="field_newsDate">News Date</label> | ||
32 | <div class="d-flex"> | ||
33 | <input id="field_newsDate" type="datetime-local" class="form-control" name="newsDate" formControlName="newsDate" placeholder="YYYY-MM-DD HH:mm"/> | ||
34 | </div> | ||
35 | <div *ngIf="editForm.get('newsDate')!.invalid && (editForm.get('newsDate')!.dirty || editForm.get('newsDate')!.touched)"> | ||
36 | <small class="form-text text-danger" | ||
37 | *ngIf="editForm.get('newsDate')?.errors?.required" jhiTranslate="entity.validation.required"> | ||
38 | This field is required. | ||
39 | </small> | ||
40 | <small class="form-text text-danger" | ||
41 | [hidden]="!editForm.get('newsDate')?.errors?.ZonedDateTimelocal" jhiTranslate="entity.validation.ZonedDateTimelocal"> | ||
42 | This field should be a date and time. | ||
43 | </small> | ||
44 | </div> | ||
45 | </div> | ||
46 | |||
47 | <div class="form-group"> | ||
48 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.headline" for="field_headline">Headline</label> | ||
49 | <input type="text" class="form-control" name="headline" id="field_headline" | ||
50 | formControlName="headline"/> | ||
51 | <div *ngIf="editForm.get('headline')!.invalid && (editForm.get('headline')!.dirty || editForm.get('headline')!.touched)"> | ||
52 | <small class="form-text text-danger" | ||
53 | *ngIf="editForm.get('headline')?.errors?.required" jhiTranslate="entity.validation.required"> | ||
54 | This field is required. | ||
55 | </small> | ||
56 | <small class="form-text text-danger" | ||
57 | *ngIf="editForm.get('headline')?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 300 }"> | ||
58 | This field cannot be longer than 300 characters. | ||
59 | </small> | ||
60 | </div> | ||
61 | </div> | ||
62 | |||
63 | <div class="form-group"> | ||
64 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.content" for="field_content">Content</label> | ||
65 | <input type="text" class="form-control" name="content" id="field_content" | ||
66 | formControlName="content"/> | ||
67 | <div *ngIf="editForm.get('content')!.invalid && (editForm.get('content')!.dirty || editForm.get('content')!.touched)"> | ||
68 | <small class="form-text text-danger" | ||
69 | *ngIf="editForm.get('content')?.errors?.required" jhiTranslate="entity.validation.required"> | ||
70 | This field is required. | ||
71 | </small> | ||
72 | <small class="form-text text-danger" | ||
73 | *ngIf="editForm.get('content')?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 600 }"> | ||
74 | This field cannot be longer than 600 characters. | ||
75 | </small> | ||
76 | </div> | ||
77 | </div> | ||
78 | |||
79 | <div class="form-group"> | ||
80 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.link" for="field_link">Link</label> | ||
81 | <input type="text" class="form-control" name="link" id="field_link" | ||
82 | formControlName="link"/> | ||
83 | <div *ngIf="editForm.get('link')!.invalid && (editForm.get('link')!.dirty || editForm.get('link')!.touched)"> | ||
84 | <small class="form-text text-danger" | ||
85 | *ngIf="editForm.get('link')?.errors?.required" jhiTranslate="entity.validation.required"> | ||
86 | This field is required. | ||
87 | </small> | ||
88 | <small class="form-text text-danger" | ||
89 | *ngIf="editForm.get('link')?.errors?.maxlength" jhiTranslate="entity.validation.maxlength" [translateValues]="{ max: 600 }"> | ||
90 | This field cannot be longer than 600 characters. | ||
91 | </small> | ||
92 | </div> | ||
93 | </div> | ||
94 | |||
95 | <div class="form-group"> | ||
96 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.publishDate" for="field_publishDate">Publish Date</label> | ||
97 | <div class="d-flex"> | ||
98 | <input id="field_publishDate" type="datetime-local" class="form-control" name="publishDate" formControlName="publishDate" placeholder="YYYY-MM-DD HH:mm"/> | ||
99 | </div> | ||
100 | </div> | ||
101 | |||
102 | <div class="form-group"> | ||
103 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.createdBy" for="field_createdBy">Created By</label> | ||
104 | <input type="text" class="form-control" name="createdBy" id="field_createdBy" | ||
105 | formControlName="createdBy"/> | ||
106 | </div> | ||
107 | |||
108 | <div class="form-group"> | ||
109 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.createdDate" for="field_createdDate">Created Date</label> | ||
110 | <div class="d-flex"> | ||
111 | <input id="field_createdDate" type="datetime-local" class="form-control" name="createdDate" formControlName="createdDate" placeholder="YYYY-MM-DD HH:mm"/> | ||
112 | </div> | ||
113 | </div> | ||
114 | |||
115 | <div class="form-group"> | ||
116 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.lastModifiedBy" for="field_lastModifiedBy">Last Modified By</label> | ||
117 | <input type="text" class="form-control" name="lastModifiedBy" id="field_lastModifiedBy" | ||
118 | formControlName="lastModifiedBy"/> | ||
119 | </div> | ||
120 | |||
121 | <div class="form-group"> | ||
122 | <label class="form-control-label" jhiTranslate="honlapApp.pieceOfNews.lastModifiedDate" for="field_lastModifiedDate">Last Modified Date</label> | ||
123 | <div class="d-flex"> | ||
124 | <input id="field_lastModifiedDate" type="datetime-local" class="form-control" name="lastModifiedDate" formControlName="lastModifiedDate" placeholder="YYYY-MM-DD HH:mm"/> | ||
125 | </div> | ||
126 | </div> | ||
127 | </div> | ||
128 | |||
129 | <div> | ||
130 | <button type="button" id="cancel-save" class="btn btn-secondary" (click)="previousState()"> | ||
131 | <fa-icon icon="ban"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancel</span> | ||
132 | </button> | ||
133 | |||
134 | <button type="submit" id="save-entity" [disabled]="editForm.invalid || isSaving" class="btn btn-primary"> | ||
135 | <fa-icon icon="save"></fa-icon> <span jhiTranslate="entity.action.save">Save</span> | ||
136 | </button> | ||
137 | </div> | ||
138 | </form> | ||
139 | </div> | ||
140 | </div> |
File src/main/webapp/app/entities/piece-of-news/piece-of-news-update.component.ts added (mode: 100644) (index 0000000..87bffcf) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { HttpResponse } from '@angular/common/http'; | ||
3 | // eslint-disable-next-line @typescript-eslint/no-unused-vars | ||
4 | import { FormBuilder, Validators } from '@angular/forms'; | ||
5 | import { ActivatedRoute } from '@angular/router'; | ||
6 | import { Observable } from 'rxjs'; | ||
7 | import * as moment from 'moment'; | ||
8 | import { DATE_TIME_FORMAT } from 'app/shared/constants/input.constants'; | ||
9 | |||
10 | import { IPieceOfNews, PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
11 | import { PieceOfNewsService } from './piece-of-news.service'; | ||
12 | |||
13 | @Component({ | ||
14 | selector: 'auth-piece-of-news-update', | ||
15 | templateUrl: './piece-of-news-update.component.html' | ||
16 | }) | ||
17 | export class PieceOfNewsUpdateComponent implements OnInit { | ||
18 | isSaving = false; | ||
19 | |||
20 | editForm = this.fb.group({ | ||
21 | id: [], | ||
22 | appId: [null, [Validators.required]], | ||
23 | newsDate: [null, [Validators.required]], | ||
24 | headline: [null, [Validators.required, Validators.maxLength(300)]], | ||
25 | content: [null, [Validators.required, Validators.maxLength(600)]], | ||
26 | link: [null, [Validators.required, Validators.maxLength(600)]], | ||
27 | publishDate: [], | ||
28 | createdBy: [], | ||
29 | createdDate: [], | ||
30 | lastModifiedBy: [], | ||
31 | lastModifiedDate: [] | ||
32 | }); | ||
33 | |||
34 | constructor(protected pieceOfNewsService: PieceOfNewsService, protected activatedRoute: ActivatedRoute, private fb: FormBuilder) {} | ||
35 | |||
36 | ngOnInit(): void { | ||
37 | this.activatedRoute.data.subscribe(({ pieceOfNews }) => { | ||
38 | if (!pieceOfNews.id) { | ||
39 | const today = moment().startOf('day'); | ||
40 | pieceOfNews.newsDate = today; | ||
41 | pieceOfNews.publishDate = today; | ||
42 | pieceOfNews.createdDate = today; | ||
43 | pieceOfNews.lastModifiedDate = today; | ||
44 | } | ||
45 | |||
46 | this.updateForm(pieceOfNews); | ||
47 | }); | ||
48 | } | ||
49 | |||
50 | updateForm(pieceOfNews: IPieceOfNews): void { | ||
51 | this.editForm.patchValue({ | ||
52 | id: pieceOfNews.id, | ||
53 | appId: pieceOfNews.appId, | ||
54 | newsDate: pieceOfNews.newsDate ? pieceOfNews.newsDate.format(DATE_TIME_FORMAT) : null, | ||
55 | headline: pieceOfNews.headline, | ||
56 | content: pieceOfNews.content, | ||
57 | link: pieceOfNews.link, | ||
58 | publishDate: pieceOfNews.publishDate ? pieceOfNews.publishDate.format(DATE_TIME_FORMAT) : null, | ||
59 | createdBy: pieceOfNews.createdBy, | ||
60 | createdDate: pieceOfNews.createdDate ? pieceOfNews.createdDate.format(DATE_TIME_FORMAT) : null, | ||
61 | lastModifiedBy: pieceOfNews.lastModifiedBy, | ||
62 | lastModifiedDate: pieceOfNews.lastModifiedDate ? pieceOfNews.lastModifiedDate.format(DATE_TIME_FORMAT) : null | ||
63 | }); | ||
64 | } | ||
65 | |||
66 | previousState(): void { | ||
67 | window.history.back(); | ||
68 | } | ||
69 | |||
70 | save(): void { | ||
71 | this.isSaving = true; | ||
72 | const pieceOfNews = this.createFromForm(); | ||
73 | if (pieceOfNews.id !== undefined) { | ||
74 | this.subscribeToSaveResponse(this.pieceOfNewsService.update(pieceOfNews)); | ||
75 | } else { | ||
76 | this.subscribeToSaveResponse(this.pieceOfNewsService.create(pieceOfNews)); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | private createFromForm(): IPieceOfNews { | ||
81 | return { | ||
82 | ...new PieceOfNews(), | ||
83 | id: this.editForm.get(['id'])!.value, | ||
84 | appId: this.editForm.get(['appId'])!.value, | ||
85 | newsDate: this.editForm.get(['newsDate'])!.value ? moment(this.editForm.get(['newsDate'])!.value, DATE_TIME_FORMAT) : undefined, | ||
86 | headline: this.editForm.get(['headline'])!.value, | ||
87 | content: this.editForm.get(['content'])!.value, | ||
88 | link: this.editForm.get(['link'])!.value, | ||
89 | publishDate: this.editForm.get(['publishDate'])!.value | ||
90 | ? moment(this.editForm.get(['publishDate'])!.value, DATE_TIME_FORMAT) | ||
91 | : undefined, | ||
92 | createdBy: this.editForm.get(['createdBy'])!.value, | ||
93 | createdDate: this.editForm.get(['createdDate'])!.value | ||
94 | ? moment(this.editForm.get(['createdDate'])!.value, DATE_TIME_FORMAT) | ||
95 | : undefined, | ||
96 | lastModifiedBy: this.editForm.get(['lastModifiedBy'])!.value, | ||
97 | lastModifiedDate: this.editForm.get(['lastModifiedDate'])!.value | ||
98 | ? moment(this.editForm.get(['lastModifiedDate'])!.value, DATE_TIME_FORMAT) | ||
99 | : undefined | ||
100 | }; | ||
101 | } | ||
102 | |||
103 | protected subscribeToSaveResponse(result: Observable<HttpResponse<IPieceOfNews>>): void { | ||
104 | result.subscribe( | ||
105 | () => this.onSaveSuccess(), | ||
106 | () => this.onSaveError() | ||
107 | ); | ||
108 | } | ||
109 | |||
110 | protected onSaveSuccess(): void { | ||
111 | this.isSaving = false; | ||
112 | this.previousState(); | ||
113 | } | ||
114 | |||
115 | protected onSaveError(): void { | ||
116 | this.isSaving = false; | ||
117 | } | ||
118 | } |
File src/main/webapp/app/entities/piece-of-news/piece-of-news.component.html added (mode: 100644) (index 0000000..e48ac08) | |||
1 | <div> | ||
2 | <h2 id="page-heading"> | ||
3 | <span jhiTranslate="honlapApp.pieceOfNews.home.title">Piece Of News</span> | ||
4 | |||
5 | <button id="jh-create-entity" class="btn btn-primary float-right jh-create-entity create-piece-of-news" [routerLink]="['/piece-of-news/new']"> | ||
6 | <fa-icon icon="plus"></fa-icon> | ||
7 | <span jhiTranslate="honlapApp.pieceOfNews.home.createLabel"> | ||
8 | Create a new Piece Of News | ||
9 | </span> | ||
10 | </button> | ||
11 | </h2> | ||
12 | |||
13 | <auth-alert-error></auth-alert-error> | ||
14 | |||
15 | <auth-alert></auth-alert> | ||
16 | |||
17 | <div class="alert alert-warning" id="no-result" *ngIf="pieceOfNews?.length === 0"> | ||
18 | <span jhiTranslate="honlapApp.pieceOfNews.home.notFound">No pieceOfNews found</span> | ||
19 | </div> | ||
20 | |||
21 | <div class="table-responsive" id="entities" *ngIf="pieceOfNews?.length > 0"> | ||
22 | <table class="table table-striped" aria-describedby="page-heading"> | ||
23 | <thead> | ||
24 | <tr jhiSort [(predicate)]="predicate" [(ascending)]="ascending" [callback]="loadPage.bind(this)"> | ||
25 | <th scope="col" jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon icon="sort"></fa-icon></th> | ||
26 | <th scope="col" jhiSortBy="appId"><span jhiTranslate="honlapApp.pieceOfNews.appId">App Id</span> <fa-icon icon="sort"></fa-icon></th> | ||
27 | <th scope="col" jhiSortBy="newsDate"><span jhiTranslate="honlapApp.pieceOfNews.newsDate">News Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
28 | <th scope="col" jhiSortBy="headline"><span jhiTranslate="honlapApp.pieceOfNews.headline">Headline</span> <fa-icon icon="sort"></fa-icon></th> | ||
29 | <th scope="col" jhiSortBy="content"><span jhiTranslate="honlapApp.pieceOfNews.content">Content</span> <fa-icon icon="sort"></fa-icon></th> | ||
30 | <th scope="col" jhiSortBy="link"><span jhiTranslate="honlapApp.pieceOfNews.link">Link</span> <fa-icon icon="sort"></fa-icon></th> | ||
31 | <th scope="col" jhiSortBy="publishDate"><span jhiTranslate="honlapApp.pieceOfNews.publishDate">Publish Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
32 | <th scope="col" jhiSortBy="createdBy"><span jhiTranslate="honlapApp.pieceOfNews.createdBy">Created By</span> <fa-icon icon="sort"></fa-icon></th> | ||
33 | <th scope="col" jhiSortBy="createdDate"><span jhiTranslate="honlapApp.pieceOfNews.createdDate">Created Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
34 | <th scope="col" jhiSortBy="lastModifiedBy"><span jhiTranslate="honlapApp.pieceOfNews.lastModifiedBy">Last Modified By</span> <fa-icon icon="sort"></fa-icon></th> | ||
35 | <th scope="col" jhiSortBy="lastModifiedDate"><span jhiTranslate="honlapApp.pieceOfNews.lastModifiedDate">Last Modified Date</span> <fa-icon icon="sort"></fa-icon></th> | ||
36 | <th scope="col"></th> | ||
37 | </tr> | ||
38 | </thead> | ||
39 | <tbody> | ||
40 | <tr *ngFor="let pieceOfNews of pieceOfNews ;trackBy: trackId"> | ||
41 | <td><a [routerLink]="['/piece-of-news', pieceOfNews.id, 'view']">{{ pieceOfNews.id }}</a></td> | ||
42 | <td>{{ pieceOfNews.appId }}</td> | ||
43 | <td>{{ pieceOfNews.newsDate | date:'medium' }}</td> | ||
44 | <td>{{ pieceOfNews.headline }}</td> | ||
45 | <td>{{ pieceOfNews.content }}</td> | ||
46 | <td>{{ pieceOfNews.link }}</td> | ||
47 | <td>{{ pieceOfNews.publishDate | date:'medium' }}</td> | ||
48 | <td>{{ pieceOfNews.createdBy }}</td> | ||
49 | <td>{{ pieceOfNews.createdDate | date:'medium' }}</td> | ||
50 | <td>{{ pieceOfNews.lastModifiedBy }}</td> | ||
51 | <td>{{ pieceOfNews.lastModifiedDate | date:'medium' }}</td> | ||
52 | <td class="text-right"> | ||
53 | <div class="btn-group"> | ||
54 | <button type="submit" | ||
55 | [routerLink]="['/piece-of-news', pieceOfNews.id, 'view']" | ||
56 | class="btn btn-info btn-sm"> | ||
57 | <fa-icon icon="eye"></fa-icon> | ||
58 | <span class="d-none d-md-inline" jhiTranslate="entity.action.view">View</span> | ||
59 | </button> | ||
60 | |||
61 | <button type="submit" | ||
62 | [routerLink]="['/piece-of-news', pieceOfNews.id, 'edit']" | ||
63 | class="btn btn-primary btn-sm"> | ||
64 | <fa-icon icon="pencil-alt"></fa-icon> | ||
65 | <span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit</span> | ||
66 | </button> | ||
67 | |||
68 | <button type="submit" (click)="delete(pieceOfNews)" | ||
69 | class="btn btn-danger btn-sm"> | ||
70 | <fa-icon icon="times"></fa-icon> | ||
71 | <span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span> | ||
72 | </button> | ||
73 | </div> | ||
74 | </td> | ||
75 | </tr> | ||
76 | </tbody> | ||
77 | </table> | ||
78 | </div> | ||
79 | |||
80 | <div *ngIf="pieceOfNews?.length > 0"> | ||
81 | <div class="row justify-content-center"> | ||
82 | <jhi-item-count [page]="page" [total]="totalItems" [itemsPerPage]="itemsPerPage"></jhi-item-count> | ||
83 | </div> | ||
84 | |||
85 | <div class="row justify-content-center"> | ||
86 | <ngb-pagination [collectionSize]="totalItems" [(page)]="ngbPaginationPage" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage($event)"></ngb-pagination> | ||
87 | </div> | ||
88 | </div> | ||
89 | </div> |
File src/main/webapp/app/entities/piece-of-news/piece-of-news.component.ts added (mode: 100644) (index 0000000..c6f927e) | |||
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||
2 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; | ||
3 | import { ActivatedRoute, Router } from '@angular/router'; | ||
4 | import { Subscription } from 'rxjs'; | ||
5 | import { JhiEventManager } from 'ng-jhipster'; | ||
6 | import { NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||
7 | |||
8 | import { IPieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
9 | |||
10 | import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; | ||
11 | import { PieceOfNewsService } from './piece-of-news.service'; | ||
12 | import { PieceOfNewsDeleteDialogComponent } from './piece-of-news-delete-dialog.component'; | ||
13 | |||
14 | @Component({ | ||
15 | selector: 'auth-piece-of-news', | ||
16 | templateUrl: './piece-of-news.component.html' | ||
17 | }) | ||
18 | export class PieceOfNewsComponent implements OnInit, OnDestroy { | ||
19 | pieceOfNews?: IPieceOfNews[]; | ||
20 | eventSubscriber?: Subscription; | ||
21 | totalItems = 0; | ||
22 | itemsPerPage = ITEMS_PER_PAGE; | ||
23 | page!: number; | ||
24 | predicate!: string; | ||
25 | ascending!: boolean; | ||
26 | ngbPaginationPage = 1; | ||
27 | |||
28 | constructor( | ||
29 | protected pieceOfNewsService: PieceOfNewsService, | ||
30 | protected activatedRoute: ActivatedRoute, | ||
31 | protected router: Router, | ||
32 | protected eventManager: JhiEventManager, | ||
33 | protected modalService: NgbModal | ||
34 | ) {} | ||
35 | |||
36 | loadPage(page?: number): void { | ||
37 | const pageToLoad: number = page || this.page; | ||
38 | |||
39 | this.pieceOfNewsService | ||
40 | .query({ | ||
41 | page: pageToLoad - 1, | ||
42 | size: this.itemsPerPage, | ||
43 | sort: this.sort() | ||
44 | }) | ||
45 | .subscribe( | ||
46 | (res: HttpResponse<IPieceOfNews[]>) => this.onSuccess(res.body, res.headers, pageToLoad), | ||
47 | () => this.onError() | ||
48 | ); | ||
49 | } | ||
50 | |||
51 | ngOnInit(): void { | ||
52 | this.activatedRoute.data.subscribe(data => { | ||
53 | this.page = data.pagingParams.page; | ||
54 | this.ascending = data.pagingParams.ascending; | ||
55 | this.predicate = data.pagingParams.predicate; | ||
56 | this.ngbPaginationPage = data.pagingParams.page; | ||
57 | this.loadPage(); | ||
58 | }); | ||
59 | this.registerChangeInPieceOfNews(); | ||
60 | } | ||
61 | |||
62 | ngOnDestroy(): void { | ||
63 | if (this.eventSubscriber) { | ||
64 | this.eventManager.destroy(this.eventSubscriber); | ||
65 | } | ||
66 | } | ||
67 | |||
68 | trackId(index: number, item: IPieceOfNews): number { | ||
69 | // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-assertion | ||
70 | return item.id!; | ||
71 | } | ||
72 | |||
73 | registerChangeInPieceOfNews(): void { | ||
74 | this.eventSubscriber = this.eventManager.subscribe('pieceOfNewsListModification', () => this.loadPage()); | ||
75 | } | ||
76 | |||
77 | delete(pieceOfNews: IPieceOfNews): void { | ||
78 | const modalRef = this.modalService.open(PieceOfNewsDeleteDialogComponent, { size: 'lg', backdrop: 'static' }); | ||
79 | modalRef.componentInstance.pieceOfNews = pieceOfNews; | ||
80 | } | ||
81 | |||
82 | sort(): string[] { | ||
83 | const result = [this.predicate + ',' + (this.ascending ? 'asc' : 'desc')]; | ||
84 | if (this.predicate !== 'id') { | ||
85 | result.push('id'); | ||
86 | } | ||
87 | return result; | ||
88 | } | ||
89 | |||
90 | protected onSuccess(data: IPieceOfNews[] | null, headers: HttpHeaders, page: number): void { | ||
91 | this.totalItems = Number(headers.get('X-Total-Count')); | ||
92 | this.page = page; | ||
93 | this.router.navigate(['/piece-of-news'], { | ||
94 | queryParams: { | ||
95 | page: this.page, | ||
96 | size: this.itemsPerPage, | ||
97 | sort: this.predicate + ',' + (this.ascending ? 'asc' : 'desc') | ||
98 | } | ||
99 | }); | ||
100 | this.pieceOfNews = data || []; | ||
101 | } | ||
102 | |||
103 | protected onError(): void { | ||
104 | this.ngbPaginationPage = this.page; | ||
105 | } | ||
106 | } |
File src/main/webapp/app/entities/piece-of-news/piece-of-news.module.ts added (mode: 100644) (index 0000000..4e90026) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | |||
4 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
5 | import { PieceOfNewsComponent } from './piece-of-news.component'; | ||
6 | import { PieceOfNewsDetailComponent } from './piece-of-news-detail.component'; | ||
7 | import { PieceOfNewsUpdateComponent } from './piece-of-news-update.component'; | ||
8 | import { PieceOfNewsDeleteDialogComponent } from './piece-of-news-delete-dialog.component'; | ||
9 | import { pieceOfNewsRoute } from './piece-of-news.route'; | ||
10 | |||
11 | @NgModule({ | ||
12 | imports: [HonlapSharedModule, RouterModule.forChild(pieceOfNewsRoute)], | ||
13 | declarations: [PieceOfNewsComponent, PieceOfNewsDetailComponent, PieceOfNewsUpdateComponent, PieceOfNewsDeleteDialogComponent], | ||
14 | entryComponents: [PieceOfNewsDeleteDialogComponent] | ||
15 | }) | ||
16 | export class HonlapPieceOfNewsModule {} |
File src/main/webapp/app/entities/piece-of-news/piece-of-news.route.ts added (mode: 100644) (index 0000000..fdc8d76) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpResponse } from '@angular/common/http'; | ||
3 | import { Resolve, ActivatedRouteSnapshot, Routes, Router } from '@angular/router'; | ||
4 | import { JhiResolvePagingParams } from 'ng-jhipster'; | ||
5 | import { Observable, of, EMPTY } from 'rxjs'; | ||
6 | import { flatMap } from 'rxjs/operators'; | ||
7 | |||
8 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
9 | import { UserRouteAccessService } from 'app/core/auth/user-route-access-service'; | ||
10 | import { IPieceOfNews, PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
11 | import { PieceOfNewsService } from './piece-of-news.service'; | ||
12 | import { PieceOfNewsComponent } from './piece-of-news.component'; | ||
13 | import { PieceOfNewsDetailComponent } from './piece-of-news-detail.component'; | ||
14 | import { PieceOfNewsUpdateComponent } from './piece-of-news-update.component'; | ||
15 | |||
16 | @Injectable({ providedIn: 'root' }) | ||
17 | export class PieceOfNewsResolve implements Resolve<IPieceOfNews> { | ||
18 | constructor(private service: PieceOfNewsService, private router: Router) {} | ||
19 | |||
20 | resolve(route: ActivatedRouteSnapshot): Observable<IPieceOfNews> | Observable<never> { | ||
21 | const id = route.params['id']; | ||
22 | if (id) { | ||
23 | return this.service.find(id).pipe( | ||
24 | flatMap((pieceOfNews: HttpResponse<PieceOfNews>) => { | ||
25 | if (pieceOfNews.body) { | ||
26 | return of(pieceOfNews.body); | ||
27 | } else { | ||
28 | this.router.navigate(['404']); | ||
29 | return EMPTY; | ||
30 | } | ||
31 | }) | ||
32 | ); | ||
33 | } | ||
34 | return of(new PieceOfNews()); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | export const pieceOfNewsRoute: Routes = [ | ||
39 | { | ||
40 | path: '', | ||
41 | component: PieceOfNewsComponent, | ||
42 | resolve: { | ||
43 | pagingParams: JhiResolvePagingParams | ||
44 | }, | ||
45 | data: { | ||
46 | authorities: [Authority.USER], | ||
47 | defaultSort: 'id,asc', | ||
48 | pageTitle: 'honlapApp.pieceOfNews.home.title' | ||
49 | }, | ||
50 | canActivate: [UserRouteAccessService] | ||
51 | }, | ||
52 | { | ||
53 | path: ':id/view', | ||
54 | component: PieceOfNewsDetailComponent, | ||
55 | resolve: { | ||
56 | pieceOfNews: PieceOfNewsResolve | ||
57 | }, | ||
58 | data: { | ||
59 | authorities: [Authority.USER], | ||
60 | pageTitle: 'honlapApp.pieceOfNews.home.title' | ||
61 | }, | ||
62 | canActivate: [UserRouteAccessService] | ||
63 | }, | ||
64 | { | ||
65 | path: 'new', | ||
66 | component: PieceOfNewsUpdateComponent, | ||
67 | resolve: { | ||
68 | pieceOfNews: PieceOfNewsResolve | ||
69 | }, | ||
70 | data: { | ||
71 | authorities: [Authority.USER], | ||
72 | pageTitle: 'honlapApp.pieceOfNews.home.title' | ||
73 | }, | ||
74 | canActivate: [UserRouteAccessService] | ||
75 | }, | ||
76 | { | ||
77 | path: ':id/edit', | ||
78 | component: PieceOfNewsUpdateComponent, | ||
79 | resolve: { | ||
80 | pieceOfNews: PieceOfNewsResolve | ||
81 | }, | ||
82 | data: { | ||
83 | authorities: [Authority.USER], | ||
84 | pageTitle: 'honlapApp.pieceOfNews.home.title' | ||
85 | }, | ||
86 | canActivate: [UserRouteAccessService] | ||
87 | } | ||
88 | ]; |
File src/main/webapp/app/entities/piece-of-news/piece-of-news.service.ts added (mode: 100644) (index 0000000..3c460b2) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient, HttpResponse } from '@angular/common/http'; | ||
3 | import { Observable } from 'rxjs'; | ||
4 | import { map } from 'rxjs/operators'; | ||
5 | import * as moment from 'moment'; | ||
6 | |||
7 | import { SERVER_API_URL } from 'app/app.constants'; | ||
8 | import { createRequestOption } from 'app/shared/util/request-util'; | ||
9 | import { IPieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
10 | |||
11 | type EntityResponseType = HttpResponse<IPieceOfNews>; | ||
12 | type EntityArrayResponseType = HttpResponse<IPieceOfNews[]>; | ||
13 | |||
14 | @Injectable({ providedIn: 'root' }) | ||
15 | export class PieceOfNewsService { | ||
16 | public resourceUrl = SERVER_API_URL + 'api/piece-of-news'; | ||
17 | |||
18 | constructor(protected http: HttpClient) {} | ||
19 | |||
20 | create(pieceOfNews: IPieceOfNews): Observable<EntityResponseType> { | ||
21 | const copy = this.convertDateFromClient(pieceOfNews); | ||
22 | return this.http | ||
23 | .post<IPieceOfNews>(this.resourceUrl, copy, { observe: 'response' }) | ||
24 | .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); | ||
25 | } | ||
26 | |||
27 | update(pieceOfNews: IPieceOfNews): Observable<EntityResponseType> { | ||
28 | const copy = this.convertDateFromClient(pieceOfNews); | ||
29 | return this.http | ||
30 | .put<IPieceOfNews>(this.resourceUrl, copy, { observe: 'response' }) | ||
31 | .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); | ||
32 | } | ||
33 | |||
34 | find(id: number): Observable<EntityResponseType> { | ||
35 | return this.http | ||
36 | .get<IPieceOfNews>(`${this.resourceUrl}/${id}`, { observe: 'response' }) | ||
37 | .pipe(map((res: EntityResponseType) => this.convertDateFromServer(res))); | ||
38 | } | ||
39 | |||
40 | query(req?: any): Observable<EntityArrayResponseType> { | ||
41 | const options = createRequestOption(req); | ||
42 | return this.http | ||
43 | .get<IPieceOfNews[]>(this.resourceUrl, { params: options, observe: 'response' }) | ||
44 | .pipe(map((res: EntityArrayResponseType) => this.convertDateArrayFromServer(res))); | ||
45 | } | ||
46 | |||
47 | delete(id: number): Observable<HttpResponse<{}>> { | ||
48 | return this.http.delete(`${this.resourceUrl}/${id}`, { observe: 'response' }); | ||
49 | } | ||
50 | |||
51 | protected convertDateFromClient(pieceOfNews: IPieceOfNews): IPieceOfNews { | ||
52 | const copy: IPieceOfNews = Object.assign({}, pieceOfNews, { | ||
53 | newsDate: pieceOfNews.newsDate && pieceOfNews.newsDate.isValid() ? pieceOfNews.newsDate.toJSON() : undefined, | ||
54 | publishDate: pieceOfNews.publishDate && pieceOfNews.publishDate.isValid() ? pieceOfNews.publishDate.toJSON() : undefined, | ||
55 | createdDate: pieceOfNews.createdDate && pieceOfNews.createdDate.isValid() ? pieceOfNews.createdDate.toJSON() : undefined, | ||
56 | lastModifiedDate: | ||
57 | pieceOfNews.lastModifiedDate && pieceOfNews.lastModifiedDate.isValid() ? pieceOfNews.lastModifiedDate.toJSON() : undefined | ||
58 | }); | ||
59 | return copy; | ||
60 | } | ||
61 | |||
62 | protected convertDateFromServer(res: EntityResponseType): EntityResponseType { | ||
63 | if (res.body) { | ||
64 | res.body.newsDate = res.body.newsDate ? moment(res.body.newsDate) : undefined; | ||
65 | res.body.publishDate = res.body.publishDate ? moment(res.body.publishDate) : undefined; | ||
66 | res.body.createdDate = res.body.createdDate ? moment(res.body.createdDate) : undefined; | ||
67 | res.body.lastModifiedDate = res.body.lastModifiedDate ? moment(res.body.lastModifiedDate) : undefined; | ||
68 | } | ||
69 | return res; | ||
70 | } | ||
71 | |||
72 | protected convertDateArrayFromServer(res: EntityArrayResponseType): EntityArrayResponseType { | ||
73 | if (res.body) { | ||
74 | res.body.forEach((pieceOfNews: IPieceOfNews) => { | ||
75 | pieceOfNews.newsDate = pieceOfNews.newsDate ? moment(pieceOfNews.newsDate) : undefined; | ||
76 | pieceOfNews.publishDate = pieceOfNews.publishDate ? moment(pieceOfNews.publishDate) : undefined; | ||
77 | pieceOfNews.createdDate = pieceOfNews.createdDate ? moment(pieceOfNews.createdDate) : undefined; | ||
78 | pieceOfNews.lastModifiedDate = pieceOfNews.lastModifiedDate ? moment(pieceOfNews.lastModifiedDate) : undefined; | ||
79 | }); | ||
80 | } | ||
81 | return res; | ||
82 | } | ||
83 | } |
File src/main/webapp/app/home/home.component.html added (mode: 100644) (index 0000000..0f54094) | |||
1 | <div class="row"> | ||
2 | <div class="col-md-3"> | ||
3 | <span class="hipster img-fluid rounded"></span> | ||
4 | </div> | ||
5 | |||
6 | <div class="col-md-9"> | ||
7 | <h1 class="display-4" jhiTranslate="home.title">Welcome, Java Hipster!</h1> | ||
8 | |||
9 | <p class="lead" jhiTranslate="home.subtitle">This is your homepage</p> | ||
10 | |||
11 | <div [ngSwitch]="isAuthenticated()"> | ||
12 | <div class="alert alert-success" *ngSwitchCase="true"> | ||
13 | <span id="home-logged-message" *ngIf="account" jhiTranslate="home.logged.message" | ||
14 | [translateValues]="{ username: account.login }">You are logged in as user "{{ account.login }}".</span> | ||
15 | </div> | ||
16 | |||
17 | <div class="alert alert-warning" *ngSwitchCase="false"> | ||
18 | <span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span> | ||
19 | <a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span> | ||
20 | </div> | ||
21 | |||
22 | <div class="alert alert-warning" *ngSwitchCase="false"> | ||
23 | <span jhiTranslate="global.messages.info.register.noaccount">You don't have an account yet?</span> | ||
24 | <a class="alert-link" routerLink="account/register" jhiTranslate="global.messages.info.register.link">Register a new account</a> | ||
25 | </div> | ||
26 | </div> | ||
27 | |||
28 | <p jhiTranslate="home.question"> | ||
29 | If you have any question on JHipster: | ||
30 | </p> | ||
31 | |||
32 | <ul> | ||
33 | <li><a href="https://www.jhipster.tech/" target="_blank" rel="noopener noreferrer" jhiTranslate="home.link.homepage">JHipster homepage</a></li> | ||
34 | <li><a href="http://stackoverflow.com/tags/jhipster/info" target="_blank" rel="noopener noreferrer" jhiTranslate="home.link.stackoverflow">JHipster on Stack Overflow</a></li> | ||
35 | <li><a href="https://github.com/jhipster/generator-jhipster/issues?state=open" target="_blank" rel="noopener noreferrer" jhiTranslate="home.link.bugtracker">JHipster bug tracker</a></li> | ||
36 | <li><a href="https://gitter.im/jhipster/generator-jhipster" target="_blank" rel="noopener noreferrer" jhiTranslate="home.link.chat">JHipster public chat room</a></li> | ||
37 | <li><a href="https://twitter.com/jhipster" target="_blank" rel="noopener noreferrer" jhiTranslate="home.link.follow">follow @jhipster on Twitter</a></li> | ||
38 | </ul> | ||
39 | |||
40 | <p> | ||
41 | <span jhiTranslate="home.like">If you like JHipster, don't forget to give us a star on</span> <a href="https://github.com/jhipster/generator-jhipster" target="_blank" rel="noopener noreferrer" jhiTranslate="home.github">GitHub</a>! | ||
42 | </p> | ||
43 | </div> | ||
44 | </div> |
File src/main/webapp/app/home/home.component.ts added (mode: 100644) (index 0000000..9ef01af) | |||
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||
2 | import { Subscription } from 'rxjs'; | ||
3 | |||
4 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
5 | import { AccountService } from 'app/core/auth/account.service'; | ||
6 | import { Account } from 'app/core/user/account.model'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-home', | ||
10 | templateUrl: './home.component.html', | ||
11 | styleUrls: ['home.scss'] | ||
12 | }) | ||
13 | export class HomeComponent implements OnInit, OnDestroy { | ||
14 | account: Account | null = null; | ||
15 | authSubscription?: Subscription; | ||
16 | |||
17 | constructor(private accountService: AccountService, private loginModalService: LoginModalService) {} | ||
18 | |||
19 | ngOnInit(): void { | ||
20 | this.authSubscription = this.accountService.getAuthenticationState().subscribe(account => (this.account = account)); | ||
21 | } | ||
22 | |||
23 | isAuthenticated(): boolean { | ||
24 | return this.accountService.isAuthenticated(); | ||
25 | } | ||
26 | |||
27 | login(): void { | ||
28 | this.loginModalService.open(); | ||
29 | } | ||
30 | |||
31 | ngOnDestroy(): void { | ||
32 | if (this.authSubscription) { | ||
33 | this.authSubscription.unsubscribe(); | ||
34 | } | ||
35 | } | ||
36 | } |
File src/main/webapp/app/home/home.module.ts added (mode: 100644) (index 0000000..70efe12) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { RouterModule } from '@angular/router'; | ||
3 | |||
4 | import { HonlapSharedModule } from 'app/shared/shared.module'; | ||
5 | import { HOME_ROUTE } from './home.route'; | ||
6 | import { HomeComponent } from './home.component'; | ||
7 | |||
8 | @NgModule({ | ||
9 | imports: [HonlapSharedModule, RouterModule.forChild([HOME_ROUTE])], | ||
10 | declarations: [HomeComponent] | ||
11 | }) | ||
12 | export class HonlapHomeModule {} |
File src/main/webapp/app/home/home.route.ts added (mode: 100644) (index 0000000..aefa2b7) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { HomeComponent } from './home.component'; | ||
4 | |||
5 | export const HOME_ROUTE: Route = { | ||
6 | path: '', | ||
7 | component: HomeComponent, | ||
8 | data: { | ||
9 | authorities: [], | ||
10 | pageTitle: 'home.title' | ||
11 | } | ||
12 | }; |
File src/main/webapp/app/home/home.scss added (mode: 100644) (index 0000000..c731f12) | |||
1 | /* ========================================================================== | ||
2 | Main page styles | ||
3 | ========================================================================== */ | ||
4 | |||
5 | .hipster { | ||
6 | display: inline-block; | ||
7 | width: 347px; | ||
8 | height: 497px; | ||
9 | background: url('../../content/images/jhipster_family_member_0.svg') no-repeat center top; | ||
10 | background-size: contain; | ||
11 | } | ||
12 | |||
13 | /* wait autoprefixer update to allow simple generation of high pixel density media query */ | ||
14 | @media only screen and (-webkit-min-device-pixel-ratio: 2), | ||
15 | only screen and (-moz-min-device-pixel-ratio: 2), | ||
16 | only screen and (-o-min-device-pixel-ratio: 2/1), | ||
17 | only screen and (min-resolution: 192dpi), | ||
18 | only screen and (min-resolution: 2dppx) { | ||
19 | .hipster { | ||
20 | background: url('../../content/images/jhipster_family_member_0.svg') no-repeat center top; | ||
21 | background-size: contain; | ||
22 | } | ||
23 | } |
File src/main/webapp/app/layouts/error/error.component.html added (mode: 100644) (index 0000000..b51ae9d) | |||
1 | <div> | ||
2 | <div class="row"> | ||
3 | <div class="col-md-4"> | ||
4 | <span class="hipster img-fluid rounded"></span> | ||
5 | </div> | ||
6 | |||
7 | <div class="col-md-8"> | ||
8 | <h1 jhiTranslate="error.title">Error Page!</h1> | ||
9 | |||
10 | <div *ngIf="errorMessage"> | ||
11 | <div class="alert alert-danger">{{ errorMessage }}</div> | ||
12 | </div> | ||
13 | </div> | ||
14 | </div> | ||
15 | </div> |
File src/main/webapp/app/layouts/error/error.component.ts added (mode: 100644) (index 0000000..133a96b) | |||
1 | import { Component, OnInit, OnDestroy } from '@angular/core'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | import { Subscription } from 'rxjs'; | ||
4 | import { TranslateService } from '@ngx-translate/core'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-error', | ||
8 | templateUrl: './error.component.html' | ||
9 | }) | ||
10 | export class ErrorComponent implements OnInit, OnDestroy { | ||
11 | errorMessage?: string; | ||
12 | errorKey?: string; | ||
13 | langChangeSubscription?: Subscription; | ||
14 | |||
15 | constructor(private translateService: TranslateService, private route: ActivatedRoute) {} | ||
16 | |||
17 | ngOnInit(): void { | ||
18 | this.route.data.subscribe(routeData => { | ||
19 | if (routeData.errorMessage) { | ||
20 | this.errorKey = routeData.errorMessage; | ||
21 | this.getErrorMessageTranslation(); | ||
22 | this.langChangeSubscription = this.translateService.onLangChange.subscribe(() => this.getErrorMessageTranslation()); | ||
23 | } | ||
24 | }); | ||
25 | } | ||
26 | |||
27 | ngOnDestroy(): void { | ||
28 | if (this.langChangeSubscription) { | ||
29 | this.langChangeSubscription.unsubscribe(); | ||
30 | } | ||
31 | } | ||
32 | |||
33 | private getErrorMessageTranslation(): void { | ||
34 | this.errorMessage = ''; | ||
35 | if (this.errorKey) { | ||
36 | this.translateService.get(this.errorKey).subscribe(translatedErrorMessage => (this.errorMessage = translatedErrorMessage)); | ||
37 | } | ||
38 | } | ||
39 | } |
File src/main/webapp/app/layouts/error/error.route.ts added (mode: 100644) (index 0000000..4828cc7) | |||
1 | import { Routes } from '@angular/router'; | ||
2 | |||
3 | import { ErrorComponent } from './error.component'; | ||
4 | |||
5 | export const errorRoute: Routes = [ | ||
6 | { | ||
7 | path: 'error', | ||
8 | component: ErrorComponent, | ||
9 | data: { | ||
10 | authorities: [], | ||
11 | pageTitle: 'error.title' | ||
12 | } | ||
13 | }, | ||
14 | { | ||
15 | path: 'accessdenied', | ||
16 | component: ErrorComponent, | ||
17 | data: { | ||
18 | authorities: [], | ||
19 | pageTitle: 'error.title', | ||
20 | errorMessage: 'error.http.403' | ||
21 | } | ||
22 | }, | ||
23 | { | ||
24 | path: '404', | ||
25 | component: ErrorComponent, | ||
26 | data: { | ||
27 | authorities: [], | ||
28 | pageTitle: 'error.title', | ||
29 | errorMessage: 'error.http.404' | ||
30 | } | ||
31 | }, | ||
32 | { | ||
33 | path: '**', | ||
34 | redirectTo: '/404' | ||
35 | } | ||
36 | ]; |
File src/main/webapp/app/layouts/footer/footer.component.html added (mode: 100644) (index 0000000..9312ad0) | |||
1 | <div class="footer"> | ||
2 | <p jhiTranslate="footer">This is your footer</p> | ||
3 | </div> |
File src/main/webapp/app/layouts/footer/footer.component.ts added (mode: 100644) (index 0000000..53c8dde) | |||
1 | import { Component } from '@angular/core'; | ||
2 | |||
3 | @Component({ | ||
4 | selector: 'auth-footer', | ||
5 | templateUrl: './footer.component.html' | ||
6 | }) | ||
7 | export class FooterComponent {} |
File src/main/webapp/app/layouts/main/main.component.html added (mode: 100644) (index 0000000..fce6a43) | |||
1 | <auth-page-ribbon></auth-page-ribbon> | ||
2 | |||
3 | <div> | ||
4 | <router-outlet name="navbar"></router-outlet> | ||
5 | </div> | ||
6 | |||
7 | <div class="container-fluid"> | ||
8 | <div class="card jh-card"> | ||
9 | <router-outlet></router-outlet> | ||
10 | </div> | ||
11 | |||
12 | <auth-footer></auth-footer> | ||
13 | </div> |
File src/main/webapp/app/layouts/main/main.component.ts added (mode: 100644) (index 0000000..3c791eb) | |||
1 | import { Component, OnInit, RendererFactory2, Renderer2 } from '@angular/core'; | ||
2 | import { Title } from '@angular/platform-browser'; | ||
3 | import { Router, ActivatedRouteSnapshot, NavigationEnd, NavigationError } from '@angular/router'; | ||
4 | import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; | ||
5 | |||
6 | import { AccountService } from 'app/core/auth/account.service'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-main', | ||
10 | templateUrl: './main.component.html' | ||
11 | }) | ||
12 | export class MainComponent implements OnInit { | ||
13 | private renderer: Renderer2; | ||
14 | |||
15 | constructor( | ||
16 | private accountService: AccountService, | ||
17 | private titleService: Title, | ||
18 | private router: Router, | ||
19 | private translateService: TranslateService, | ||
20 | rootRenderer: RendererFactory2 | ||
21 | ) { | ||
22 | this.renderer = rootRenderer.createRenderer(document.querySelector('html'), null); | ||
23 | } | ||
24 | |||
25 | ngOnInit(): void { | ||
26 | // try to log in automatically | ||
27 | this.accountService.identity().subscribe(); | ||
28 | |||
29 | this.router.events.subscribe(event => { | ||
30 | if (event instanceof NavigationEnd) { | ||
31 | this.updateTitle(); | ||
32 | } | ||
33 | if (event instanceof NavigationError && event.error.status === 404) { | ||
34 | this.router.navigate(['/404']); | ||
35 | } | ||
36 | }); | ||
37 | |||
38 | this.translateService.onLangChange.subscribe((langChangeEvent: LangChangeEvent) => { | ||
39 | this.updateTitle(); | ||
40 | |||
41 | this.renderer.setAttribute(document.querySelector('html'), 'lang', langChangeEvent.lang); | ||
42 | }); | ||
43 | } | ||
44 | |||
45 | private getPageTitle(routeSnapshot: ActivatedRouteSnapshot): string { | ||
46 | let title: string = routeSnapshot.data && routeSnapshot.data['pageTitle'] ? routeSnapshot.data['pageTitle'] : ''; | ||
47 | if (routeSnapshot.firstChild) { | ||
48 | title = this.getPageTitle(routeSnapshot.firstChild) || title; | ||
49 | } | ||
50 | return title; | ||
51 | } | ||
52 | |||
53 | private updateTitle(): void { | ||
54 | let pageTitle = this.getPageTitle(this.router.routerState.snapshot.root); | ||
55 | if (!pageTitle) { | ||
56 | pageTitle = 'global.title'; | ||
57 | } | ||
58 | this.translateService.get(pageTitle).subscribe(title => this.titleService.setTitle(title)); | ||
59 | } | ||
60 | } |
File src/main/webapp/app/layouts/navbar/active-menu.directive.ts added (mode: 100644) (index 0000000..5915bd8) | |||
1 | import { Directive, OnInit, ElementRef, Renderer2, Input } from '@angular/core'; | ||
2 | import { TranslateService, LangChangeEvent } from '@ngx-translate/core'; | ||
3 | |||
4 | @Directive({ | ||
5 | selector: '[authActiveMenu]' | ||
6 | }) | ||
7 | export class ActiveMenuDirective implements OnInit { | ||
8 | @Input() authActiveMenu?: string; | ||
9 | |||
10 | constructor(private el: ElementRef, private renderer: Renderer2, private translateService: TranslateService) {} | ||
11 | |||
12 | ngOnInit(): void { | ||
13 | this.translateService.onLangChange.subscribe((event: LangChangeEvent) => { | ||
14 | this.updateActiveFlag(event.lang); | ||
15 | }); | ||
16 | |||
17 | this.updateActiveFlag(this.translateService.currentLang); | ||
18 | } | ||
19 | |||
20 | updateActiveFlag(selectedLanguage: string): void { | ||
21 | if (this.authActiveMenu === selectedLanguage) { | ||
22 | this.renderer.addClass(this.el.nativeElement, 'active'); | ||
23 | } else { | ||
24 | this.renderer.removeClass(this.el.nativeElement, 'active'); | ||
25 | } | ||
26 | } | ||
27 | } |
File src/main/webapp/app/layouts/navbar/navbar.component.html added (mode: 100644) (index 0000000..4375f3f) | |||
1 | <nav class="navbar navbar-dark navbar-expand-md bg-dark"> | ||
2 | <a class="navbar-brand logo" routerLink="/" (click)="collapseNavbar()"> | ||
3 | <span class="logo-img"></span> | ||
4 | <span jhiTranslate="global.title" class="navbar-title">Honlap</span> <span class="navbar-version">{{ version }}</span> | ||
5 | </a> | ||
6 | <a class="navbar-toggler d-lg-none" href="javascript:void(0);" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation" (click)="toggleNavbar()"> | ||
7 | <fa-icon icon="bars"></fa-icon> | ||
8 | </a> | ||
9 | <div class="navbar-collapse collapse" id="navbarResponsive" [ngbCollapse]="isNavbarCollapsed" [ngSwitch]="isAuthenticated()"> | ||
10 | <ul class="navbar-nav ml-auto"> | ||
11 | <li class="nav-item" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> | ||
12 | <a class="nav-link" routerLink="/" (click)="collapseNavbar()"> | ||
13 | <span> | ||
14 | <fa-icon icon="home"></fa-icon> | ||
15 | <span jhiTranslate="global.menu.home">Home</span> | ||
16 | </span> | ||
17 | </a> | ||
18 | </li> | ||
19 | <!-- jhipster-needle-add-element-to-menu - JHipster will add new menu items here --> | ||
20 | <li *ngSwitchCase="true" ngbDropdown class="nav-item dropdown pointer" display="dynamic" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> | ||
21 | <a class="nav-link dropdown-toggle" ngbDropdownToggle href="javascript:void(0);" id="entity-menu"> | ||
22 | <span> | ||
23 | <fa-icon icon="th-list"></fa-icon> | ||
24 | <span jhiTranslate="global.menu.entities.main"> | ||
25 | Entities | ||
26 | </span> | ||
27 | </span> | ||
28 | </a> | ||
29 | <ul class="dropdown-menu" ngbDropdownMenu aria-labelledby="entity-menu"> | ||
30 | <li> | ||
31 | <a class="dropdown-item" routerLink="piece-of-news" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }" (click)="collapseNavbar()"> | ||
32 | <fa-icon icon="asterisk" fixedWidth="true"></fa-icon> | ||
33 | <span jhiTranslate="global.menu.entities.pieceOfNews">Piece Of News</span> | ||
34 | </a> | ||
35 | </li> | ||
36 | <!-- jhipster-needle-add-entity-to-menu - JHipster will add entities to the menu here --> | ||
37 | </ul> | ||
38 | </li> | ||
39 | <li *authHasAnyAuthority="'ROLE_ADMIN'" ngbDropdown class="nav-item dropdown pointer" display="dynamic" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> | ||
40 | <a class="nav-link dropdown-toggle" ngbDropdownToggle href="javascript:void(0);" id="admin-menu"> | ||
41 | <span> | ||
42 | <fa-icon icon="user-plus"></fa-icon> | ||
43 | <span jhiTranslate="global.menu.admin.main">Administration</span> | ||
44 | </span> | ||
45 | </a> | ||
46 | <ul class="dropdown-menu" ngbDropdownMenu aria-labelledby="admin-menu"> | ||
47 | <li> | ||
48 | <a class="dropdown-item" routerLink="admin/user-management" routerLinkActive="active" (click)="collapseNavbar()"> | ||
49 | <fa-icon icon="user" fixedWidth="true"></fa-icon> | ||
50 | <span jhiTranslate="global.menu.admin.userManagement">User management</span> | ||
51 | </a> | ||
52 | </li> | ||
53 | <li> | ||
54 | <a class="dropdown-item" routerLink="admin/metrics" routerLinkActive="active" (click)="collapseNavbar()"> | ||
55 | <fa-icon icon="tachometer-alt" fixedWidth="true"></fa-icon> | ||
56 | <span jhiTranslate="global.menu.admin.metrics">Metrics</span> | ||
57 | </a> | ||
58 | </li> | ||
59 | <li> | ||
60 | <a class="dropdown-item" routerLink="admin/health" routerLinkActive="active" (click)="collapseNavbar()"> | ||
61 | <fa-icon icon="heart" fixedWidth="true"></fa-icon> | ||
62 | <span jhiTranslate="global.menu.admin.health">Health</span> | ||
63 | </a> | ||
64 | </li> | ||
65 | <li> | ||
66 | <a class="dropdown-item" routerLink="admin/configuration" routerLinkActive="active" (click)="collapseNavbar()"> | ||
67 | <fa-icon icon="list" fixedWidth="true"></fa-icon> | ||
68 | <span jhiTranslate="global.menu.admin.configuration">Configuration</span> | ||
69 | </a> | ||
70 | </li> | ||
71 | <li> | ||
72 | <a class="dropdown-item" routerLink="admin/audits" routerLinkActive="active" (click)="collapseNavbar()"> | ||
73 | <fa-icon icon="bell" fixedWidth="true"></fa-icon> | ||
74 | <span jhiTranslate="global.menu.admin.audits">Audits</span> | ||
75 | </a> | ||
76 | </li> | ||
77 | <li> | ||
78 | <a class="dropdown-item" routerLink="admin/logs" routerLinkActive="active" (click)="collapseNavbar()"> | ||
79 | <fa-icon icon="tasks" fixedWidth="true"></fa-icon> | ||
80 | <span jhiTranslate="global.menu.admin.logs">Logs</span> | ||
81 | </a> | ||
82 | </li> | ||
83 | <li *ngIf="swaggerEnabled"> | ||
84 | <a class="dropdown-item" routerLink="admin/docs" routerLinkActive="active" (click)="collapseNavbar()"> | ||
85 | <fa-icon icon="book" fixedWidth="true"></fa-icon> | ||
86 | <span jhiTranslate="global.menu.admin.apidocs">API</span> | ||
87 | </a> | ||
88 | </li> | ||
89 | <!-- jhipster-needle-add-element-to-admin-menu - JHipster will add entities to the admin menu here --> | ||
90 | <li *ngIf="!inProduction"> | ||
91 | <a class="dropdown-item" href='./h2-console' target="_tab" (click)="collapseNavbar()"> | ||
92 | <fa-icon icon="hdd" fixedWidth="true"></fa-icon> | ||
93 | <span jhiTranslate="global.menu.admin.database">Database</span> | ||
94 | </a> | ||
95 | </li> | ||
96 | </ul> | ||
97 | </li> | ||
98 | <li ngbDropdown class="nav-item dropdown pointer" display="dynamic" *ngIf="languages && languages.length > 1"> | ||
99 | <a class="nav-link dropdown-toggle" ngbDropdownToggle href="javascript:void(0);" id="languagesnavBarDropdown"> | ||
100 | <span> | ||
101 | <fa-icon icon="flag"></fa-icon> | ||
102 | <span jhiTranslate="global.menu.language">Language</span> | ||
103 | </span> | ||
104 | </a> | ||
105 | <ul class="dropdown-menu" ngbDropdownMenu aria-labelledby="languagesnavBarDropdown"> | ||
106 | <li *ngFor="let language of languages"> | ||
107 | <a class="dropdown-item" [authActiveMenu]="language" href="javascript:void(0);" (click)="changeLanguage(language);collapseNavbar();">{{ language | findLanguageFromKey }}</a> | ||
108 | </li> | ||
109 | </ul> | ||
110 | </li> | ||
111 | <li ngbDropdown class="nav-item dropdown pointer" display="dynamic" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"> | ||
112 | <a class="nav-link dropdown-toggle" ngbDropdownToggle href="javascript:void(0);" id="account-menu"> | ||
113 | <span *ngIf="!getImageUrl()"> | ||
114 | <fa-icon icon="user"></fa-icon> | ||
115 | <span jhiTranslate="global.menu.account.main"> | ||
116 | Account | ||
117 | </span> | ||
118 | </span> | ||
119 | <span *ngIf="getImageUrl()"> | ||
120 | <img [src]="getImageUrl()" class="profile-image rounded-circle" alt="Avatar"> | ||
121 | </span> | ||
122 | </a> | ||
123 | <ul class="dropdown-menu" ngbDropdownMenu aria-labelledby="account-menu"> | ||
124 | <li *ngSwitchCase="true"> | ||
125 | <a class="dropdown-item" routerLink="account/settings" routerLinkActive="active" (click)="collapseNavbar()"> | ||
126 | <fa-icon icon="wrench" fixedWidth="true"></fa-icon> | ||
127 | <span jhiTranslate="global.menu.account.settings">Settings</span> | ||
128 | </a> | ||
129 | </li> | ||
130 | <li *ngSwitchCase="true"> | ||
131 | <a class="dropdown-item" routerLink="account/password" routerLinkActive="active" (click)="collapseNavbar()"> | ||
132 | <fa-icon icon="lock" fixedWidth="true"></fa-icon> | ||
133 | <span jhiTranslate="global.menu.account.password">Password</span> | ||
134 | </a> | ||
135 | </li> | ||
136 | <li *ngSwitchCase="true"> | ||
137 | <a class="dropdown-item" (click)="logout()" id="logout"> | ||
138 | <fa-icon icon="sign-out-alt" fixedWidth="true"></fa-icon> | ||
139 | <span jhiTranslate="global.menu.account.logout">Sign out</span> | ||
140 | </a> | ||
141 | </li> | ||
142 | <li *ngSwitchCase="false"> | ||
143 | <a class="dropdown-item" (click)="login()" id="login"> | ||
144 | <fa-icon icon="sign-in-alt" fixedWidth="true"></fa-icon> | ||
145 | <span jhiTranslate="global.menu.account.login">Sign in</span> | ||
146 | </a> | ||
147 | </li> | ||
148 | <li *ngSwitchCase="false"> | ||
149 | <a class="dropdown-item" routerLink="account/register" routerLinkActive="active" (click)="collapseNavbar()"> | ||
150 | <fa-icon icon="user-plus" fixedWidth="true"></fa-icon> | ||
151 | <span jhiTranslate="global.menu.account.register">Register</span> | ||
152 | </a> | ||
153 | </li> | ||
154 | </ul> | ||
155 | </li> | ||
156 | </ul> | ||
157 | </div> | ||
158 | </nav> |
File src/main/webapp/app/layouts/navbar/navbar.component.ts added (mode: 100644) (index 0000000..93f7f08) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { Router } from '@angular/router'; | ||
3 | import { JhiLanguageService } from 'ng-jhipster'; | ||
4 | import { SessionStorageService } from 'ngx-webstorage'; | ||
5 | |||
6 | import { VERSION } from 'app/app.constants'; | ||
7 | import { LANGUAGES } from 'app/core/language/language.constants'; | ||
8 | import { AccountService } from 'app/core/auth/account.service'; | ||
9 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
10 | import { LoginService } from 'app/core/login/login.service'; | ||
11 | import { ProfileService } from 'app/layouts/profiles/profile.service'; | ||
12 | |||
13 | @Component({ | ||
14 | selector: 'auth-navbar', | ||
15 | templateUrl: './navbar.component.html', | ||
16 | styleUrls: ['navbar.scss'] | ||
17 | }) | ||
18 | export class NavbarComponent implements OnInit { | ||
19 | inProduction?: boolean; | ||
20 | isNavbarCollapsed = true; | ||
21 | languages = LANGUAGES; | ||
22 | swaggerEnabled?: boolean; | ||
23 | version: string; | ||
24 | |||
25 | constructor( | ||
26 | private loginService: LoginService, | ||
27 | private languageService: JhiLanguageService, | ||
28 | private sessionStorage: SessionStorageService, | ||
29 | private accountService: AccountService, | ||
30 | private loginModalService: LoginModalService, | ||
31 | private profileService: ProfileService, | ||
32 | private router: Router | ||
33 | ) { | ||
34 | this.version = VERSION ? (VERSION.toLowerCase().startsWith('v') ? VERSION : 'v' + VERSION) : ''; | ||
35 | } | ||
36 | |||
37 | ngOnInit(): void { | ||
38 | this.profileService.getProfileInfo().subscribe(profileInfo => { | ||
39 | this.inProduction = profileInfo.inProduction; | ||
40 | this.swaggerEnabled = profileInfo.swaggerEnabled; | ||
41 | }); | ||
42 | } | ||
43 | |||
44 | changeLanguage(languageKey: string): void { | ||
45 | this.sessionStorage.store('locale', languageKey); | ||
46 | this.languageService.changeLanguage(languageKey); | ||
47 | } | ||
48 | |||
49 | collapseNavbar(): void { | ||
50 | this.isNavbarCollapsed = true; | ||
51 | } | ||
52 | |||
53 | isAuthenticated(): boolean { | ||
54 | return this.accountService.isAuthenticated(); | ||
55 | } | ||
56 | |||
57 | login(): void { | ||
58 | this.loginModalService.open(); | ||
59 | } | ||
60 | |||
61 | logout(): void { | ||
62 | this.collapseNavbar(); | ||
63 | this.loginService.logout(); | ||
64 | this.router.navigate(['']); | ||
65 | } | ||
66 | |||
67 | toggleNavbar(): void { | ||
68 | this.isNavbarCollapsed = !this.isNavbarCollapsed; | ||
69 | } | ||
70 | |||
71 | getImageUrl(): string { | ||
72 | return this.isAuthenticated() ? this.accountService.getImageUrl() : ''; | ||
73 | } | ||
74 | } |
File src/main/webapp/app/layouts/navbar/navbar.route.ts added (mode: 100644) (index 0000000..3519143) | |||
1 | import { Route } from '@angular/router'; | ||
2 | |||
3 | import { NavbarComponent } from './navbar.component'; | ||
4 | |||
5 | export const navbarRoute: Route = { | ||
6 | path: '', | ||
7 | component: NavbarComponent, | ||
8 | outlet: 'navbar' | ||
9 | }; |
File src/main/webapp/app/layouts/navbar/navbar.scss added (mode: 100644) (index 0000000..1ff209b) | |||
1 | @import '~bootstrap/scss/functions'; | ||
2 | @import '~bootstrap/scss/variables'; | ||
3 | |||
4 | /* ========================================================================== | ||
5 | Navbar | ||
6 | ========================================================================== */ | ||
7 | |||
8 | .navbar-version { | ||
9 | font-size: 0.65em; | ||
10 | color: $navbar-dark-color; | ||
11 | } | ||
12 | |||
13 | .profile-image { | ||
14 | height: 1.75em; | ||
15 | width: 1.75em; | ||
16 | } | ||
17 | |||
18 | .navbar { | ||
19 | padding: 0.2rem 1rem; | ||
20 | |||
21 | ul.navbar-nav { | ||
22 | .nav-item { | ||
23 | margin-left: 0.5em; | ||
24 | } | ||
25 | } | ||
26 | |||
27 | a.nav-link { | ||
28 | font-weight: 400; | ||
29 | } | ||
30 | } | ||
31 | |||
32 | /* ========================================================================== | ||
33 | Logo styles | ||
34 | ========================================================================== */ | ||
35 | .logo-img { | ||
36 | height: 45px; | ||
37 | width: 45px; | ||
38 | display: inline-block; | ||
39 | vertical-align: middle; | ||
40 | background: url('../../../content/images/logo-jhipster.png') no-repeat center center; | ||
41 | background-size: contain; | ||
42 | } |
File src/main/webapp/app/layouts/profiles/page-ribbon.component.ts added (mode: 100644) (index 0000000..66fc245) | |||
1 | import { Component, OnInit } from '@angular/core'; | ||
2 | import { Observable } from 'rxjs'; | ||
3 | import { map } from 'rxjs/operators'; | ||
4 | import { ProfileService } from './profile.service'; | ||
5 | |||
6 | @Component({ | ||
7 | selector: 'auth-page-ribbon', | ||
8 | template: ` | ||
9 | <div class="ribbon" *ngIf="ribbonEnv$ | async as ribbonEnv"> | ||
10 | <a href="" jhiTranslate="global.ribbon.{{ ribbonEnv }}">{{ ribbonEnv }}</a> | ||
11 | </div> | ||
12 | `, | ||
13 | styleUrls: ['page-ribbon.scss'] | ||
14 | }) | ||
15 | export class PageRibbonComponent implements OnInit { | ||
16 | ribbonEnv$?: Observable<string | undefined>; | ||
17 | |||
18 | constructor(private profileService: ProfileService) {} | ||
19 | |||
20 | ngOnInit(): void { | ||
21 | this.ribbonEnv$ = this.profileService.getProfileInfo().pipe(map(profileInfo => profileInfo.ribbonEnv)); | ||
22 | } | ||
23 | } |
File src/main/webapp/app/layouts/profiles/page-ribbon.scss added (mode: 100644) (index 0000000..a78f268) | |||
1 | /* ========================================================================== | ||
2 | Developement Ribbon | ||
3 | ========================================================================== */ | ||
4 | .ribbon { | ||
5 | background-color: rgba(170, 0, 0, 0.5); | ||
6 | left: -3.5em; | ||
7 | -moz-transform: rotate(-45deg); | ||
8 | -ms-transform: rotate(-45deg); | ||
9 | -o-transform: rotate(-45deg); | ||
10 | -webkit-transform: rotate(-45deg); | ||
11 | transform: rotate(-45deg); | ||
12 | overflow: hidden; | ||
13 | position: absolute; | ||
14 | top: 40px; | ||
15 | white-space: nowrap; | ||
16 | width: 15em; | ||
17 | z-index: 9999; | ||
18 | pointer-events: none; | ||
19 | opacity: 0.75; | ||
20 | a { | ||
21 | color: #fff; | ||
22 | display: block; | ||
23 | font-weight: 400; | ||
24 | margin: 1px 0; | ||
25 | padding: 10px 50px; | ||
26 | text-align: center; | ||
27 | text-decoration: none; | ||
28 | text-shadow: 0 0 5px #444; | ||
29 | pointer-events: none; | ||
30 | } | ||
31 | } |
File src/main/webapp/app/layouts/profiles/profile-info.model.ts added (mode: 100644) (index 0000000..e7763ee) | |||
1 | export interface InfoResponse { | ||
2 | 'display-ribbon-on-profiles'?: string; | ||
3 | git?: any; | ||
4 | build?: any; | ||
5 | activeProfiles?: string[]; | ||
6 | } | ||
7 | |||
8 | export class ProfileInfo { | ||
9 | constructor( | ||
10 | public activeProfiles?: string[], | ||
11 | public ribbonEnv?: string, | ||
12 | public inProduction?: boolean, | ||
13 | public swaggerEnabled?: boolean | ||
14 | ) {} | ||
15 | } |
File src/main/webapp/app/layouts/profiles/profile.service.ts added (mode: 100644) (index 0000000..f1512d3) | |||
1 | import { Injectable } from '@angular/core'; | ||
2 | import { HttpClient } from '@angular/common/http'; | ||
3 | import { map, shareReplay } from 'rxjs/operators'; | ||
4 | import { Observable } from 'rxjs'; | ||
5 | |||
6 | import { SERVER_API_URL } from 'app/app.constants'; | ||
7 | import { ProfileInfo, InfoResponse } from './profile-info.model'; | ||
8 | |||
9 | @Injectable({ providedIn: 'root' }) | ||
10 | export class ProfileService { | ||
11 | private infoUrl = SERVER_API_URL + 'management/info'; | ||
12 | private profileInfo$!: Observable<ProfileInfo>; | ||
13 | |||
14 | constructor(private http: HttpClient) {} | ||
15 | |||
16 | getProfileInfo(): Observable<ProfileInfo> { | ||
17 | if (this.profileInfo$) { | ||
18 | return this.profileInfo$; | ||
19 | } | ||
20 | |||
21 | this.profileInfo$ = this.http.get<InfoResponse>(this.infoUrl).pipe( | ||
22 | map((response: InfoResponse) => { | ||
23 | const profileInfo: ProfileInfo = { | ||
24 | activeProfiles: response.activeProfiles, | ||
25 | inProduction: response.activeProfiles && response.activeProfiles.includes('prod'), | ||
26 | swaggerEnabled: response.activeProfiles && response.activeProfiles.includes('swagger') | ||
27 | }; | ||
28 | if (response.activeProfiles && response['display-ribbon-on-profiles']) { | ||
29 | const displayRibbonOnProfiles = response['display-ribbon-on-profiles'].split(','); | ||
30 | const ribbonProfiles = displayRibbonOnProfiles.filter( | ||
31 | profile => response.activeProfiles && response.activeProfiles.includes(profile) | ||
32 | ); | ||
33 | if (ribbonProfiles.length > 0) { | ||
34 | profileInfo.ribbonEnv = ribbonProfiles[0]; | ||
35 | } | ||
36 | } | ||
37 | return profileInfo; | ||
38 | }), | ||
39 | shareReplay() | ||
40 | ); | ||
41 | return this.profileInfo$; | ||
42 | } | ||
43 | } |
File src/main/webapp/app/polyfills.ts added (mode: 100644) (index 0000000..f8a8d65) | |||
1 | import 'zone.js/dist/zone'; | ||
2 | import '@angular/localize/init'; | ||
3 | require('../manifest.webapp'); |
File src/main/webapp/app/shared/alert/alert-error.component.ts added (mode: 100644) (index 0000000..712c90a) | |||
1 | import { Component, OnDestroy } from '@angular/core'; | ||
2 | import { HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { TranslateService } from '@ngx-translate/core'; | ||
4 | import { JhiEventManager, JhiAlert, JhiAlertService, JhiEventWithContent } from 'ng-jhipster'; | ||
5 | import { Subscription } from 'rxjs'; | ||
6 | |||
7 | import { AlertError } from './alert-error.model'; | ||
8 | |||
9 | @Component({ | ||
10 | selector: 'auth-alert-error', | ||
11 | template: ` | ||
12 | <div class="alerts" role="alert"> | ||
13 | <div *ngFor="let alert of alerts" [ngClass]="setClasses(alert)"> | ||
14 | <ngb-alert *ngIf="alert && alert.type && alert.msg" [type]="alert.type" (close)="alert.close(alerts)"> | ||
15 | <pre [innerHTML]="alert.msg"></pre> | ||
16 | </ngb-alert> | ||
17 | </div> | ||
18 | </div> | ||
19 | ` | ||
20 | }) | ||
21 | export class AlertErrorComponent implements OnDestroy { | ||
22 | alerts: JhiAlert[] = []; | ||
23 | errorListener: Subscription; | ||
24 | httpErrorListener: Subscription; | ||
25 | |||
26 | constructor(private alertService: JhiAlertService, private eventManager: JhiEventManager, translateService: TranslateService) { | ||
27 | this.errorListener = eventManager.subscribe('honlapApp.error', (response: JhiEventWithContent<AlertError>) => { | ||
28 | const errorResponse = response.content; | ||
29 | this.addErrorAlert(errorResponse.message, errorResponse.key, errorResponse.params); | ||
30 | }); | ||
31 | |||
32 | this.httpErrorListener = eventManager.subscribe('honlapApp.httpError', (response: JhiEventWithContent<HttpErrorResponse>) => { | ||
33 | const httpErrorResponse = response.content; | ||
34 | switch (httpErrorResponse.status) { | ||
35 | // connection refused, server not reachable | ||
36 | case 0: | ||
37 | this.addErrorAlert('Server not reachable', 'error.server.not.reachable'); | ||
38 | break; | ||
39 | |||
40 | case 400: { | ||
41 | const arr = httpErrorResponse.headers.keys(); | ||
42 | let errorHeader = null; | ||
43 | let entityKey = null; | ||
44 | arr.forEach(entry => { | ||
45 | if (entry.toLowerCase().endsWith('app-error')) { | ||
46 | errorHeader = httpErrorResponse.headers.get(entry); | ||
47 | } else if (entry.toLowerCase().endsWith('app-params')) { | ||
48 | entityKey = httpErrorResponse.headers.get(entry); | ||
49 | } | ||
50 | }); | ||
51 | if (errorHeader) { | ||
52 | const entityName = translateService.instant('global.menu.entities.' + entityKey); | ||
53 | this.addErrorAlert(errorHeader, errorHeader, { entityName }); | ||
54 | } else if (httpErrorResponse.error !== '' && httpErrorResponse.error.fieldErrors) { | ||
55 | const fieldErrors = httpErrorResponse.error.fieldErrors; | ||
56 | for (const fieldError of fieldErrors) { | ||
57 | if (['Min', 'Max', 'DecimalMin', 'DecimalMax'].includes(fieldError.message)) { | ||
58 | fieldError.message = 'Size'; | ||
59 | } | ||
60 | // convert 'something[14].other[4].id' to 'something[].other[].id' so translations can be written to it | ||
61 | const convertedField = fieldError.field.replace(/\[\d*\]/g, '[]'); | ||
62 | const fieldName = translateService.instant('honlapApp.' + fieldError.objectName + '.' + convertedField); | ||
63 | this.addErrorAlert('Error on field "' + fieldName + '"', 'error.' + fieldError.message, { fieldName }); | ||
64 | } | ||
65 | } else if (httpErrorResponse.error !== '' && httpErrorResponse.error.message) { | ||
66 | this.addErrorAlert(httpErrorResponse.error.message, httpErrorResponse.error.message, httpErrorResponse.error.params); | ||
67 | } else { | ||
68 | this.addErrorAlert(httpErrorResponse.error); | ||
69 | } | ||
70 | break; | ||
71 | } | ||
72 | |||
73 | case 404: | ||
74 | this.addErrorAlert('Not found', 'error.url.not.found'); | ||
75 | break; | ||
76 | |||
77 | default: | ||
78 | if (httpErrorResponse.error !== '' && httpErrorResponse.error.message) { | ||
79 | this.addErrorAlert(httpErrorResponse.error.message); | ||
80 | } else { | ||
81 | this.addErrorAlert(httpErrorResponse.error); | ||
82 | } | ||
83 | } | ||
84 | }); | ||
85 | } | ||
86 | |||
87 | setClasses(alert: JhiAlert): { [key: string]: boolean } { | ||
88 | const classes = { 'jhi-toast': Boolean(alert.toast) }; | ||
89 | if (alert.position) { | ||
90 | return { ...classes, [alert.position]: true }; | ||
91 | } | ||
92 | return classes; | ||
93 | } | ||
94 | |||
95 | ngOnDestroy(): void { | ||
96 | if (this.errorListener) { | ||
97 | this.eventManager.destroy(this.errorListener); | ||
98 | } | ||
99 | if (this.httpErrorListener) { | ||
100 | this.eventManager.destroy(this.httpErrorListener); | ||
101 | } | ||
102 | } | ||
103 | |||
104 | addErrorAlert(message: string, key?: string, data?: any): void { | ||
105 | message = key && key !== null ? key : message; | ||
106 | |||
107 | const newAlert: JhiAlert = { | ||
108 | type: 'danger', | ||
109 | msg: message, | ||
110 | params: data, | ||
111 | timeout: 5000, | ||
112 | toast: this.alertService.isToast(), | ||
113 | scoped: true | ||
114 | }; | ||
115 | |||
116 | this.alerts.push(this.alertService.addAlert(newAlert, this.alerts)); | ||
117 | } | ||
118 | } |
File src/main/webapp/app/shared/alert/alert-error.model.ts added (mode: 100644) (index 0000000..e76241a) | |||
1 | export class AlertError { | ||
2 | constructor(public message: string, public key?: string, public params?: any) {} | ||
3 | } |
File src/main/webapp/app/shared/alert/alert.component.ts added (mode: 100644) (index 0000000..0f13b15) | |||
1 | import { Component, OnDestroy, OnInit } from '@angular/core'; | ||
2 | import { JhiAlertService, JhiAlert } from 'ng-jhipster'; | ||
3 | |||
4 | @Component({ | ||
5 | selector: 'auth-alert', | ||
6 | template: ` | ||
7 | <div class="alerts" role="alert"> | ||
8 | <div *ngFor="let alert of alerts" [ngClass]="setClasses(alert)"> | ||
9 | <ngb-alert *ngIf="alert && alert.type && alert.msg" [type]="alert.type" (close)="alert.close(alerts)"> | ||
10 | <pre [innerHTML]="alert.msg"></pre> | ||
11 | </ngb-alert> | ||
12 | </div> | ||
13 | </div> | ||
14 | ` | ||
15 | }) | ||
16 | export class AlertComponent implements OnInit, OnDestroy { | ||
17 | alerts: JhiAlert[] = []; | ||
18 | |||
19 | constructor(private alertService: JhiAlertService) {} | ||
20 | |||
21 | ngOnInit(): void { | ||
22 | this.alerts = this.alertService.get(); | ||
23 | } | ||
24 | |||
25 | setClasses(alert: JhiAlert): { [key: string]: boolean } { | ||
26 | const classes = { 'jhi-toast': Boolean(alert.toast) }; | ||
27 | if (alert.position) { | ||
28 | return { ...classes, [alert.position]: true }; | ||
29 | } | ||
30 | return classes; | ||
31 | } | ||
32 | |||
33 | ngOnDestroy(): void { | ||
34 | this.alertService.clear(); | ||
35 | } | ||
36 | } |
File src/main/webapp/app/shared/auth/has-any-authority.directive.ts added (mode: 100644) (index 0000000..43b97c4) | |||
1 | import { Directive, Input, TemplateRef, ViewContainerRef, OnDestroy } from '@angular/core'; | ||
2 | import { Subscription } from 'rxjs'; | ||
3 | |||
4 | import { AccountService } from 'app/core/auth/account.service'; | ||
5 | |||
6 | /** | ||
7 | * @whatItDoes Conditionally includes an HTML element if current user has any | ||
8 | * of the authorities passed as the `expression`. | ||
9 | * | ||
10 | * @howToUse | ||
11 | * ``` | ||
12 | * <some-element *authHasAnyAuthority="'ROLE_ADMIN'">...</some-element> | ||
13 | * | ||
14 | * <some-element *authHasAnyAuthority="['ROLE_ADMIN', 'ROLE_USER']">...</some-element> | ||
15 | * ``` | ||
16 | */ | ||
17 | @Directive({ | ||
18 | selector: '[authHasAnyAuthority]' | ||
19 | }) | ||
20 | export class HasAnyAuthorityDirective implements OnDestroy { | ||
21 | private authorities: string[] = []; | ||
22 | private authenticationSubscription?: Subscription; | ||
23 | |||
24 | constructor(private accountService: AccountService, private templateRef: TemplateRef<any>, private viewContainerRef: ViewContainerRef) {} | ||
25 | |||
26 | @Input() | ||
27 | set authHasAnyAuthority(value: string | string[]) { | ||
28 | this.authorities = typeof value === 'string' ? [value] : value; | ||
29 | this.updateView(); | ||
30 | // Get notified each time authentication state changes. | ||
31 | this.authenticationSubscription = this.accountService.getAuthenticationState().subscribe(() => this.updateView()); | ||
32 | } | ||
33 | |||
34 | ngOnDestroy(): void { | ||
35 | if (this.authenticationSubscription) { | ||
36 | this.authenticationSubscription.unsubscribe(); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | private updateView(): void { | ||
41 | const hasAnyAuthority = this.accountService.hasAnyAuthority(this.authorities); | ||
42 | this.viewContainerRef.clear(); | ||
43 | if (hasAnyAuthority) { | ||
44 | this.viewContainerRef.createEmbeddedView(this.templateRef); | ||
45 | } | ||
46 | } | ||
47 | } |
File src/main/webapp/app/shared/constants/authority.constants.ts added (mode: 100644) (index 0000000..9f672ce) | |||
1 | export enum Authority { | ||
2 | ADMIN = 'ROLE_ADMIN', | ||
3 | USER = 'ROLE_USER' | ||
4 | } |
File src/main/webapp/app/shared/constants/error.constants.ts added (mode: 100644) (index 0000000..42d91d9) | |||
1 | export const PROBLEM_BASE_URL = 'https://www.jhipster.tech/problem'; | ||
2 | export const EMAIL_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/email-already-used'; | ||
3 | export const LOGIN_ALREADY_USED_TYPE = PROBLEM_BASE_URL + '/login-already-used'; |
File src/main/webapp/app/shared/constants/input.constants.ts added (mode: 100644) (index 0000000..1e3978a) | |||
1 | export const DATE_FORMAT = 'YYYY-MM-DD'; | ||
2 | export const DATE_TIME_FORMAT = 'YYYY-MM-DDTHH:mm'; |
File src/main/webapp/app/shared/constants/pagination.constants.ts added (mode: 100644) (index 0000000..a148d45) | |||
1 | export const ITEMS_PER_PAGE = 20; |
File src/main/webapp/app/shared/language/find-language-from-key.pipe.ts added (mode: 100644) (index 0000000..cb52a3e) | |||
1 | import { Pipe, PipeTransform } from '@angular/core'; | ||
2 | |||
3 | @Pipe({ name: 'findLanguageFromKey' }) | ||
4 | export class FindLanguageFromKeyPipe implements PipeTransform { | ||
5 | private languages: { [key: string]: { name: string; rtl?: boolean } } = { | ||
6 | en: { name: 'English' }, | ||
7 | hu: { name: 'Magyar' } | ||
8 | // jhipster-needle-i18n-language-key-pipe - JHipster will add/remove languages in this object | ||
9 | }; | ||
10 | |||
11 | transform(lang: string): string { | ||
12 | return this.languages[lang].name; | ||
13 | } | ||
14 | } |
File src/main/webapp/app/shared/login/login.component.html added (mode: 100644) (index 0000000..dcd23c1) | |||
1 | <div class="modal-header"> | ||
2 | <h4 class="modal-title" jhiTranslate="login.title">Sign in</h4> | ||
3 | |||
4 | <button aria-label="Close" data-dismiss="modal" class="close" type="button" (click)="activeModal.dismiss('closed')"> | ||
5 | <span aria-hidden="true">x</span> | ||
6 | </button> | ||
7 | </div> | ||
8 | |||
9 | <div class="modal-body"> | ||
10 | <div class="row justify-content-center"> | ||
11 | <div class="col-md-8"> | ||
12 | <div class="alert alert-danger" *ngIf="authenticationError" jhiTranslate="login.messages.error.authentication"> | ||
13 | <strong>Failed to sign in!</strong> Please check your credentials and try again. | ||
14 | </div> | ||
15 | </div> | ||
16 | |||
17 | <div class="col-md-8"> | ||
18 | <form class="form" role="form" (ngSubmit)="login()" [formGroup]="loginForm"> | ||
19 | <div class="form-group"> | ||
20 | <label class="username-label" for="username" jhiTranslate="global.form.username.label">Login</label> | ||
21 | <input type="text" class="form-control" name="username" id="username" placeholder="{{ 'global.form.username.placeholder' | translate }}" | ||
22 | formControlName="username" #username> | ||
23 | </div> | ||
24 | |||
25 | <div class="form-group"> | ||
26 | <label for="password" jhiTranslate="login.form.password">Password</label> | ||
27 | <input type="password" class="form-control" name="password" id="password" placeholder="{{ 'login.form.password.placeholder' | translate }}" | ||
28 | formControlName="password"> | ||
29 | </div> | ||
30 | |||
31 | <div class="form-check"> | ||
32 | <label class="form-check-label" for="rememberMe"> | ||
33 | <input class="form-check-input" type="checkbox" name="rememberMe" id="rememberMe" formControlName="rememberMe"> | ||
34 | <span jhiTranslate="login.form.rememberme">Remember me</span> | ||
35 | </label> | ||
36 | </div> | ||
37 | |||
38 | <button type="submit" class="btn btn-primary" jhiTranslate="login.form.button">Sign in</button> | ||
39 | </form> | ||
40 | |||
41 | <div class="mt-3 alert alert-warning"> | ||
42 | <a class="alert-link" (click)="requestResetPassword()" jhiTranslate="login.password.forgot">Did you forget your password?</a> | ||
43 | </div> | ||
44 | |||
45 | <div class="alert alert-warning"> | ||
46 | <span jhiTranslate="global.messages.info.register.noaccount">You don't have an account yet?</span> | ||
47 | <a class="alert-link" (click)="register()" jhiTranslate="global.messages.info.register.link">Register a new account</a> | ||
48 | </div> | ||
49 | </div> | ||
50 | </div> | ||
51 | </div> |
File src/main/webapp/app/shared/login/login.component.ts added (mode: 100644) (index 0000000..24183ce) | |||
1 | import { Component, AfterViewInit, ElementRef, ViewChild } from '@angular/core'; | ||
2 | import { FormBuilder } from '@angular/forms'; | ||
3 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
4 | import { Router } from '@angular/router'; | ||
5 | |||
6 | import { LoginService } from 'app/core/login/login.service'; | ||
7 | |||
8 | @Component({ | ||
9 | selector: 'auth-login-modal', | ||
10 | templateUrl: './login.component.html' | ||
11 | }) | ||
12 | export class LoginModalComponent implements AfterViewInit { | ||
13 | @ViewChild('username', { static: false }) | ||
14 | username?: ElementRef; | ||
15 | |||
16 | authenticationError = false; | ||
17 | |||
18 | loginForm = this.fb.group({ | ||
19 | username: [''], | ||
20 | password: [''], | ||
21 | rememberMe: [false] | ||
22 | }); | ||
23 | |||
24 | constructor(private loginService: LoginService, private router: Router, public activeModal: NgbActiveModal, private fb: FormBuilder) {} | ||
25 | |||
26 | ngAfterViewInit(): void { | ||
27 | if (this.username) { | ||
28 | this.username.nativeElement.focus(); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | cancel(): void { | ||
33 | this.authenticationError = false; | ||
34 | this.loginForm.patchValue({ | ||
35 | username: '', | ||
36 | password: '' | ||
37 | }); | ||
38 | this.activeModal.dismiss('cancel'); | ||
39 | } | ||
40 | |||
41 | login(): void { | ||
42 | this.loginService | ||
43 | .login({ | ||
44 | username: this.loginForm.get('username')!.value, | ||
45 | password: this.loginForm.get('password')!.value, | ||
46 | rememberMe: this.loginForm.get('rememberMe')!.value | ||
47 | }) | ||
48 | .subscribe( | ||
49 | () => { | ||
50 | this.authenticationError = false; | ||
51 | this.activeModal.close(); | ||
52 | if ( | ||
53 | this.router.url === '/account/register' || | ||
54 | this.router.url.startsWith('/account/activate') || | ||
55 | this.router.url.startsWith('/account/reset/') | ||
56 | ) { | ||
57 | this.router.navigate(['']); | ||
58 | } | ||
59 | }, | ||
60 | () => (this.authenticationError = true) | ||
61 | ); | ||
62 | } | ||
63 | |||
64 | register(): void { | ||
65 | this.activeModal.dismiss('to state register'); | ||
66 | this.router.navigate(['/account/register']); | ||
67 | } | ||
68 | |||
69 | requestResetPassword(): void { | ||
70 | this.activeModal.dismiss('to state requestReset'); | ||
71 | this.router.navigate(['/account/reset', 'request']); | ||
72 | } | ||
73 | } |
File src/main/webapp/app/shared/model/piece-of-news.model.ts added (mode: 100644) (index 0000000..b7cef07) | |||
1 | import { Moment } from 'moment'; | ||
2 | |||
3 | export interface IPieceOfNews { | ||
4 | id?: number; | ||
5 | appId?: number; | ||
6 | newsDate?: Moment; | ||
7 | headline?: string; | ||
8 | content?: string; | ||
9 | link?: string; | ||
10 | publishDate?: Moment; | ||
11 | createdBy?: string; | ||
12 | createdDate?: Moment; | ||
13 | lastModifiedBy?: string; | ||
14 | lastModifiedDate?: Moment; | ||
15 | } | ||
16 | |||
17 | export class PieceOfNews implements IPieceOfNews { | ||
18 | constructor( | ||
19 | public id?: number, | ||
20 | public appId?: number, | ||
21 | public newsDate?: Moment, | ||
22 | public headline?: string, | ||
23 | public content?: string, | ||
24 | public link?: string, | ||
25 | public publishDate?: Moment, | ||
26 | public createdBy?: string, | ||
27 | public createdDate?: Moment, | ||
28 | public lastModifiedBy?: string, | ||
29 | public lastModifiedDate?: Moment | ||
30 | ) {} | ||
31 | } |
File src/main/webapp/app/shared/shared-libs.module.ts added (mode: 100644) (index 0000000..609736f) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { CommonModule } from '@angular/common'; | ||
3 | import { FormsModule, ReactiveFormsModule } from '@angular/forms'; | ||
4 | import { NgbModule } from '@ng-bootstrap/ng-bootstrap'; | ||
5 | import { NgJhipsterModule } from 'ng-jhipster'; | ||
6 | import { InfiniteScrollModule } from 'ngx-infinite-scroll'; | ||
7 | import { FontAwesomeModule } from '@fortawesome/angular-fontawesome'; | ||
8 | import { TranslateModule } from '@ngx-translate/core'; | ||
9 | |||
10 | @NgModule({ | ||
11 | exports: [ | ||
12 | FormsModule, | ||
13 | CommonModule, | ||
14 | NgbModule, | ||
15 | NgJhipsterModule, | ||
16 | InfiniteScrollModule, | ||
17 | FontAwesomeModule, | ||
18 | ReactiveFormsModule, | ||
19 | TranslateModule | ||
20 | ] | ||
21 | }) | ||
22 | export class HonlapSharedLibsModule {} |
File src/main/webapp/app/shared/shared.module.ts added (mode: 100644) (index 0000000..2dc0a43) | |||
1 | import { NgModule } from '@angular/core'; | ||
2 | import { HonlapSharedLibsModule } from './shared-libs.module'; | ||
3 | import { FindLanguageFromKeyPipe } from './language/find-language-from-key.pipe'; | ||
4 | import { AlertComponent } from './alert/alert.component'; | ||
5 | import { AlertErrorComponent } from './alert/alert-error.component'; | ||
6 | import { LoginModalComponent } from './login/login.component'; | ||
7 | import { HasAnyAuthorityDirective } from './auth/has-any-authority.directive'; | ||
8 | |||
9 | @NgModule({ | ||
10 | imports: [HonlapSharedLibsModule], | ||
11 | declarations: [FindLanguageFromKeyPipe, AlertComponent, AlertErrorComponent, LoginModalComponent, HasAnyAuthorityDirective], | ||
12 | entryComponents: [LoginModalComponent], | ||
13 | exports: [ | ||
14 | HonlapSharedLibsModule, | ||
15 | FindLanguageFromKeyPipe, | ||
16 | AlertComponent, | ||
17 | AlertErrorComponent, | ||
18 | LoginModalComponent, | ||
19 | HasAnyAuthorityDirective | ||
20 | ] | ||
21 | }) | ||
22 | export class HonlapSharedModule {} |
File src/main/webapp/app/shared/util/datepicker-adapter.ts added (mode: 100644) (index 0000000..027f123) | |||
1 | /** | ||
2 | * Angular bootstrap Date adapter | ||
3 | */ | ||
4 | import { Injectable } from '@angular/core'; | ||
5 | import { NgbDateAdapter, NgbDateStruct } from '@ng-bootstrap/ng-bootstrap'; | ||
6 | import { Moment } from 'moment'; | ||
7 | import * as moment from 'moment'; | ||
8 | |||
9 | @Injectable() | ||
10 | export class NgbDateMomentAdapter extends NgbDateAdapter<Moment> { | ||
11 | fromModel(date: Moment): NgbDateStruct { | ||
12 | if (date && moment.isMoment(date) && date.isValid()) { | ||
13 | return { year: date.year(), month: date.month() + 1, day: date.date() }; | ||
14 | } | ||
15 | // ! can be removed after https://github.com/ng-bootstrap/ng-bootstrap/issues/1544 is resolved | ||
16 | return null!; | ||
17 | } | ||
18 | |||
19 | toModel(date: NgbDateStruct): Moment { | ||
20 | // ! after null can be removed after https://github.com/ng-bootstrap/ng-bootstrap/issues/1544 is resolved | ||
21 | return date ? moment(date.year + '-' + date.month + '-' + date.day, 'YYYY-MM-DD') : null!; | ||
22 | } | ||
23 | } |
File src/main/webapp/app/shared/util/request-util.ts added (mode: 100644) (index 0000000..f839fd6) | |||
1 | import { HttpParams } from '@angular/common/http'; | ||
2 | |||
3 | export interface Pagination { | ||
4 | page: number; | ||
5 | size: number; | ||
6 | sort: string[]; | ||
7 | } | ||
8 | |||
9 | export interface Search { | ||
10 | query: string; | ||
11 | } | ||
12 | |||
13 | export interface SearchWithPagination extends Search, Pagination {} | ||
14 | |||
15 | export const createRequestOption = (req?: any): HttpParams => { | ||
16 | let options: HttpParams = new HttpParams(); | ||
17 | |||
18 | if (req) { | ||
19 | Object.keys(req).forEach(key => { | ||
20 | if (key !== 'sort') { | ||
21 | options = options.set(key, req[key]); | ||
22 | } | ||
23 | }); | ||
24 | |||
25 | if (req.sort) { | ||
26 | req.sort.forEach((val: string) => { | ||
27 | options = options.append('sort', val); | ||
28 | }); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | return options; | ||
33 | }; |
File src/main/webapp/app/vendor.ts added (mode: 100644) (index 0000000..a89c6da) | |||
1 | /* after changing this file run 'npm run webpack:build' */ | ||
2 | import '../content/scss/vendor.scss'; |
File src/main/webapp/content/css/loading.css added (mode: 100644) (index 0000000..b2c6626) | |||
1 | @keyframes lds-pacman-1 { | ||
2 | 0% { | ||
3 | -webkit-transform: rotate(0deg); | ||
4 | transform: rotate(0deg); | ||
5 | } | ||
6 | 50% { | ||
7 | -webkit-transform: rotate(-45deg); | ||
8 | transform: rotate(-45deg); | ||
9 | } | ||
10 | 100% { | ||
11 | -webkit-transform: rotate(0deg); | ||
12 | transform: rotate(0deg); | ||
13 | } | ||
14 | } | ||
15 | @-webkit-keyframes lds-pacman-1 { | ||
16 | 0% { | ||
17 | -webkit-transform: rotate(0deg); | ||
18 | transform: rotate(0deg); | ||
19 | } | ||
20 | 50% { | ||
21 | -webkit-transform: rotate(-45deg); | ||
22 | transform: rotate(-45deg); | ||
23 | } | ||
24 | 100% { | ||
25 | -webkit-transform: rotate(0deg); | ||
26 | transform: rotate(0deg); | ||
27 | } | ||
28 | } | ||
29 | @keyframes lds-pacman-2 { | ||
30 | 0% { | ||
31 | -webkit-transform: rotate(180deg); | ||
32 | transform: rotate(180deg); | ||
33 | } | ||
34 | 50% { | ||
35 | -webkit-transform: rotate(225deg); | ||
36 | transform: rotate(225deg); | ||
37 | } | ||
38 | 100% { | ||
39 | -webkit-transform: rotate(180deg); | ||
40 | transform: rotate(180deg); | ||
41 | } | ||
42 | } | ||
43 | @-webkit-keyframes lds-pacman-2 { | ||
44 | 0% { | ||
45 | -webkit-transform: rotate(180deg); | ||
46 | transform: rotate(180deg); | ||
47 | } | ||
48 | 50% { | ||
49 | -webkit-transform: rotate(225deg); | ||
50 | transform: rotate(225deg); | ||
51 | } | ||
52 | 100% { | ||
53 | -webkit-transform: rotate(180deg); | ||
54 | transform: rotate(180deg); | ||
55 | } | ||
56 | } | ||
57 | @keyframes lds-pacman-3 { | ||
58 | 0% { | ||
59 | -webkit-transform: translate(190px, 0); | ||
60 | transform: translate(190px, 0); | ||
61 | opacity: 0; | ||
62 | } | ||
63 | 20% { | ||
64 | opacity: 1; | ||
65 | } | ||
66 | 100% { | ||
67 | -webkit-transform: translate(70px, 0); | ||
68 | transform: translate(70px, 0); | ||
69 | opacity: 1; | ||
70 | } | ||
71 | } | ||
72 | @-webkit-keyframes lds-pacman-3 { | ||
73 | 0% { | ||
74 | -webkit-transform: translate(190px, 0); | ||
75 | transform: translate(190px, 0); | ||
76 | opacity: 0; | ||
77 | } | ||
78 | 20% { | ||
79 | opacity: 1; | ||
80 | } | ||
81 | 100% { | ||
82 | -webkit-transform: translate(70px, 0); | ||
83 | transform: translate(70px, 0); | ||
84 | opacity: 1; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | .app-loading { | ||
89 | font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; | ||
90 | position: relative; | ||
91 | display: flex; | ||
92 | flex-direction: column; | ||
93 | align-items: center; | ||
94 | justify-content: center; | ||
95 | top: 10em; | ||
96 | } | ||
97 | .app-loading p { | ||
98 | display: block; | ||
99 | font-size: 1.17em; | ||
100 | margin-inline-start: 0px; | ||
101 | margin-inline-end: 0px; | ||
102 | font-weight: normal; | ||
103 | } | ||
104 | |||
105 | .app-loading .lds-pacman { | ||
106 | position: relative; | ||
107 | margin: auto; | ||
108 | width: 200px !important; | ||
109 | height: 200px !important; | ||
110 | -webkit-transform: translate(-100px, -100px) scale(1) translate(100px, 100px); | ||
111 | transform: translate(-100px, -100px) scale(1) translate(100px, 100px); | ||
112 | } | ||
113 | .app-loading .lds-pacman > div:nth-child(2) div { | ||
114 | position: absolute; | ||
115 | top: 40px; | ||
116 | left: 40px; | ||
117 | width: 120px; | ||
118 | height: 60px; | ||
119 | border-radius: 120px 120px 0 0; | ||
120 | background: #bbcedd; | ||
121 | -webkit-animation: lds-pacman-1 1s linear infinite; | ||
122 | animation: lds-pacman-1 1s linear infinite; | ||
123 | -webkit-transform-origin: 60px 60px; | ||
124 | transform-origin: 60px 60px; | ||
125 | } | ||
126 | .app-loading .lds-pacman > div:nth-child(2) div:nth-child(2) { | ||
127 | -webkit-animation: lds-pacman-2 1s linear infinite; | ||
128 | animation: lds-pacman-2 1s linear infinite; | ||
129 | } | ||
130 | .app-loading .lds-pacman > div:nth-child(1) div { | ||
131 | position: absolute; | ||
132 | top: 97px; | ||
133 | left: -8px; | ||
134 | width: 24px; | ||
135 | height: 10px; | ||
136 | background-image: url('../images/logo-jhipster.png'); | ||
137 | background-size: contain; | ||
138 | -webkit-animation: lds-pacman-3 1s linear infinite; | ||
139 | animation: lds-pacman-3 1.5s linear infinite; | ||
140 | } | ||
141 | .app-loading .lds-pacman > div:nth-child(1) div:nth-child(1) { | ||
142 | -webkit-animation-delay: -0.67s; | ||
143 | animation-delay: -1s; | ||
144 | } | ||
145 | .app-loading .lds-pacman > div:nth-child(1) div:nth-child(2) { | ||
146 | -webkit-animation-delay: -0.33s; | ||
147 | animation-delay: -0.5s; | ||
148 | } | ||
149 | .app-loading .lds-pacman > div:nth-child(1) div:nth-child(3) { | ||
150 | -webkit-animation-delay: 0s; | ||
151 | animation-delay: 0s; | ||
152 | } |
File src/main/webapp/content/images/jhipster_family_member_0.svg added (mode: 100644) (index 0000000..d6df83c) |
File src/main/webapp/content/images/jhipster_family_member_0_head-192.png added (mode: 100644) (index 0000000..6d90ab3) |
File src/main/webapp/content/images/jhipster_family_member_0_head-256.png added (mode: 100644) (index 0000000..8e99bfe) |
File src/main/webapp/content/images/jhipster_family_member_0_head-384.png added (mode: 100644) (index 0000000..c7ca460) |
File src/main/webapp/content/images/jhipster_family_member_0_head-512.png added (mode: 100644) (index 0000000..7e0b843) |
File src/main/webapp/content/images/jhipster_family_member_1.svg added (mode: 100644) (index 0000000..e3a0f3d) |
File src/main/webapp/content/images/jhipster_family_member_1_head-192.png added (mode: 100644) (index 0000000..ac5f2a0) |
File src/main/webapp/content/images/jhipster_family_member_1_head-256.png added (mode: 100644) (index 0000000..443822e) |
File src/main/webapp/content/images/jhipster_family_member_1_head-384.png added (mode: 100644) (index 0000000..4a5e9fe) |
File src/main/webapp/content/images/jhipster_family_member_1_head-512.png added (mode: 100644) (index 0000000..66c625c) |
File src/main/webapp/content/images/jhipster_family_member_2.svg added (mode: 100644) (index 0000000..51c6a5a) |
File src/main/webapp/content/images/jhipster_family_member_2_head-192.png added (mode: 100644) (index 0000000..24baf78) |
File src/main/webapp/content/images/jhipster_family_member_2_head-256.png added (mode: 100644) (index 0000000..7b25f52) |
File src/main/webapp/content/images/jhipster_family_member_2_head-384.png added (mode: 100644) (index 0000000..e89e120) |
File src/main/webapp/content/images/jhipster_family_member_2_head-512.png added (mode: 100644) (index 0000000..3c0e6cb) |
File src/main/webapp/content/images/jhipster_family_member_3.svg added (mode: 100644) (index 0000000..cc0d01f) |
File src/main/webapp/content/images/jhipster_family_member_3_head-192.png added (mode: 100644) (index 0000000..b1e4fb3) |
File src/main/webapp/content/images/jhipster_family_member_3_head-256.png added (mode: 100644) (index 0000000..aa058c7) |
File src/main/webapp/content/images/jhipster_family_member_3_head-384.png added (mode: 100644) (index 0000000..1d10bd5) |
File src/main/webapp/content/images/jhipster_family_member_3_head-512.png added (mode: 100644) (index 0000000..e719f1d) |
File src/main/webapp/content/images/logo-jhipster.png added (mode: 100644) (index 0000000..6a005bf) |
File src/main/webapp/content/scss/_bootstrap-variables.scss added (mode: 100644) (index 0000000..a64158a) | |||
1 | /* | ||
2 | * Bootstrap overrides https://getbootstrap.com/docs/4.0/getting-started/theming/ | ||
3 | * All values defined in bootstrap source | ||
4 | * https://github.com/twbs/bootstrap/blob/v4-dev/scss/_variables.scss can be overwritten here | ||
5 | * Make sure not to add !default to values here | ||
6 | */ | ||
7 | |||
8 | // Colors: | ||
9 | // Grayscale and brand colors for use across Bootstrap. | ||
10 | |||
11 | $primary: #3e8acc; | ||
12 | $success: #28a745; | ||
13 | $info: #17a2b8; | ||
14 | $warning: #ffc107; | ||
15 | $danger: #dc3545; | ||
16 | |||
17 | // Options: | ||
18 | // Quickly modify global styling by enabling or disabling optional features. | ||
19 | $enable-rounded: true; | ||
20 | $enable-shadows: false; | ||
21 | $enable-gradients: false; | ||
22 | $enable-transitions: true; | ||
23 | $enable-hover-media-query: false; | ||
24 | $enable-grid-classes: true; | ||
25 | $enable-print-styles: true; | ||
26 | |||
27 | // Components: | ||
28 | // Define common padding and border radius sizes and more. | ||
29 | |||
30 | $border-radius: 0.15rem; | ||
31 | $border-radius-lg: 0.125rem; | ||
32 | $border-radius-sm: 0.1rem; | ||
33 | |||
34 | // Body: | ||
35 | // Settings for the `<body>` element. | ||
36 | |||
37 | $body-bg: #e4e5e6; | ||
38 | |||
39 | // Typography: | ||
40 | // Font, line-height, and color for body text, headings, and more. | ||
41 | |||
42 | $font-size-base: 1rem; | ||
43 | |||
44 | $dropdown-link-hover-color: white; | ||
45 | $dropdown-link-hover-bg: #343a40; |
File src/main/webapp/content/scss/global.scss added (mode: 100644) (index 0000000..543a62c) | |||
1 | @import 'bootstrap-variables'; | ||
2 | @import '~bootstrap/scss/functions'; | ||
3 | @import '~bootstrap/scss/variables'; | ||
4 | |||
5 | /* ============================================================== | ||
6 | Bootstrap tweaks | ||
7 | ===============================================================*/ | ||
8 | |||
9 | body, | ||
10 | h1, | ||
11 | h2, | ||
12 | h3, | ||
13 | h4 { | ||
14 | font-weight: 300; | ||
15 | } | ||
16 | |||
17 | /* Increase contrast of links to get 100% on Lighthouse Accessability Audit. Override this color if you want to change the link color, or use a Bootswatch theme */ | ||
18 | a { | ||
19 | color: #533f03; | ||
20 | font-weight: bold; | ||
21 | } | ||
22 | |||
23 | a:hover { | ||
24 | color: #533f03; | ||
25 | } | ||
26 | |||
27 | /* override hover color for dropdown-item forced by bootstrap to all a:not([href]):not([tabindex]) elements in _reboot.scss */ | ||
28 | a:not([href]):not([tabindex]):hover.dropdown-item { | ||
29 | color: $dropdown-link-hover-color; | ||
30 | } | ||
31 | |||
32 | /* override .dropdown-item.active background-color on hover */ | ||
33 | .dropdown-item.active:hover { | ||
34 | background-color: mix($dropdown-link-hover-bg, $dropdown-link-active-bg, 50%); | ||
35 | } | ||
36 | |||
37 | a:hover { | ||
38 | /* make sure browsers use the pointer cursor for anchors, even with no href */ | ||
39 | cursor: pointer; | ||
40 | } | ||
41 | |||
42 | .dropdown-item:hover { | ||
43 | color: $dropdown-link-hover-color; | ||
44 | } | ||
45 | |||
46 | /* ========================================================================== | ||
47 | Browser Upgrade Prompt | ||
48 | ========================================================================== */ | ||
49 | .browserupgrade { | ||
50 | margin: 0.2em 0; | ||
51 | background: #ccc; | ||
52 | color: #000; | ||
53 | padding: 0.2em 0; | ||
54 | } | ||
55 | |||
56 | /* ========================================================================== | ||
57 | Generic styles | ||
58 | ========================================================================== */ | ||
59 | |||
60 | /* Error highlight on input fields */ | ||
61 | .ng-valid[required], | ||
62 | .ng-valid.required { | ||
63 | border-left: 5px solid green; | ||
64 | } | ||
65 | |||
66 | .ng-invalid:not(form) { | ||
67 | border-left: 5px solid red; | ||
68 | } | ||
69 | |||
70 | /* other generic styles */ | ||
71 | |||
72 | .jh-card { | ||
73 | padding: 1.5%; | ||
74 | margin-top: 20px; | ||
75 | border: none; | ||
76 | } | ||
77 | |||
78 | .error { | ||
79 | color: white; | ||
80 | background-color: red; | ||
81 | } | ||
82 | |||
83 | .pad { | ||
84 | padding: 10px; | ||
85 | } | ||
86 | |||
87 | .w-40 { | ||
88 | width: 40% !important; | ||
89 | } | ||
90 | |||
91 | .w-60 { | ||
92 | width: 60% !important; | ||
93 | } | ||
94 | |||
95 | .break { | ||
96 | white-space: normal; | ||
97 | word-break: break-all; | ||
98 | } | ||
99 | |||
100 | .readonly { | ||
101 | background-color: #eee; | ||
102 | opacity: 1; | ||
103 | } | ||
104 | |||
105 | .footer { | ||
106 | border-top: 1px solid rgba(0, 0, 0, 0.125); | ||
107 | } | ||
108 | |||
109 | .hand, | ||
110 | [jhisortby] { | ||
111 | cursor: pointer; | ||
112 | } | ||
113 | |||
114 | /* ========================================================================== | ||
115 | Custom alerts for notification | ||
116 | ========================================================================== */ | ||
117 | .alerts { | ||
118 | .alert { | ||
119 | text-overflow: ellipsis; | ||
120 | pre { | ||
121 | background: none; | ||
122 | border: none; | ||
123 | font: inherit; | ||
124 | color: inherit; | ||
125 | padding: 0; | ||
126 | margin: 0; | ||
127 | } | ||
128 | .popover pre { | ||
129 | font-size: 10px; | ||
130 | } | ||
131 | } | ||
132 | .jhi-toast { | ||
133 | position: fixed; | ||
134 | width: 100%; | ||
135 | &.left { | ||
136 | left: 5px; | ||
137 | } | ||
138 | &.right { | ||
139 | right: 5px; | ||
140 | } | ||
141 | &.top { | ||
142 | top: 55px; | ||
143 | } | ||
144 | &.bottom { | ||
145 | bottom: 55px; | ||
146 | } | ||
147 | } | ||
148 | } | ||
149 | |||
150 | @media screen and (min-width: 480px) { | ||
151 | .alerts .jhi-toast { | ||
152 | width: 50%; | ||
153 | } | ||
154 | } | ||
155 | |||
156 | /* ========================================================================== | ||
157 | entity detail page css | ||
158 | ========================================================================== */ | ||
159 | .row.jh-entity-details > { | ||
160 | dd { | ||
161 | margin-bottom: 15px; | ||
162 | } | ||
163 | } | ||
164 | |||
165 | @media screen and (min-width: 768px) { | ||
166 | .row.jh-entity-details > { | ||
167 | dt { | ||
168 | margin-bottom: 15px; | ||
169 | } | ||
170 | dd { | ||
171 | border-bottom: 1px solid #eee; | ||
172 | padding-left: 180px; | ||
173 | margin-left: 0; | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | |||
178 | /* ========================================================================== | ||
179 | ui bootstrap tweaks | ||
180 | ========================================================================== */ | ||
181 | .nav, | ||
182 | .pagination, | ||
183 | .carousel, | ||
184 | .panel-title a { | ||
185 | cursor: pointer; | ||
186 | } | ||
187 | |||
188 | .thread-dump-modal-lock { | ||
189 | max-width: 450px; | ||
190 | overflow: hidden; | ||
191 | text-overflow: ellipsis; | ||
192 | white-space: nowrap; | ||
193 | } | ||
194 | |||
195 | /* jhipster-needle-scss-add-main JHipster will add new css style */ |
File src/main/webapp/content/scss/vendor.scss added (mode: 100644) (index 0000000..31688d0) | |||
1 | /* after changing this file run 'npm run webpack:build' */ | ||
2 | |||
3 | /*************************** | ||
4 | put Sass variables here: | ||
5 | eg $input-color: red; | ||
6 | ****************************/ | ||
7 | // Override Bootstrap variables | ||
8 | @import 'bootstrap-variables'; | ||
9 | // Import Bootstrap source files from node_modules | ||
10 | @import '~bootstrap/scss/bootstrap'; | ||
11 | |||
12 | /* jhipster-needle-scss-add-vendor JHipster will add new css style */ |
File src/main/webapp/favicon.ico added (mode: 100644) (index 0000000..4179874) |
File src/main/webapp/i18n/en/activate.json added (mode: 100644) (index 0000000..058bd49) | |||
1 | { | ||
2 | "activate": { | ||
3 | "title": "Activation", | ||
4 | "messages": { | ||
5 | "success": "<strong>Your user account has been activated.</strong> Please ", | ||
6 | "error": "<strong>Your user could not be activated.</strong> Please use the registration form to sign up." | ||
7 | } | ||
8 | } | ||
9 | } |
File src/main/webapp/i18n/en/audits.json added (mode: 100644) (index 0000000..8af22b2) | |||
1 | { | ||
2 | "audits": { | ||
3 | "title": "Audits", | ||
4 | "filter": { | ||
5 | "title": "Filter per date", | ||
6 | "from": "from", | ||
7 | "to": "to", | ||
8 | "button": { | ||
9 | "weeks": "Weeks", | ||
10 | "today": "today", | ||
11 | "clear": "clear", | ||
12 | "close": "close" | ||
13 | } | ||
14 | }, | ||
15 | "table": { | ||
16 | "header": { | ||
17 | "principal": "User", | ||
18 | "date": "Date", | ||
19 | "status": "State", | ||
20 | "data": "Extra data" | ||
21 | }, | ||
22 | "data": { | ||
23 | "remoteAddress": "Remote Address:" | ||
24 | } | ||
25 | }, | ||
26 | "notFound": "No audit found" | ||
27 | } | ||
28 | } |
File src/main/webapp/i18n/en/configuration.json added (mode: 100644) (index 0000000..09c9a1a) | |||
1 | { | ||
2 | "configuration": { | ||
3 | "title": "Configuration", | ||
4 | "filter": "Filter (by prefix)", | ||
5 | "table": { | ||
6 | "prefix": "Prefix", | ||
7 | "properties": "Properties" | ||
8 | } | ||
9 | } | ||
10 | } |
File src/main/webapp/i18n/en/error.json added (mode: 100644) (index 0000000..d257563) | |||
1 | { | ||
2 | "error": { | ||
3 | "title": "Error page!", | ||
4 | "http": { | ||
5 | "400": "Bad request.", | ||
6 | "403": "You are not authorized to access this page.", | ||
7 | "404": "The page does not exist.", | ||
8 | "405": "The HTTP verb you used is not supported for this URL.", | ||
9 | "500": "Internal server error." | ||
10 | }, | ||
11 | "concurrencyFailure": "Another user modified this data at the same time as you. Your changes were rejected.", | ||
12 | "validation": "Validation error on the server." | ||
13 | } | ||
14 | } |
File src/main/webapp/i18n/en/global.json added (mode: 100644) (index 0000000..31905f2) | |||
1 | { | ||
2 | "global": { | ||
3 | "title": "Honlap", | ||
4 | "browsehappy": "You are using an <strong>outdated</strong> browser. Please <a href=\"http://browsehappy.com/?locale=en\">upgrade your browser</a> to improve your experience.", | ||
5 | "menu": { | ||
6 | "home": "Home", | ||
7 | "jhipster-needle-menu-add-element": "JHipster will add additional menu entries here (do not translate!)", | ||
8 | "entities": { | ||
9 | "main": "Entities", | ||
10 | "pieceOfNews": "Piece Of News", | ||
11 | "jhipster-needle-menu-add-entry": "JHipster will add additional entities here (do not translate!)" | ||
12 | }, | ||
13 | "account": { | ||
14 | "main": "Account", | ||
15 | "settings": "Settings", | ||
16 | "password": "Password", | ||
17 | "sessions": "Sessions", | ||
18 | "login": "Sign in", | ||
19 | "logout": "Sign out", | ||
20 | "register": "Register" | ||
21 | }, | ||
22 | "admin": { | ||
23 | "main": "Administration", | ||
24 | "userManagement": "User management", | ||
25 | "tracker": "User tracker", | ||
26 | "metrics": "Metrics", | ||
27 | "health": "Health", | ||
28 | "configuration": "Configuration", | ||
29 | "logs": "Logs", | ||
30 | "audits": "Audits", | ||
31 | "apidocs": "API", | ||
32 | "database": "Database", | ||
33 | "jhipster-needle-menu-add-admin-element": "JHipster will add additional menu entries here (do not translate!)" | ||
34 | }, | ||
35 | "language": "Language" | ||
36 | }, | ||
37 | "form": { | ||
38 | "username.label": "Username", | ||
39 | "username.placeholder": "Your username", | ||
40 | "currentpassword.label": "Current password", | ||
41 | "currentpassword.placeholder": "Current password", | ||
42 | "newpassword.label": "New password", | ||
43 | "newpassword.placeholder": "New password", | ||
44 | "confirmpassword.label": "New password confirmation", | ||
45 | "confirmpassword.placeholder": "Confirm the new password", | ||
46 | "email.label": "Email", | ||
47 | "email.placeholder": "Your email" | ||
48 | }, | ||
49 | "messages": { | ||
50 | "info": { | ||
51 | "authenticated": { | ||
52 | "prefix": "If you want to ", | ||
53 | "link": "sign in", | ||
54 | "suffix": ", you can try the default accounts:<br/>- Administrator (login=\"admin\" and password=\"admin\") <br/>- User (login=\"user\" and password=\"user\")." | ||
55 | }, | ||
56 | "register": { | ||
57 | "noaccount": "You don't have an account yet?", | ||
58 | "link": "Register a new account" | ||
59 | } | ||
60 | }, | ||
61 | "error": { | ||
62 | "dontmatch": "The password and its confirmation do not match!" | ||
63 | }, | ||
64 | "validate": { | ||
65 | "newpassword": { | ||
66 | "required": "Your password is required.", | ||
67 | "minlength": "Your password is required to be at least 4 characters.", | ||
68 | "maxlength": "Your password cannot be longer than 50 characters.", | ||
69 | "strength": "Password strength:" | ||
70 | }, | ||
71 | "confirmpassword": { | ||
72 | "required": "Your confirmation password is required.", | ||
73 | "minlength": "Your confirmation password is required to be at least 4 characters.", | ||
74 | "maxlength": "Your confirmation password cannot be longer than 50 characters." | ||
75 | }, | ||
76 | "email": { | ||
77 | "required": "Your email is required.", | ||
78 | "invalid": "Your email is invalid.", | ||
79 | "minlength": "Your email is required to be at least 5 characters.", | ||
80 | "maxlength": "Your email cannot be longer than 50 characters." | ||
81 | } | ||
82 | } | ||
83 | }, | ||
84 | "field": { | ||
85 | "id": "ID" | ||
86 | }, | ||
87 | "ribbon": { | ||
88 | "dev": "Development" | ||
89 | }, | ||
90 | "item-count": "Showing {{first}} - {{second}} of {{total}} items." | ||
91 | }, | ||
92 | "entity": { | ||
93 | "action": { | ||
94 | "addblob": "Add blob", | ||
95 | "addimage": "Add image", | ||
96 | "back": "Back", | ||
97 | "cancel": "Cancel", | ||
98 | "delete": "Delete", | ||
99 | "edit": "Edit", | ||
100 | "open": "Open", | ||
101 | "save": "Save", | ||
102 | "view": "View" | ||
103 | }, | ||
104 | "detail": { | ||
105 | "field": "Field", | ||
106 | "value": "Value" | ||
107 | }, | ||
108 | "delete": { | ||
109 | "title": "Confirm delete operation" | ||
110 | }, | ||
111 | "validation": { | ||
112 | "required": "This field is required.", | ||
113 | "minlength": "This field is required to be at least {{ min }} characters.", | ||
114 | "maxlength": "This field cannot be longer than {{ max }} characters.", | ||
115 | "min": "This field should be at least {{ min }}.", | ||
116 | "max": "This field cannot be more than {{ max }}.", | ||
117 | "minbytes": "This field should be at least {{ min }} bytes.", | ||
118 | "maxbytes": "This field cannot be more than {{ max }} bytes.", | ||
119 | "pattern": "This field should follow pattern for {{ pattern }}.", | ||
120 | "number": "This field should be a number.", | ||
121 | "datetimelocal": "This field should be a date and time.", | ||
122 | "patternLogin": "This field can only contain letters, digits and e-mail addresses." | ||
123 | } | ||
124 | }, | ||
125 | "error": { | ||
126 | "internalServerError": "Internal server error", | ||
127 | "server.not.reachable": "Server not reachable", | ||
128 | "url.not.found": "Not found", | ||
129 | "NotNull": "Field {{ fieldName }} cannot be empty!", | ||
130 | "Size": "Field {{ fieldName }} does not meet min/max size requirements!", | ||
131 | "userexists": "Login name already used!", | ||
132 | "emailexists": "Email is already in use!", | ||
133 | "idexists": "A new {{ entityName }} cannot already have an ID", | ||
134 | "idnull": "Invalid ID", | ||
135 | "file": { | ||
136 | "could.not.extract": "Could not extract file", | ||
137 | "not.image": "File was expected to be an image but was found to be \"{{ fileType }}\"" | ||
138 | } | ||
139 | }, | ||
140 | "footer": "This is your footer" | ||
141 | } |
File src/main/webapp/i18n/en/health.json added (mode: 100644) (index 0000000..0cbff26) | |||
1 | { | ||
2 | "health": { | ||
3 | "title": "Health Checks", | ||
4 | "refresh.button": "Refresh", | ||
5 | "stacktrace": "Stacktrace", | ||
6 | "details": { | ||
7 | "details": "Details", | ||
8 | "properties": "Properties", | ||
9 | "name": "Name", | ||
10 | "value": "Value", | ||
11 | "error": "Error" | ||
12 | }, | ||
13 | "indicator": { | ||
14 | "diskSpace": "Disk space", | ||
15 | "mail": "Email", | ||
16 | "ping": "Application", | ||
17 | "db": "Database" | ||
18 | }, | ||
19 | "table": { | ||
20 | "service": "Service name", | ||
21 | "status": "Status" | ||
22 | }, | ||
23 | "status": { | ||
24 | "UNKNOWN": "UNKNOWN", | ||
25 | "UP": "UP", | ||
26 | "DOWN": "DOWN" | ||
27 | } | ||
28 | } | ||
29 | } |
File src/main/webapp/i18n/en/home.json added (mode: 100644) (index 0000000..d9fc499) | |||
1 | { | ||
2 | "home": { | ||
3 | "title": "Welcome, Java Hipster!", | ||
4 | "subtitle": "This is your homepage", | ||
5 | "logged": { | ||
6 | "message": "You are logged in as user \"{{username}}\"." | ||
7 | }, | ||
8 | "question": "If you have any question on JHipster:", | ||
9 | "link": { | ||
10 | "homepage": "JHipster homepage", | ||
11 | "stackoverflow": "JHipster on Stack Overflow", | ||
12 | "bugtracker": "JHipster bug tracker", | ||
13 | "chat": "JHipster public chat room", | ||
14 | "follow": "follow @jhipster on Twitter" | ||
15 | }, | ||
16 | "like": "If you like JHipster, don't forget to give us a star on", | ||
17 | "github": "GitHub" | ||
18 | } | ||
19 | } |
File src/main/webapp/i18n/en/login.json added (mode: 100644) (index 0000000..4667958) | |||
1 | { | ||
2 | "login": { | ||
3 | "title": "Sign in", | ||
4 | "form": { | ||
5 | "password": "Password", | ||
6 | "password.placeholder": "Your password", | ||
7 | "rememberme": "Remember me", | ||
8 | "button": "Sign in" | ||
9 | }, | ||
10 | "messages": { | ||
11 | "error": { | ||
12 | "authentication": "<strong>Failed to sign in!</strong> Please check your credentials and try again." | ||
13 | } | ||
14 | }, | ||
15 | "password": { | ||
16 | "forgot": "Did you forget your password?" | ||
17 | } | ||
18 | } | ||
19 | } |
File src/main/webapp/i18n/en/logs.json added (mode: 100644) (index 0000000..8ee0ba5) | |||
1 | { | ||
2 | "logs": { | ||
3 | "title": "Logs", | ||
4 | "nbloggers": "There are {{ total }} loggers.", | ||
5 | "filter": "Filter", | ||
6 | "table": { | ||
7 | "name": "Name", | ||
8 | "level": "Level" | ||
9 | } | ||
10 | } | ||
11 | } |
File src/main/webapp/i18n/en/metrics.json added (mode: 100644) (index 0000000..c514dee) | |||
1 | { | ||
2 | "metrics": { | ||
3 | "title": "Application Metrics", | ||
4 | "refresh.button": "Refresh", | ||
5 | "updating": "Updating...", | ||
6 | "jvm": { | ||
7 | "title": "JVM Metrics", | ||
8 | "memory": { | ||
9 | "title": "Memory", | ||
10 | "total": "Total Memory", | ||
11 | "heap": "Heap Memory", | ||
12 | "nonheap": "Non-Heap Memory" | ||
13 | }, | ||
14 | "threads": { | ||
15 | "title": "Threads", | ||
16 | "all": "All", | ||
17 | "runnable": "Runnable", | ||
18 | "timedwaiting": "Timed waiting", | ||
19 | "waiting": "Waiting", | ||
20 | "blocked": "Blocked", | ||
21 | "dump": { | ||
22 | "title": "Threads dump", | ||
23 | "id": "Id: ", | ||
24 | "blockedtime": "Blocked Time", | ||
25 | "blockedcount": "Blocked Count", | ||
26 | "waitedtime": "Waited Time", | ||
27 | "waitedcount": "Waited Count", | ||
28 | "lockname": "Lock name", | ||
29 | "stacktrace": "Stacktrace", | ||
30 | "show": "Show Stacktrace", | ||
31 | "hide": "Hide Stacktrace" | ||
32 | } | ||
33 | }, | ||
34 | "gc": { | ||
35 | "title": "Garbage collections", | ||
36 | "marksweepcount": "Mark Sweep count", | ||
37 | "marksweeptime": "Mark Sweep time", | ||
38 | "scavengecount": "Scavenge count", | ||
39 | "scavengetime": "Scavenge time" | ||
40 | }, | ||
41 | "http": { | ||
42 | "title": "HTTP requests (time in millisecond)", | ||
43 | "active": "Active requests:", | ||
44 | "total": "Total requests:", | ||
45 | "table": { | ||
46 | "code": "Code", | ||
47 | "count": "Count", | ||
48 | "mean": "Mean", | ||
49 | "average": "Average", | ||
50 | "max": "Max" | ||
51 | }, | ||
52 | "code": { | ||
53 | "ok": "Ok", | ||
54 | "notfound": "Not found", | ||
55 | "servererror": "Server Error" | ||
56 | } | ||
57 | } | ||
58 | }, | ||
59 | "servicesstats": { | ||
60 | "title": "Services statistics (time in millisecond)", | ||
61 | "table": { | ||
62 | "name": "Service name", | ||
63 | "count": "Count", | ||
64 | "mean": "Mean", | ||
65 | "min": "Min", | ||
66 | "max": "Max", | ||
67 | "p50": "p50", | ||
68 | "p75": "p75", | ||
69 | "p95": "p95", | ||
70 | "p99": "p99" | ||
71 | } | ||
72 | }, | ||
73 | "cache": { | ||
74 | "title": "Cache statistics", | ||
75 | "cachename": "Cache name", | ||
76 | "hits": "Cache Hits", | ||
77 | "misses": "Cache Misses", | ||
78 | "gets": "Cache Gets", | ||
79 | "puts": "Cache Puts", | ||
80 | "removals": "Cache Removals", | ||
81 | "evictions": "Cache Evictions", | ||
82 | "hitPercent": "Cache Hit %", | ||
83 | "missPercent": "Cache Miss %", | ||
84 | "averageGetTime": "Average get time (µs)", | ||
85 | "averagePutTime": "Average put time (µs)", | ||
86 | "averageRemoveTime": "Average remove time (µs)" | ||
87 | }, | ||
88 | "datasource": { | ||
89 | "usage": "Connection Pool Usage", | ||
90 | "title": "DataSource statistics (time in millisecond)", | ||
91 | "name": "Pool usage", | ||
92 | "count": "Count", | ||
93 | "mean": "Mean", | ||
94 | "min": "Min", | ||
95 | "max": "Max", | ||
96 | "p50": "p50", | ||
97 | "p75": "p75", | ||
98 | "p95": "p95", | ||
99 | "p99": "p99" | ||
100 | } | ||
101 | } | ||
102 | } |
File src/main/webapp/i18n/en/password.json added (mode: 100644) (index 0000000..fc9b6c9) | |||
1 | { | ||
2 | "password": { | ||
3 | "title": "Password for [<strong>{{username}}</strong>]", | ||
4 | "form": { | ||
5 | "button": "Save" | ||
6 | }, | ||
7 | "messages": { | ||
8 | "error": "<strong>An error has occurred!</strong> The password could not be changed.", | ||
9 | "success": "<strong>Password changed!</strong>" | ||
10 | } | ||
11 | } | ||
12 | } |
File src/main/webapp/i18n/en/pieceOfNews.json added (mode: 100644) (index 0000000..909c22f) | |||
1 | { | ||
2 | "honlapApp": { | ||
3 | "pieceOfNews": { | ||
4 | "home": { | ||
5 | "title": "Piece Of News", | ||
6 | "createLabel": "Create a new Piece Of News", | ||
7 | "createOrEditLabel": "Create or edit a Piece Of News", | ||
8 | "notFound": "No Piece Of News found" | ||
9 | }, | ||
10 | "created": "A new Piece Of News is created with identifier {{ param }}", | ||
11 | "updated": "A Piece Of News is updated with identifier {{ param }}", | ||
12 | "deleted": "A Piece Of News is deleted with identifier {{ param }}", | ||
13 | "delete": { | ||
14 | "question": "Are you sure you want to delete Piece Of News {{ id }}?" | ||
15 | }, | ||
16 | "detail": { | ||
17 | "title": "Piece Of News" | ||
18 | }, | ||
19 | "appId": "App Id", | ||
20 | "newsDate": "News Date", | ||
21 | "headline": "Headline", | ||
22 | "content": "Content", | ||
23 | "link": "Link", | ||
24 | "publishDate": "Publish Date", | ||
25 | "createdBy": "Created By", | ||
26 | "createdDate": "Created Date", | ||
27 | "lastModifiedBy": "Last Modified By", | ||
28 | "lastModifiedDate": "Last Modified Date" | ||
29 | } | ||
30 | } | ||
31 | } |
File src/main/webapp/i18n/en/register.json added (mode: 100644) (index 0000000..bbd49eb) | |||
1 | { | ||
2 | "register": { | ||
3 | "title": "Registration", | ||
4 | "form": { | ||
5 | "button": "Register" | ||
6 | }, | ||
7 | "messages": { | ||
8 | "validate": { | ||
9 | "login": { | ||
10 | "required": "Your username is required.", | ||
11 | "minlength": "Your username is required to be at least 1 character.", | ||
12 | "maxlength": "Your username cannot be longer than 50 characters.", | ||
13 | "pattern": "Your username can only contain letters and digits." | ||
14 | } | ||
15 | }, | ||
16 | "success": "<strong>Registration saved!</strong> Please check your email for confirmation.", | ||
17 | "error": { | ||
18 | "fail": "<strong>Registration failed!</strong> Please try again later.", | ||
19 | "userexists": "<strong>Login name already registered!</strong> Please choose another one.", | ||
20 | "emailexists": "<strong>Email is already in use!</strong> Please choose another one." | ||
21 | } | ||
22 | } | ||
23 | } | ||
24 | } |
File src/main/webapp/i18n/en/reset.json added (mode: 100644) (index 0000000..4c35e9a) | |||
1 | { | ||
2 | "reset": { | ||
3 | "request": { | ||
4 | "title": "Reset your password", | ||
5 | "form": { | ||
6 | "button": "Reset password" | ||
7 | }, | ||
8 | "messages": { | ||
9 | "info": "Enter the email address you used to register", | ||
10 | "success": "Check your emails for details on how to reset your password." | ||
11 | } | ||
12 | }, | ||
13 | "finish": { | ||
14 | "title": "Reset password", | ||
15 | "form": { | ||
16 | "button": "Validate new password" | ||
17 | }, | ||
18 | "messages": { | ||
19 | "info": "Choose a new password", | ||
20 | "success": "<strong>Your password has been reset.</strong> Please ", | ||
21 | "keymissing": "The reset key is missing.", | ||
22 | "error": "Your password couldn't be reset. Remember a password request is only valid for 24 hours." | ||
23 | } | ||
24 | } | ||
25 | } | ||
26 | } |
File src/main/webapp/i18n/en/sessions.json added (mode: 100644) (index 0000000..38bf44f) | |||
1 | { | ||
2 | "sessions": { | ||
3 | "title": "Active sessions for [<strong>{{username}}</strong>]", | ||
4 | "table": { | ||
5 | "ipaddress": "IP address", | ||
6 | "useragent": "User Agent", | ||
7 | "date": "Date", | ||
8 | "button": "Invalidate" | ||
9 | }, | ||
10 | "messages": { | ||
11 | "success": "<strong>Session invalidated!</strong>", | ||
12 | "error": "<strong>An error has occurred!</strong> The session could not be invalidated." | ||
13 | } | ||
14 | } | ||
15 | } |
File src/main/webapp/i18n/en/settings.json added (mode: 100644) (index 0000000..508c037) | |||
1 | { | ||
2 | "settings": { | ||
3 | "title": "User settings for [<strong>{{username}}</strong>]", | ||
4 | "form": { | ||
5 | "firstname": "First Name", | ||
6 | "firstname.placeholder": "Your first name", | ||
7 | "lastname": "Last Name", | ||
8 | "lastname.placeholder": "Your last name", | ||
9 | "language": "Language", | ||
10 | "button": "Save" | ||
11 | }, | ||
12 | "messages": { | ||
13 | "error": { | ||
14 | "fail": "<strong>An error has occurred!</strong> Settings could not be saved.", | ||
15 | "emailexists": "<strong>Email is already in use!</strong> Please choose another one." | ||
16 | }, | ||
17 | "success": "<strong>Settings saved!</strong>", | ||
18 | "validate": { | ||
19 | "firstname": { | ||
20 | "required": "Your first name is required.", | ||
21 | "minlength": "Your first name is required to be at least 1 character", | ||
22 | "maxlength": "Your first name cannot be longer than 50 characters" | ||
23 | }, | ||
24 | "lastname": { | ||
25 | "required": "Your last name is required.", | ||
26 | "minlength": "Your last name is required to be at least 1 character", | ||
27 | "maxlength": "Your last name cannot be longer than 50 characters" | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } |
File src/main/webapp/i18n/en/user-management.json added (mode: 100644) (index 0000000..4923c09) | |||
1 | { | ||
2 | "userManagement": { | ||
3 | "home": { | ||
4 | "title": "Users", | ||
5 | "createLabel": "Create a new user", | ||
6 | "createOrEditLabel": "Create or edit a user" | ||
7 | }, | ||
8 | "created": "A new user is created with identifier {{ param }}", | ||
9 | "updated": "A user is updated with identifier {{ param }}", | ||
10 | "deleted": "A user is deleted with identifier {{ param }}", | ||
11 | "delete": { | ||
12 | "question": "Are you sure you want to delete user {{ login }}?" | ||
13 | }, | ||
14 | "detail": { | ||
15 | "title": "User" | ||
16 | }, | ||
17 | "login": "Login", | ||
18 | "firstName": "First name", | ||
19 | "lastName": "Last name", | ||
20 | "email": "Email", | ||
21 | "activated": "Activated", | ||
22 | "deactivated": "Deactivated", | ||
23 | "profiles": "Profiles", | ||
24 | "langKey": "Language", | ||
25 | "createdBy": "Created by", | ||
26 | "createdDate": "Created date", | ||
27 | "lastModifiedBy": "Modified by", | ||
28 | "lastModifiedDate": "Modified date" | ||
29 | } | ||
30 | } |
File src/main/webapp/i18n/hu/activate.json added (mode: 100644) (index 0000000..33ebfa6) | |||
1 | { | ||
2 | "activate": { | ||
3 | "title": "Aktiválás", | ||
4 | "messages": { | ||
5 | "success": "<strong>A hozzáférése aktiválásra került.</strong> Kérjük ", | ||
6 | "error": "<strong>A hozzáférését nem sikerült aktiválni.</strong> Kérjük használja a regisztrációs oldalt, hogy hozzáférést igényeljen." | ||
7 | } | ||
8 | } | ||
9 | } |
File src/main/webapp/i18n/hu/audits.json added (mode: 100644) (index 0000000..c2e2f44) | |||
1 | { | ||
2 | "audits": { | ||
3 | "title": "Biztonsági ellenörzés", | ||
4 | "filter": { | ||
5 | "title": "Dátum szerinti szűrés", | ||
6 | "from": "Kezdet", | ||
7 | "to": "Vég", | ||
8 | "button": { | ||
9 | "weeks": "hetek", | ||
10 | "today": "ma", | ||
11 | "clear": "törlés", | ||
12 | "close": "bezárás" | ||
13 | } | ||
14 | }, | ||
15 | "table": { | ||
16 | "header": { | ||
17 | "principal": "Felhasználó", | ||
18 | "date": "Dátum", | ||
19 | "status": "Állapot", | ||
20 | "data": "Extra információ" | ||
21 | }, | ||
22 | "data": { | ||
23 | "remoteAddress": "IP cím:" | ||
24 | } | ||
25 | }, | ||
26 | "notFound": "No audit found" | ||
27 | } | ||
28 | } |
File src/main/webapp/i18n/hu/configuration.json added (mode: 100644) (index 0000000..ee24680) | |||
1 | { | ||
2 | "configuration": { | ||
3 | "title": "Beállítások", | ||
4 | "filter": "Szűrés (prefix alapján)", | ||
5 | "table": { | ||
6 | "prefix": "Prefix", | ||
7 | "properties": "Beállítások" | ||
8 | } | ||
9 | } | ||
10 | } |
File src/main/webapp/i18n/hu/error.json added (mode: 100644) (index 0000000..3f5aad1) | |||
1 | { | ||
2 | "error": { | ||
3 | "title": "Hiba!", | ||
4 | "http": { | ||
5 | "400": "Bad request.", | ||
6 | "403": "Nem vagy jogosult ennek a lapnak a megnézésére.", | ||
7 | "404": "Az oldal nem létezik.", | ||
8 | "405": "The HTTP verb you used is not supported for this URL.", | ||
9 | "500": "Internal server error." | ||
10 | }, | ||
11 | "concurrencyFailure": "Another user modified this data at the same time as you. Your changes were rejected.", | ||
12 | "validation": "Validation error on the server." | ||
13 | } | ||
14 | } |
File src/main/webapp/i18n/hu/global.json added (mode: 100644) (index 0000000..2dc3e9d) | |||
1 | { | ||
2 | "global": { | ||
3 | "title": "Honlap", | ||
4 | "browsehappy": "Ön <strong>elavult</strong> böngészőt használ. Kérjük <a href=\"http://browsehappy.com/?locale=hu\">frissítse böngészőjét</a> hogy javuljon a felhasználói élménye.", | ||
5 | "menu": { | ||
6 | "home": "Kezdőpont", | ||
7 | "jhipster-needle-menu-add-element": "JHipster will add additional menu entries here (do not translate!)", | ||
8 | "entities": { | ||
9 | "main": "Entitások", | ||
10 | "pieceOfNews": "Piece Of News", | ||
11 | "jhipster-needle-menu-add-entry": "JHipster will add additional entities here (do not translate!)" | ||
12 | }, | ||
13 | "account": { | ||
14 | "main": "Hozzáférés", | ||
15 | "settings": "Beállítások", | ||
16 | "password": "Jelszó", | ||
17 | "sessions": "Munkamenetek", | ||
18 | "login": "Hitelesítés", | ||
19 | "logout": "Kilépés", | ||
20 | "register": "Regisztráció" | ||
21 | }, | ||
22 | "admin": { | ||
23 | "main": "Adminisztráció", | ||
24 | "userManagement": "Felhasználókezelés", | ||
25 | "tracker": "Felhasználó követés", | ||
26 | "metrics": "Metrikák", | ||
27 | "health": "Akalmazás állapota", | ||
28 | "configuration": "Konfiguráció", | ||
29 | "logs": "Naplók", | ||
30 | "audits": "Nyomkövetés", | ||
31 | "apidocs": "API dokumentáció", | ||
32 | "database": "Adatbázis", | ||
33 | "jhipster-needle-menu-add-admin-element": "JHipster will add additional menu entries here (do not translate!)" | ||
34 | }, | ||
35 | "language": "Nyelvek" | ||
36 | }, | ||
37 | "form": { | ||
38 | "username.label": "Azonosító", | ||
39 | "username.placeholder": "Az Ön felhasználói neve", | ||
40 | "currentpassword.label": "Current password", | ||
41 | "currentpassword.placeholder": "Current password", | ||
42 | "newpassword.label": "Új jelszó", | ||
43 | "newpassword.placeholder": "Új jelszava", | ||
44 | "confirmpassword.label": "Új jelszó megerősítése", | ||
45 | "confirmpassword.placeholder": "Írja be újra a jelszavát", | ||
46 | "email.label": "Email", | ||
47 | "email.placeholder": "Az Ön email címe" | ||
48 | }, | ||
49 | "messages": { | ||
50 | "info": { | ||
51 | "authenticated": { | ||
52 | "prefix": "Ha be akar ", | ||
53 | "link": "lépni", | ||
54 | "suffix": ", kipróbálás céljából használható felhasználók:<br/>- Adminisztrátor (azonosító=\"admin\" és a jelszó=\"admin\") <br/>- Felhasználó (azonosító=\"user\" és jelszó=\"user\")." | ||
55 | }, | ||
56 | "register": { | ||
57 | "noaccount": "Nincs még hozzáférése?", | ||
58 | "link": "Regisztráljon" | ||
59 | } | ||
60 | }, | ||
61 | "error": { | ||
62 | "dontmatch": "A jelszó és a jelszó megerősítés nem egyezik meg!" | ||
63 | }, | ||
64 | "validate": { | ||
65 | "newpassword": { | ||
66 | "required": "A jelszó kötelező.", | ||
67 | "minlength": "A jelszó legalább 4 karakterből kell, hogy álljon", | ||
68 | "maxlength": "A jelszó nem lehet hosszabb mint 50 karakter", | ||
69 | "strength": "A jelszó bonyolultsága:" | ||
70 | }, | ||
71 | "confirmpassword": { | ||
72 | "required": "A jelszó megerősítés kötelező.", | ||
73 | "minlength": "A jelszó megerősítés legalább 4 betűből kell, hogy álljon", | ||
74 | "maxlength": "A jelszó megerősítés nem lehet hosszabb mint 50 betű" | ||
75 | }, | ||
76 | "email": { | ||
77 | "required": "Az email cím kötelező.", | ||
78 | "invalid": "A megadott email cím nem jó.", | ||
79 | "minlength": "Az email cím legalább 5 betüből kell, hogy álljon", | ||
80 | "maxlength": "Az email cím nem lehet hosszabb mint 50 betű" | ||
81 | } | ||
82 | } | ||
83 | }, | ||
84 | "field": { | ||
85 | "id": "ID" | ||
86 | }, | ||
87 | "ribbon": { | ||
88 | "dev": "Fejlesztői változat" | ||
89 | }, | ||
90 | "item-count": "Showing {{first}} - {{second}} of {{total}} items." | ||
91 | }, | ||
92 | "entity": { | ||
93 | "action": { | ||
94 | "addblob": "Fájl hozzáadása", | ||
95 | "addimage": "Kép hozzáadása", | ||
96 | "back": "Vissza", | ||
97 | "cancel": "Mégsem", | ||
98 | "delete": "Törlés", | ||
99 | "edit": "Szerkesztés", | ||
100 | "open": "Megnyitás", | ||
101 | "save": "Mentés", | ||
102 | "view": "Nézet" | ||
103 | }, | ||
104 | "detail": { | ||
105 | "field": "Mező", | ||
106 | "value": "Érték" | ||
107 | }, | ||
108 | "delete": { | ||
109 | "title": "Erősítse meg a törlési szándékát" | ||
110 | }, | ||
111 | "validation": { | ||
112 | "required": "Ez a mező kötelező.", | ||
113 | "minlength": "Ez a mező legalább {{min}} karaktert kell, hogy tartalmazzon.", | ||
114 | "maxlength": "Ez a mező nem lehet hosszabb mint {{max}} karakter.", | ||
115 | "min": "Ennek a mezőnek a megengedett minimum értéke {{min}}.", | ||
116 | "max": "Ennek a mezőnek a megengedett maximum értéke {{max}}.", | ||
117 | "minbytes": "Ennek a mezőnek a megengedett minimum értéke {{min}} bytes.", | ||
118 | "maxbytes": "Ennek a mezőnek a megengedett maximum értéke {{max}} bytes.", | ||
119 | "pattern": "Ennek a mezőnek meg kell felelni a {{pattern}} mintának.", | ||
120 | "number": "Ennek a mezőnek számnak kell lennie.", | ||
121 | "datetimelocal": "Ennek a mezőnek dátumnak vagy időpontnak kell lennie." | ||
122 | } | ||
123 | }, | ||
124 | "error": { | ||
125 | "internalServerError": "Szerver hiba", | ||
126 | "server.not.reachable": "A szerver nem elérhető", | ||
127 | "url.not.found": "Nem található", | ||
128 | "NotNull": "Az {{fieldName}} mező nem lehet üres!", | ||
129 | "Size": "A {{fieldName}} mező nem teljesíti a minimum/maximum hossz követelményeket!", | ||
130 | "userexists": "Ezzel a felhasználónévvel már regisztráltak!", | ||
131 | "emailexists": "Ezzel az email címmel már regisztráltak!", | ||
132 | "idexists": "Az új {{entityName}}-nak/nek nem lehet még ID-ja", | ||
133 | "idnull": "Invalid ID", | ||
134 | "file": { | ||
135 | "could.not.extract": "Could not extract file", | ||
136 | "not.image": "File was expected to be an image but was found to be \"{{ fileType }}\"" | ||
137 | } | ||
138 | }, | ||
139 | "footer": "Ez a lábléc." | ||
140 | } |
File src/main/webapp/i18n/hu/health.json added (mode: 100644) (index 0000000..243aec1) | |||
1 | { | ||
2 | "health": { | ||
3 | "title": "Rendszer ellenőrzések", | ||
4 | "refresh.button": "Frissítés", | ||
5 | "stacktrace": "Stacktrace", | ||
6 | "details": { | ||
7 | "details": "Details", | ||
8 | "properties": "Properties", | ||
9 | "name": "Name", | ||
10 | "value": "Value", | ||
11 | "error": "Error" | ||
12 | }, | ||
13 | "indicator": { | ||
14 | "diskSpace": "Szabad hely a diszken", | ||
15 | "mail": "Email", | ||
16 | "ping": "Application", | ||
17 | "db": "Adatbázis" | ||
18 | }, | ||
19 | "table": { | ||
20 | "service": "Szervíz neve", | ||
21 | "status": "Státusz" | ||
22 | }, | ||
23 | "status": { | ||
24 | "UNKNOWN": "UNKNOWN", | ||
25 | "UP": "MŰKÖDIK", | ||
26 | "DOWN": "NEM MŰKÖDIK" | ||
27 | } | ||
28 | } | ||
29 | } |
File src/main/webapp/i18n/hu/home.json added (mode: 100644) (index 0000000..c407f12) | |||
1 | { | ||
2 | "home": { | ||
3 | "title": "Üdvözöljük, Java Hipster!", | ||
4 | "subtitle": "Ez a nyitóképernyőd", | ||
5 | "logged": { | ||
6 | "message": "Ön \"{{username}}\"-ként lépett be." | ||
7 | }, | ||
8 | "question": "Ha bármi kérdése van a JHipster-ről:", | ||
9 | "link": { | ||
10 | "homepage": "JHipster honlapja", | ||
11 | "stackoverflow": "JHipster a Stack Overflow-n", | ||
12 | "bugtracker": "JHipster hibakövető", | ||
13 | "chat": "JHipster public chat room", | ||
14 | "follow": "lépjen kapcsolatba @jhipster -rel a Twitter-en" | ||
15 | }, | ||
16 | "like": "Ha tetszik a JHipster, ne feledjen csillagot adni a", | ||
17 | "github": "GitHub-on" | ||
18 | } | ||
19 | } |
File src/main/webapp/i18n/hu/login.json added (mode: 100644) (index 0000000..8c7b7f3) | |||
1 | { | ||
2 | "login": { | ||
3 | "title": "Hitelesítés", | ||
4 | "form": { | ||
5 | "password": "Jelszó", | ||
6 | "password.placeholder": "Az Ön jelszava", | ||
7 | "rememberme": "Automatikus belépés", | ||
8 | "button": "Belépés" | ||
9 | }, | ||
10 | "messages": { | ||
11 | "error": { | ||
12 | "authentication": "<strong>Hitelesítés nem sikerült!</strong> Kérjük ellenörizze, hogy helyesen adta meg nevét és jelszavát, és próbálja újra." | ||
13 | } | ||
14 | }, | ||
15 | "password": { | ||
16 | "forgot": "Elfelejtette a jelszavát?" | ||
17 | } | ||
18 | } | ||
19 | } |
File src/main/webapp/i18n/hu/logs.json added (mode: 100644) (index 0000000..e93fee9) | |||
1 | { | ||
2 | "logs": { | ||
3 | "title": "Naplók", | ||
4 | "nbloggers": "{{ total }} naplózó található.", | ||
5 | "filter": "Szűrő", | ||
6 | "table": { | ||
7 | "name": "Név", | ||
8 | "level": "Szint" | ||
9 | } | ||
10 | } | ||
11 | } |
File src/main/webapp/i18n/hu/metrics.json added (mode: 100644) (index 0000000..7a25dc2) | |||
1 | { | ||
2 | "metrics": { | ||
3 | "title": "Application Metrics", | ||
4 | "refresh.button": "Refresh", | ||
5 | "updating": "Updating...", | ||
6 | "jvm": { | ||
7 | "title": "JVM Metrics", | ||
8 | "memory": { | ||
9 | "title": "Memory", | ||
10 | "total": "Total Memory", | ||
11 | "heap": "Heap Memory", | ||
12 | "nonheap": "Non-Heap Memory" | ||
13 | }, | ||
14 | "threads": { | ||
15 | "title": "Threads", | ||
16 | "all": "All", | ||
17 | "runnable": "Runnable", | ||
18 | "timedwaiting": "Timed waiting", | ||
19 | "waiting": "Waiting", | ||
20 | "blocked": "Blocked", | ||
21 | "dump": { | ||
22 | "title": "Threads dump", | ||
23 | "id": "Id: ", | ||
24 | "blockedtime": "Blocked Time", | ||
25 | "blockedcount": "Blocked Count", | ||
26 | "waitedtime": "Waited Time", | ||
27 | "waitedcount": "Waited Count", | ||
28 | "lockname": "Lock name", | ||
29 | "stacktrace": "Stacktrace", | ||
30 | "show": "Show", | ||
31 | "hide": "Hide" | ||
32 | } | ||
33 | }, | ||
34 | "gc": { | ||
35 | "title": "Garbage collections", | ||
36 | "marksweepcount": "Mark Sweep count", | ||
37 | "marksweeptime": "Mark Sweep time", | ||
38 | "scavengecount": "Scavenge count", | ||
39 | "scavengetime": "Scavenge time" | ||
40 | }, | ||
41 | "http": { | ||
42 | "title": "HTTP requests (events per second)", | ||
43 | "active": "Active requests:", | ||
44 | "total": "Total requests:", | ||
45 | "table": { | ||
46 | "code": "Code", | ||
47 | "count": "Count", | ||
48 | "mean": "Mean", | ||
49 | "average": "Average" | ||
50 | }, | ||
51 | "code": { | ||
52 | "ok": "Ok", | ||
53 | "notfound": "Not found", | ||
54 | "servererror": "Server Error" | ||
55 | } | ||
56 | } | ||
57 | }, | ||
58 | "servicesstats": { | ||
59 | "title": "Services statistics (time in millisecond)", | ||
60 | "table": { | ||
61 | "name": "Service name", | ||
62 | "count": "Count", | ||
63 | "mean": "Mean", | ||
64 | "min": "Min", | ||
65 | "max": "Max", | ||
66 | "p50": "p50", | ||
67 | "p75": "p75", | ||
68 | "p95": "p95", | ||
69 | "p99": "p99" | ||
70 | } | ||
71 | }, | ||
72 | "cache": { | ||
73 | "title": "Cache statistics", | ||
74 | "cachename": "Cache name", | ||
75 | "hits": "Hits", | ||
76 | "misses": "Misses", | ||
77 | "evictions": "Evictions" | ||
78 | }, | ||
79 | "datasource": { | ||
80 | "usage": "Usage", | ||
81 | "title": "DataSource statistics (time in millisecond)", | ||
82 | "name": "Pool usage", | ||
83 | "count": "Count", | ||
84 | "mean": "Mean", | ||
85 | "min": "Min", | ||
86 | "max": "Max", | ||
87 | "p50": "p50", | ||
88 | "p75": "p75", | ||
89 | "p95": "p95", | ||
90 | "p99": "p99" | ||
91 | } | ||
92 | } | ||
93 | } |
File src/main/webapp/i18n/hu/password.json added (mode: 100644) (index 0000000..9d7f302) | |||
1 | { | ||
2 | "password": { | ||
3 | "title": "Jelszó [<strong>{{username}}</strong>]-nak", | ||
4 | "form": { | ||
5 | "button": "Mentés" | ||
6 | }, | ||
7 | "messages": { | ||
8 | "error": "<strong>Hiba történt!</strong> A jelszót nem sikerült megváltoztatni.", | ||
9 | "success": "<strong>A jelszó megváltozott!</strong>" | ||
10 | } | ||
11 | } | ||
12 | } |
File src/main/webapp/i18n/hu/pieceOfNews.json added (mode: 100644) (index 0000000..50e7037) | |||
1 | { | ||
2 | "honlapApp": { | ||
3 | "pieceOfNews": { | ||
4 | "home": { | ||
5 | "title": "PieceOfNews", | ||
6 | "createLabel": "Egy új Piece Of News létrehozása", | ||
7 | "createOrEditLabel": "Hozzon létre, vagy módosítson Piece Of Newst", | ||
8 | "notFound": "No Piece Of News found" | ||
9 | }, | ||
10 | "created": "Egy új Piece Of News lett létrehozva {{ param }} azonosítóval", | ||
11 | "updated": "A Piece Of News módosítva lett {{ param }} azonosítóval", | ||
12 | "deleted": "A Piece Of News törölve lett {{ param }} azonosítóval", | ||
13 | "delete": { | ||
14 | "question": "Biztos benne, hogy törölni szeretné az Piece Of Newst {{ id }} azonosítóval?" | ||
15 | }, | ||
16 | "detail": { | ||
17 | "title": "Piece Of News" | ||
18 | }, | ||
19 | "appId": "App Id", | ||
20 | "newsDate": "News Date", | ||
21 | "headline": "Headline", | ||
22 | "content": "Content", | ||
23 | "link": "Link", | ||
24 | "publishDate": "Publish Date", | ||
25 | "createdBy": "Created By", | ||
26 | "createdDate": "Created Date", | ||
27 | "lastModifiedBy": "Last Modified By", | ||
28 | "lastModifiedDate": "Last Modified Date" | ||
29 | } | ||
30 | } | ||
31 | } |
File src/main/webapp/i18n/hu/register.json added (mode: 100644) (index 0000000..d2ea5ff) | |||
1 | { | ||
2 | "register": { | ||
3 | "title": "Regisztráció", | ||
4 | "form": { | ||
5 | "button": "Regisztrálás" | ||
6 | }, | ||
7 | "messages": { | ||
8 | "validate": { | ||
9 | "login": { | ||
10 | "required": "A felhasználói azonosító kötelezően kitöltendő.", | ||
11 | "minlength": "A felhasználói azonosító legalább 1 betűböl kell, hogy álljon", | ||
12 | "maxlength": "A felhasználói azonosító nem lehet több, mint 50 betü", | ||
13 | "pattern": "A felhasználói azonosító csak kisbetükből és számokból állhat." | ||
14 | } | ||
15 | }, | ||
16 | "success": "<strong>A regisztrációt elmentettük!</strong> Kérjük ellenörizze emailjét, ahova a megerősítő emailt küldtük.", | ||
17 | "error": { | ||
18 | "fail": "<strong>A regisztráció nem sikerült!</strong> Kérjük próbálj újra később.", | ||
19 | "userexists": "<strong>A felhasználói azonosítót már más regisztrálta!</strong> Kérjük, válasszon másikat.", | ||
20 | "emailexists": "<strong>Az email cím már használatban van!</strong> Kérjük adjon meg másikat." | ||
21 | } | ||
22 | } | ||
23 | } | ||
24 | } |
File src/main/webapp/i18n/hu/reset.json added (mode: 100644) (index 0000000..f4d523d) | |||
1 | { | ||
2 | "reset": { | ||
3 | "request": { | ||
4 | "title": "Jelszó visszaállítás", | ||
5 | "form": { | ||
6 | "button": "Jelszó visszaállítás" | ||
7 | }, | ||
8 | "messages": { | ||
9 | "info": "Adja meg email címét, amivel regisztrált", | ||
10 | "success": "Email címére elküldtük a leírást, hogyan állíthatja vissza jelszavát." | ||
11 | } | ||
12 | }, | ||
13 | "finish": { | ||
14 | "title": "Jelszó állítás", | ||
15 | "form": { | ||
16 | "button": "Ellenőrizze új jelszavát" | ||
17 | }, | ||
18 | "messages": { | ||
19 | "info": "Válasszon új jelszót", | ||
20 | "success": "<strong>Az Ön jelszava meg lett változtatva.</strong> Kérjük ", | ||
21 | "keymissing": "A jelszó visszaállító kulcs hiányzik.", | ||
22 | "error": "Az Ön jelszavát nem lehetett átállítani. Kérjük vegye figyelembe, hogy a jelszó visszaállító kulcs csak 24 óráig érvényes." | ||
23 | } | ||
24 | } | ||
25 | } | ||
26 | } |
File src/main/webapp/i18n/hu/sessions.json added (mode: 100644) (index 0000000..5b45f61) | |||
1 | { | ||
2 | "sessions": { | ||
3 | "title": "[<strong>{{username}}</strong>]-hoz tartozó aktív munkamenetek", | ||
4 | "table": { | ||
5 | "ipaddress": "IP cím", | ||
6 | "useragent": "Böngésző típusa", | ||
7 | "date": "Dátum", | ||
8 | "button": "Kiléptet" | ||
9 | }, | ||
10 | "messages": { | ||
11 | "success": "<strong>Munkamenet be lett fejezve!</strong>", | ||
12 | "error": "<strong>Hiba történt!</strong> A munkamenetet nem sikerült befejezni." | ||
13 | } | ||
14 | } | ||
15 | } |
File src/main/webapp/i18n/hu/settings.json added (mode: 100644) (index 0000000..1d8ce8f) | |||
1 | { | ||
2 | "settings": { | ||
3 | "title": "Felhasználói beállítások [<strong>{{username}}</strong>]-nak", | ||
4 | "form": { | ||
5 | "firstname": "Keresztnév", | ||
6 | "firstname.placeholder": "Az Ön keresztneve", | ||
7 | "lastname": "Családnév", | ||
8 | "lastname.placeholder": "Az Ön családneve", | ||
9 | "language": "Nyelvek", | ||
10 | "button": "Mentés" | ||
11 | }, | ||
12 | "messages": { | ||
13 | "error": { | ||
14 | "fail": "<strong>Hiba történt!</strong> A beállításokat nem sikerült elmenteni.", | ||
15 | "emailexists": "<strong>Az email cím már használva van!</strong> Kérjük, válasszon másikat." | ||
16 | }, | ||
17 | "success": "<strong>Beállítások elmentésre kerültek!</strong>", | ||
18 | "validate": { | ||
19 | "firstname": { | ||
20 | "required": "A keresztnév kötelező.", | ||
21 | "minlength": "A keresztnév legalább 1 betűböl kell, hogy álljon", | ||
22 | "maxlength": "A keresztnév nem lehet több, mint 50 betü" | ||
23 | }, | ||
24 | "lastname": { | ||
25 | "required": "A családnév kötelező.", | ||
26 | "minlength": "A családnév legalább 1 betűböl kell, hogy álljon", | ||
27 | "maxlength": "A családnév nem lehet több, mint 50 betü" | ||
28 | } | ||
29 | } | ||
30 | } | ||
31 | } | ||
32 | } |
File src/main/webapp/i18n/hu/user-management.json added (mode: 100644) (index 0000000..46903e5) | |||
1 | { | ||
2 | "userManagement": { | ||
3 | "home": { | ||
4 | "title": "Felhasználók", | ||
5 | "createLabel": "Új felhasználó", | ||
6 | "createOrEditLabel": "Felhasználó létrehozás vagy módosítás" | ||
7 | }, | ||
8 | "created": "A new user is created with identifier {{ param }}", | ||
9 | "updated": "A user is updated with identifier {{ param }}", | ||
10 | "deleted": "A user is deleted with identifier {{ param }}", | ||
11 | "delete": { | ||
12 | "question": "Biztos benne, hogy törölni szeretné az {{ login }} azonosítóval rendelkező felhasználót?" | ||
13 | }, | ||
14 | "detail": { | ||
15 | "title": "Felhasználó" | ||
16 | }, | ||
17 | "login": "Azonosító", | ||
18 | "firstName": "Keresztnév", | ||
19 | "lastName": "Vezetéknév", | ||
20 | "email": "Email", | ||
21 | "activated": "Aktivált", | ||
22 | "deactivated": "Deaktivált", | ||
23 | "profiles": "Profil", | ||
24 | "langKey": "Nyelv", | ||
25 | "createdBy": "Létrehozó", | ||
26 | "createdDate": "Létrehozás dátuma", | ||
27 | "lastModifiedBy": "Módosította", | ||
28 | "lastModifiedDate": "Módosítás dátuma" | ||
29 | } | ||
30 | } |
File src/main/webapp/index.html added (mode: 100644) (index 0000000..b7f91d4) | |||
1 | <!doctype html> | ||
2 | <html class="no-js" lang="hu" dir="ltr"> | ||
3 | <head> | ||
4 | <base href="/" /> | ||
5 | <meta charset="utf-8"> | ||
6 | <meta http-equiv="X-UA-Compatible" content="IE=edge"> | ||
7 | <title>honlap</title> | ||
8 | <meta name="description" content="Description for honlap"> | ||
9 | <meta name="google" content="notranslate"> | ||
10 | <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
11 | <meta name="theme-color" content="#000000"> | ||
12 | <link rel="shortcut icon" href="favicon.ico" /> | ||
13 | <link rel="manifest" href="manifest.webapp" /> | ||
14 | <link rel="stylesheet" href="content/css/loading.css"> | ||
15 | <!-- jhipster-needle-add-resources-to-root - JHipster will add new resources here --> | ||
16 | </head> | ||
17 | <body> | ||
18 | <!--[if lt IE 9]> | ||
19 | <p class="browserupgrade">You are using an <strong>outdated</strong> browser. Please <a href="http://browsehappy.com/">upgrade your browser</a> to improve your experience.</p> | ||
20 | <![endif]--> | ||
21 | <auth-main> | ||
22 | <div class="app-loading"> | ||
23 | <div class="lds-css ng-scope"> | ||
24 | <div class="lds-pacman"> | ||
25 | <div><div></div><div></div><div></div></div> | ||
26 | <div><div></div><div></div><div></div></div> | ||
27 | </div> | ||
28 | </div> | ||
29 | </div> | ||
30 | <div class="app-loading"> | ||
31 | <div id="jhipster-error" style="display:none"> | ||
32 | <!-- This content is for troubleshooting purpose and will be removed when app renders --> | ||
33 | <h1>An error has occurred :-(</h1> | ||
34 | <h2>Usual error causes</h2> | ||
35 | <ol> | ||
36 | <li>You started the application from an IDE and you didn't run <code style="color:red">npm start</code> or <code style="color:red">npm run webpack:build</code>.</li> | ||
37 | <li>You had a network error while running <code style="color:red">npm install</code>. If you are behind a corporate proxy, it is likely that this error was caused by your proxy. Have a look at the JHipster error logs, you will probably have the cause of the error.</li> | ||
38 | <li>You installed a Node.js version that doesn't work with JHipster: please use an LTS (long-term support) version, as it's the only version we support.</li> | ||
39 | </ol> | ||
40 | <h2>Building the client side code again</h2> | ||
41 | <p>If you want to go fast, run <code style="color:red">./mvnw</code> to build and run everything.</p> | ||
42 | <p>If you want to have more control, so you can debug your issue more easily, you should follow the following steps:</p> | ||
43 | <ol> | ||
44 | <li>Install npm dependencies with the command <code style="color:red">npm install</code></li> | ||
45 | <li>Build the client with the command <code style="color:red">npm run webpack:build</code> or <code style="color:red">npm start</code></li> | ||
46 | <li>Start the server with <code style="color:red">./mvnw</code> or using your IDE</li> | ||
47 | </ol> | ||
48 | |||
49 | <h2>Getting more help</h2> | ||
50 | |||
51 | <h3>If you have a question on how to use JHipster</h3> | ||
52 | <p> | ||
53 | Go to Stack Overflow with the <a href="http://stackoverflow.com/tags/jhipster" target="_blank" rel="noopener noreferrer">"jhipster"</a> tag. | ||
54 | </p> | ||
55 | |||
56 | <h3>If you have a bug or a feature request</h3> | ||
57 | <p> | ||
58 | First read our <a href="https://github.com/jhipster/generator-jhipster/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">contributing guidelines</a>. | ||
59 | </p> | ||
60 | <p> | ||
61 | Then, fill a ticket on our <a href="https://github.com/jhipster/generator-jhipster/issues/new/choose" target="_blank" rel="noopener noreferrer">bug tracker</a>, we'll be happy to resolve your issue! | ||
62 | </p> | ||
63 | |||
64 | <h3>If you want to chat with contributors and other users</h3> | ||
65 | <p> | ||
66 | Join our chat room on <a href="https://gitter.im/jhipster/generator-jhipster" target="_blank" rel="noopener noreferrer">Gitter.im</a>. Please note that this is a public chat room, and that we expect you to respect other people and write in a correct English language! | ||
67 | </p> | ||
68 | <!-- end of troubleshooting content --> | ||
69 | </div> | ||
70 | </div> | ||
71 | </auth-main> | ||
72 | <noscript> | ||
73 | <h1>You must enable javascript to view this page.</h1> | ||
74 | </noscript> | ||
75 | <script type="text/javascript" language="javascript"> | ||
76 | // show an error message if the app loading takes more than 5 sec | ||
77 | window.onload=function() { | ||
78 | setTimeout(showError, 4000); | ||
79 | } | ||
80 | function showError() { | ||
81 | var errorElm = document.getElementById("jhipster-error"); | ||
82 | if (errorElm && errorElm.style) { | ||
83 | errorElm.style.display = "block"; | ||
84 | } | ||
85 | } | ||
86 | </script> | ||
87 | <!-- uncomment this for adding service worker | ||
88 | <script> | ||
89 | if ('serviceWorker' in navigator) { | ||
90 | window.addEventListener('load', function() { | ||
91 | navigator.serviceWorker.register('/service-worker.js') | ||
92 | .then(function () { | ||
93 | console.log('Service Worker Registered'); | ||
94 | }); | ||
95 | }); | ||
96 | } | ||
97 | </script> | ||
98 | --> | ||
99 | <!-- Google Analytics: uncomment and change UA-XXXXX-X to be your site's ID. | ||
100 | <script> | ||
101 | (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]= | ||
102 | function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date; | ||
103 | e=o.createElement(i);r=o.getElementsByTagName(i)[0]; | ||
104 | e.src='//www.google-analytics.com/analytics.js'; | ||
105 | r.parentNode.insertBefore(e,r)}(window,document,'script','ga')); | ||
106 | ga('create','UA-XXXXX-X');ga('send','pageview'); | ||
107 | </script>--> | ||
108 | </body> | ||
109 | </html> |
File src/main/webapp/manifest.webapp added (mode: 100644) (index 0000000..d498844) | |||
1 | { | ||
2 | "name": "Honlap", | ||
3 | "short_name": "Honlap", | ||
4 | "icons": [ | ||
5 | { | ||
6 | "src": "./content/images/jhipster_family_member_0_head-192.png", | ||
7 | "sizes": "192x192", | ||
8 | "type": "image/png" | ||
9 | }, | ||
10 | { | ||
11 | "src": "./content/images/jhipster_family_member_0_head-256.png", | ||
12 | "sizes": "256x256", | ||
13 | "type": "image/png" | ||
14 | }, | ||
15 | { | ||
16 | "src": "./content/images/jhipster_family_member_0_head-384.png", | ||
17 | "sizes": "384x384", | ||
18 | "type": "image/png" | ||
19 | }, | ||
20 | { | ||
21 | "src": "./content/images/jhipster_family_member_0_head-512.png", | ||
22 | "sizes": "512x512", | ||
23 | "type": "image/png" | ||
24 | } | ||
25 | ], | ||
26 | "theme_color": "#000000", | ||
27 | "background_color": "#e0e0e0", | ||
28 | "start_url": ".", | ||
29 | "display": "standalone", | ||
30 | "orientation": "portrait" | ||
31 | } |
File src/main/webapp/robots.txt added (mode: 100644) (index 0000000..7cda274) | |||
1 | # robotstxt.org/ | ||
2 | |||
3 | User-agent: * | ||
4 | Disallow: /api/account | ||
5 | Disallow: /api/account/change-password | ||
6 | Disallow: /api/account/sessions | ||
7 | Disallow: /api/audits/ | ||
8 | Disallow: /api/logs/ | ||
9 | Disallow: /api/users/ | ||
10 | Disallow: /management/ | ||
11 | Disallow: /v2/api-docs/ |
File src/main/webapp/swagger-ui/dist/images/throbber.gif added (mode: 100644) (index 0000000..0639388) |
File src/main/webapp/swagger-ui/index.html added (mode: 100644) (index 0000000..ae48d7d) | |||
1 | <!DOCTYPE html> | ||
2 | <html lang="en"> | ||
3 | <head> | ||
4 | <meta charset="UTF-8"> | ||
5 | <title>honlap - Swagger UI</title> | ||
6 | <link rel="stylesheet" type="text/css" href="./swagger-ui.css"> | ||
7 | <link rel="icon" type="image/png" href="./favicon-32x32.png" sizes="32x32"/> | ||
8 | <link rel="icon" type="image/png" href="./favicon-16x16.png" sizes="16x16"/> | ||
9 | </head> | ||
10 | |||
11 | <body> | ||
12 | <div id="swagger-ui"></div> | ||
13 | |||
14 | <script src="./swagger-ui-bundle.js"></script> | ||
15 | <script src="./swagger-ui-standalone-preset.js"></script> | ||
16 | <script src="./axios.min.js"></script> | ||
17 | |||
18 | |||
19 | <script type="text/javascript"> | ||
20 | window.onload = function () { | ||
21 | |||
22 | |||
23 | var urls = []; | ||
24 | axios.get("/swagger-resources").then(function (response) { | ||
25 | response.data.forEach(function (resource) { | ||
26 | urls.push({"name": resource.name, "url": resource.location}); | ||
27 | }); | ||
28 | |||
29 | urls.sort(function (a, b) { | ||
30 | var x = a.name.toLowerCase(), y = b.name.toLowerCase(); | ||
31 | return x < y ? -1 : x > y ? 1 : 0; | ||
32 | }); | ||
33 | |||
34 | // Build a system | ||
35 | var ui = SwaggerUIBundle({ | ||
36 | urls: urls, | ||
37 | dom_id: '#swagger-ui', | ||
38 | deepLinking: true, | ||
39 | filter: true, | ||
40 | layout: "StandaloneLayout", | ||
41 | withCredentials: true, | ||
42 | presets: [ | ||
43 | SwaggerUIBundle.presets.apis, | ||
44 | SwaggerUIStandalonePreset | ||
45 | ], | ||
46 | plugins: [ | ||
47 | SwaggerUIBundle.plugins.DownloadUrl | ||
48 | ], | ||
49 | requestInterceptor: function (req) { | ||
50 | var authToken = JSON.parse(localStorage.getItem("auth-authenticationtoken") | ||
51 | || sessionStorage.getItem("auth-authenticationtoken")); | ||
52 | if (authToken) { | ||
53 | req.headers['Authorization'] = "Bearer " + authToken; | ||
54 | } | ||
55 | return req; | ||
56 | } | ||
57 | }); | ||
58 | |||
59 | window.ui = ui | ||
60 | }); | ||
61 | |||
62 | }; | ||
63 | </script> | ||
64 | </body> | ||
65 | </html> |
File src/test/features/gitkeep added (mode: 100644) (index 0000000..e69de29) |
File src/test/features/user/user.feature added (mode: 100644) (index 0000000..978b1d4) | |||
1 | Feature: User management | ||
2 | |||
3 | Scenario: Retrieve administrator user | ||
4 | When I search user 'admin' | ||
5 | Then the user is found | ||
6 | And his last name is 'Administrator' |
File src/test/java/hu/dns/honlap/ArchTest.java added (mode: 100644) (index 0000000..e887541) | |||
1 | package hu.dns.honlap; | ||
2 | |||
3 | import com.tngtech.archunit.core.domain.JavaClasses; | ||
4 | import com.tngtech.archunit.core.importer.ClassFileImporter; | ||
5 | import com.tngtech.archunit.core.importer.ImportOption; | ||
6 | import org.junit.jupiter.api.Test; | ||
7 | |||
8 | import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses; | ||
9 | |||
10 | class ArchTest { | ||
11 | |||
12 | @Test | ||
13 | void servicesAndRepositoriesShouldNotDependOnWebLayer() { | ||
14 | |||
15 | JavaClasses importedClasses = new ClassFileImporter() | ||
16 | .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS) | ||
17 | .importPackages("hu.dns.honlap"); | ||
18 | |||
19 | noClasses() | ||
20 | .that() | ||
21 | .resideInAnyPackage("hu.dns.honlap.service..") | ||
22 | .or() | ||
23 | .resideInAnyPackage("hu.dns.honlap.repository..") | ||
24 | .should().dependOnClassesThat() | ||
25 | .resideInAnyPackage("..hu.dns.honlap.web..") | ||
26 | .because("Services and repositories should not depend on web layer") | ||
27 | .check(importedClasses); | ||
28 | } | ||
29 | } |
File src/test/java/hu/dns/honlap/config/NoOpMailConfiguration.java added (mode: 100644) (index 0000000..d89084e) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import hu.dns.honlap.service.MailService; | ||
4 | import org.springframework.context.annotation.Bean; | ||
5 | import org.springframework.context.annotation.Configuration; | ||
6 | |||
7 | import static org.mockito.ArgumentMatchers.any; | ||
8 | import static org.mockito.Mockito.doNothing; | ||
9 | import static org.mockito.Mockito.mock; | ||
10 | |||
11 | @Configuration | ||
12 | public class NoOpMailConfiguration { | ||
13 | private final MailService mockMailService; | ||
14 | |||
15 | public NoOpMailConfiguration() { | ||
16 | mockMailService = mock(MailService.class); | ||
17 | doNothing().when(mockMailService).sendActivationEmail(any()); | ||
18 | } | ||
19 | |||
20 | @Bean | ||
21 | public MailService mailService() { | ||
22 | return mockMailService; | ||
23 | } | ||
24 | } |
File src/test/java/hu/dns/honlap/config/WebConfigurerTest.java added (mode: 100644) (index 0000000..4e4fd2b) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import io.github.jhipster.config.JHipsterConstants; | ||
4 | import io.github.jhipster.config.JHipsterProperties; | ||
5 | import io.github.jhipster.web.filter.CachingHttpHeadersFilter; | ||
6 | import org.h2.server.web.WebServlet; | ||
7 | import org.junit.jupiter.api.BeforeEach; | ||
8 | import org.junit.jupiter.api.Test; | ||
9 | import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; | ||
10 | import org.springframework.http.HttpHeaders; | ||
11 | import org.springframework.mock.env.MockEnvironment; | ||
12 | import org.springframework.mock.web.MockServletContext; | ||
13 | import org.springframework.test.web.servlet.MockMvc; | ||
14 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
15 | |||
16 | import javax.servlet.*; | ||
17 | import java.io.File; | ||
18 | import java.util.*; | ||
19 | |||
20 | import static org.assertj.core.api.Assertions.assertThat; | ||
21 | import static org.mockito.ArgumentMatchers.any; | ||
22 | import static org.mockito.ArgumentMatchers.anyString; | ||
23 | import static org.mockito.Mockito.*; | ||
24 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
25 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options; | ||
26 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; | ||
27 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
28 | |||
29 | /** | ||
30 | * Unit tests for the {@link WebConfigurer} class. | ||
31 | */ | ||
32 | public class WebConfigurerTest { | ||
33 | |||
34 | private WebConfigurer webConfigurer; | ||
35 | |||
36 | private MockServletContext servletContext; | ||
37 | |||
38 | private MockEnvironment env; | ||
39 | |||
40 | private JHipsterProperties props; | ||
41 | |||
42 | @BeforeEach | ||
43 | public void setup() { | ||
44 | servletContext = spy(new MockServletContext()); | ||
45 | doReturn(mock(FilterRegistration.Dynamic.class)) | ||
46 | .when(servletContext).addFilter(anyString(), any(Filter.class)); | ||
47 | doReturn(mock(ServletRegistration.Dynamic.class)) | ||
48 | .when(servletContext).addServlet(anyString(), any(Servlet.class)); | ||
49 | |||
50 | env = new MockEnvironment(); | ||
51 | props = new JHipsterProperties(); | ||
52 | |||
53 | webConfigurer = new WebConfigurer(env, props); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | public void testStartUpProdServletContext() throws ServletException { | ||
58 | env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION); | ||
59 | webConfigurer.onStartup(servletContext); | ||
60 | |||
61 | verify(servletContext).addFilter(eq("cachingHttpHeadersFilter"), any(CachingHttpHeadersFilter.class)); | ||
62 | verify(servletContext, never()).addServlet(eq("H2Console"), any(WebServlet.class)); | ||
63 | } | ||
64 | |||
65 | @Test | ||
66 | public void testStartUpDevServletContext() throws ServletException { | ||
67 | env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_DEVELOPMENT); | ||
68 | webConfigurer.onStartup(servletContext); | ||
69 | |||
70 | verify(servletContext, never()).addFilter(eq("cachingHttpHeadersFilter"), any(CachingHttpHeadersFilter.class)); | ||
71 | verify(servletContext).addServlet(eq("H2Console"), any(WebServlet.class)); | ||
72 | } | ||
73 | |||
74 | @Test | ||
75 | public void testCustomizeServletContainer() { | ||
76 | env.setActiveProfiles(JHipsterConstants.SPRING_PROFILE_PRODUCTION); | ||
77 | UndertowServletWebServerFactory container = new UndertowServletWebServerFactory(); | ||
78 | webConfigurer.customize(container); | ||
79 | assertThat(container.getMimeMappings().get("abs")).isEqualTo("audio/x-mpeg"); | ||
80 | assertThat(container.getMimeMappings().get("html")).isEqualTo("text/html;charset=utf-8"); | ||
81 | assertThat(container.getMimeMappings().get("json")).isEqualTo("text/html;charset=utf-8"); | ||
82 | if (container.getDocumentRoot() != null) { | ||
83 | assertThat(container.getDocumentRoot()).isEqualTo(new File("target/classes/static/")); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | @Test | ||
88 | public void testCorsFilterOnApiPath() throws Exception { | ||
89 | props.getCors().setAllowedOrigins(Collections.singletonList("*")); | ||
90 | props.getCors().setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); | ||
91 | props.getCors().setAllowedHeaders(Collections.singletonList("*")); | ||
92 | props.getCors().setMaxAge(1800L); | ||
93 | props.getCors().setAllowCredentials(true); | ||
94 | |||
95 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) | ||
96 | .addFilters(webConfigurer.corsFilter()) | ||
97 | .build(); | ||
98 | |||
99 | mockMvc.perform( | ||
100 | options("/api/test-cors") | ||
101 | .header(HttpHeaders.ORIGIN, "other.domain.com") | ||
102 | .header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST")) | ||
103 | .andExpect(status().isOk()) | ||
104 | .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com")) | ||
105 | .andExpect(header().string(HttpHeaders.VARY, "Origin")) | ||
106 | .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE")) | ||
107 | .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true")) | ||
108 | .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800")); | ||
109 | |||
110 | mockMvc.perform( | ||
111 | get("/api/test-cors") | ||
112 | .header(HttpHeaders.ORIGIN, "other.domain.com")) | ||
113 | .andExpect(status().isOk()) | ||
114 | .andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com")); | ||
115 | } | ||
116 | |||
117 | @Test | ||
118 | public void testCorsFilterOnOtherPath() throws Exception { | ||
119 | props.getCors().setAllowedOrigins(Collections.singletonList("*")); | ||
120 | props.getCors().setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); | ||
121 | props.getCors().setAllowedHeaders(Collections.singletonList("*")); | ||
122 | props.getCors().setMaxAge(1800L); | ||
123 | props.getCors().setAllowCredentials(true); | ||
124 | |||
125 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) | ||
126 | .addFilters(webConfigurer.corsFilter()) | ||
127 | .build(); | ||
128 | |||
129 | mockMvc.perform( | ||
130 | get("/test/test-cors") | ||
131 | .header(HttpHeaders.ORIGIN, "other.domain.com")) | ||
132 | .andExpect(status().isOk()) | ||
133 | .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); | ||
134 | } | ||
135 | |||
136 | @Test | ||
137 | public void testCorsFilterDeactivated() throws Exception { | ||
138 | props.getCors().setAllowedOrigins(null); | ||
139 | |||
140 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) | ||
141 | .addFilters(webConfigurer.corsFilter()) | ||
142 | .build(); | ||
143 | |||
144 | mockMvc.perform( | ||
145 | get("/api/test-cors") | ||
146 | .header(HttpHeaders.ORIGIN, "other.domain.com")) | ||
147 | .andExpect(status().isOk()) | ||
148 | .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); | ||
149 | } | ||
150 | |||
151 | @Test | ||
152 | public void testCorsFilterDeactivated2() throws Exception { | ||
153 | props.getCors().setAllowedOrigins(new ArrayList<>()); | ||
154 | |||
155 | MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()) | ||
156 | .addFilters(webConfigurer.corsFilter()) | ||
157 | .build(); | ||
158 | |||
159 | mockMvc.perform( | ||
160 | get("/api/test-cors") | ||
161 | .header(HttpHeaders.ORIGIN, "other.domain.com")) | ||
162 | .andExpect(status().isOk()) | ||
163 | .andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)); | ||
164 | } | ||
165 | } |
File src/test/java/hu/dns/honlap/config/WebConfigurerTestController.java added (mode: 100644) (index 0000000..bbca64f) | |||
1 | package hu.dns.honlap.config; | ||
2 | |||
3 | import org.springframework.web.bind.annotation.GetMapping; | ||
4 | import org.springframework.web.bind.annotation.RestController; | ||
5 | |||
6 | @RestController | ||
7 | public class WebConfigurerTestController { | ||
8 | |||
9 | @GetMapping("/api/test-cors") | ||
10 | public void testCorsOnApiPath() { | ||
11 | } | ||
12 | |||
13 | @GetMapping("/test/test-cors") | ||
14 | public void testCorsOnOtherPath() { | ||
15 | } | ||
16 | } |
File src/test/java/hu/dns/honlap/config/timezone/HibernateTimeZoneIT.java added (mode: 100644) (index 0000000..789c929) | |||
1 | package hu.dns.honlap.config.timezone; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.repository.timezone.DateTimeWrapper; | ||
5 | import hu.dns.honlap.repository.timezone.DateTimeWrapperRepository; | ||
6 | import org.junit.jupiter.api.BeforeEach; | ||
7 | import org.junit.jupiter.api.Test; | ||
8 | import org.springframework.beans.factory.annotation.Autowired; | ||
9 | import org.springframework.boot.test.context.SpringBootTest; | ||
10 | import org.springframework.jdbc.core.JdbcTemplate; | ||
11 | import org.springframework.jdbc.support.rowset.SqlRowSet; | ||
12 | import org.springframework.transaction.annotation.Transactional; | ||
13 | |||
14 | import java.time.*; | ||
15 | import java.time.format.DateTimeFormatter; | ||
16 | |||
17 | import static java.lang.String.format; | ||
18 | import static org.assertj.core.api.Assertions.assertThat; | ||
19 | |||
20 | /** | ||
21 | * Integration tests for the UTC Hibernate configuration. | ||
22 | */ | ||
23 | @SpringBootTest(classes = HonlapApp.class) | ||
24 | public class HibernateTimeZoneIT { | ||
25 | |||
26 | @Autowired | ||
27 | private DateTimeWrapperRepository dateTimeWrapperRepository; | ||
28 | @Autowired | ||
29 | private JdbcTemplate jdbcTemplate; | ||
30 | |||
31 | private DateTimeWrapper dateTimeWrapper; | ||
32 | private DateTimeFormatter dateTimeFormatter; | ||
33 | private DateTimeFormatter timeFormatter; | ||
34 | private DateTimeFormatter dateFormatter; | ||
35 | |||
36 | @BeforeEach | ||
37 | public void setup() { | ||
38 | dateTimeWrapper = new DateTimeWrapper(); | ||
39 | dateTimeWrapper.setInstant(Instant.parse("2014-11-12T05:50:00.0Z")); | ||
40 | dateTimeWrapper.setLocalDateTime(LocalDateTime.parse("2014-11-12T07:50:00.0")); | ||
41 | dateTimeWrapper.setOffsetDateTime(OffsetDateTime.parse("2011-12-14T08:30:00.0Z")); | ||
42 | dateTimeWrapper.setZonedDateTime(ZonedDateTime.parse("2011-12-14T08:30:00.0Z")); | ||
43 | dateTimeWrapper.setLocalTime(LocalTime.parse("14:30:00")); | ||
44 | dateTimeWrapper.setOffsetTime(OffsetTime.parse("14:30:00+02:00")); | ||
45 | dateTimeWrapper.setLocalDate(LocalDate.parse("2016-09-10")); | ||
46 | |||
47 | dateTimeFormatter = DateTimeFormatter | ||
48 | .ofPattern("yyyy-MM-dd HH:mm:ss.S") | ||
49 | .withZone(ZoneId.of("UTC")); | ||
50 | |||
51 | timeFormatter = DateTimeFormatter | ||
52 | .ofPattern("HH:mm:ss") | ||
53 | .withZone(ZoneId.of("UTC")); | ||
54 | |||
55 | dateFormatter = DateTimeFormatter | ||
56 | .ofPattern("yyyy-MM-dd"); | ||
57 | } | ||
58 | |||
59 | @Test | ||
60 | @Transactional | ||
61 | public void storeInstantWithUtcConfigShouldBeStoredOnGMTTimeZone() { | ||
62 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
63 | |||
64 | String request = generateSqlRequest("instant", dateTimeWrapper.getId()); | ||
65 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
66 | String expectedValue = dateTimeFormatter.format(dateTimeWrapper.getInstant()); | ||
67 | |||
68 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
69 | } | ||
70 | |||
71 | @Test | ||
72 | @Transactional | ||
73 | public void storeLocalDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { | ||
74 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
75 | |||
76 | String request = generateSqlRequest("local_date_time", dateTimeWrapper.getId()); | ||
77 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
78 | String expectedValue = dateTimeWrapper | ||
79 | .getLocalDateTime() | ||
80 | .atZone(ZoneId.systemDefault()) | ||
81 | .format(dateTimeFormatter); | ||
82 | |||
83 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | @Transactional | ||
88 | public void storeOffsetDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { | ||
89 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
90 | |||
91 | String request = generateSqlRequest("offset_date_time", dateTimeWrapper.getId()); | ||
92 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
93 | String expectedValue = dateTimeWrapper | ||
94 | .getOffsetDateTime() | ||
95 | .format(dateTimeFormatter); | ||
96 | |||
97 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
98 | } | ||
99 | |||
100 | @Test | ||
101 | @Transactional | ||
102 | public void storeZoneDateTimeWithUtcConfigShouldBeStoredOnGMTTimeZone() { | ||
103 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
104 | |||
105 | String request = generateSqlRequest("zoned_date_time", dateTimeWrapper.getId()); | ||
106 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
107 | String expectedValue = dateTimeWrapper | ||
108 | .getZonedDateTime() | ||
109 | .format(dateTimeFormatter); | ||
110 | |||
111 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
112 | } | ||
113 | |||
114 | @Test | ||
115 | @Transactional | ||
116 | public void storeLocalTimeWithUtcConfigShouldBeStoredOnGMTTimeZoneAccordingToHis1stJan1970Value() { | ||
117 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
118 | |||
119 | String request = generateSqlRequest("local_time", dateTimeWrapper.getId()); | ||
120 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
121 | String expectedValue = dateTimeWrapper | ||
122 | .getLocalTime() | ||
123 | .atDate(LocalDate.of(1970, Month.JANUARY, 1)) | ||
124 | .atZone(ZoneId.systemDefault()) | ||
125 | .format(timeFormatter); | ||
126 | |||
127 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
128 | } | ||
129 | |||
130 | @Test | ||
131 | @Transactional | ||
132 | public void storeOffsetTimeWithUtcConfigShouldBeStoredOnGMTTimeZoneAccordingToHis1stJan1970Value() { | ||
133 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
134 | |||
135 | String request = generateSqlRequest("offset_time", dateTimeWrapper.getId()); | ||
136 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
137 | String expectedValue = dateTimeWrapper | ||
138 | .getOffsetTime() | ||
139 | .toLocalTime() | ||
140 | .atDate(LocalDate.of(1970, Month.JANUARY, 1)) | ||
141 | .atZone(ZoneId.systemDefault()) | ||
142 | .format(timeFormatter); | ||
143 | |||
144 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
145 | } | ||
146 | |||
147 | @Test | ||
148 | @Transactional | ||
149 | public void storeLocalDateWithUtcConfigShouldBeStoredWithoutTransformation() { | ||
150 | dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper); | ||
151 | |||
152 | String request = generateSqlRequest("local_date", dateTimeWrapper.getId()); | ||
153 | SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request); | ||
154 | String expectedValue = dateTimeWrapper | ||
155 | .getLocalDate() | ||
156 | .format(dateFormatter); | ||
157 | |||
158 | assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(resultSet, expectedValue); | ||
159 | } | ||
160 | |||
161 | private String generateSqlRequest(String fieldName, long id) { | ||
162 | return format("SELECT %s FROM auth_date_time_wrapper where id=%d", fieldName, id); | ||
163 | } | ||
164 | |||
165 | private void assertThatDateStoredValueIsEqualToInsertDateValueOnGMTTimeZone(SqlRowSet sqlRowSet, String expectedValue) { | ||
166 | while (sqlRowSet.next()) { | ||
167 | String dbValue = sqlRowSet.getString(1); | ||
168 | |||
169 | assertThat(dbValue).isNotNull(); | ||
170 | assertThat(dbValue).isEqualTo(expectedValue); | ||
171 | } | ||
172 | } | ||
173 | } |
File src/test/java/hu/dns/honlap/cucumber/CucumberContextConfiguration.java added (mode: 100644) (index 0000000..70ca318) | |||
1 | package hu.dns.honlap.cucumber; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import io.cucumber.java.Before; | ||
5 | import org.springframework.boot.test.context.SpringBootTest; | ||
6 | import org.springframework.test.context.ContextConfiguration; | ||
7 | import org.springframework.test.context.web.WebAppConfiguration; | ||
8 | |||
9 | @SpringBootTest | ||
10 | @WebAppConfiguration | ||
11 | @ContextConfiguration(classes = HonlapApp.class) | ||
12 | public class CucumberContextConfiguration { | ||
13 | |||
14 | @Before | ||
15 | public void setup_cucumber_spring_context() { | ||
16 | // Dummy method so cucumber will recognize this class as glue | ||
17 | // and use its context configuration. | ||
18 | } | ||
19 | |||
20 | } |
File src/test/java/hu/dns/honlap/cucumber/CucumberIT.java added (mode: 100644) (index 0000000..6e70899) | |||
1 | package hu.dns.honlap.cucumber; | ||
2 | |||
3 | import org.junit.runner.RunWith; | ||
4 | |||
5 | import io.cucumber.junit.CucumberOptions; | ||
6 | import io.cucumber.junit.Cucumber; | ||
7 | |||
8 | @RunWith(Cucumber.class) | ||
9 | @CucumberOptions(plugin = "pretty", features = "src/test/features") | ||
10 | public class CucumberIT { | ||
11 | |||
12 | } |
File src/test/java/hu/dns/honlap/cucumber/stepdefs/StepDefs.java added (mode: 100644) (index 0000000..bb3b798) | |||
1 | package hu.dns.honlap.cucumber.stepdefs; | ||
2 | |||
3 | import org.springframework.test.web.servlet.ResultActions; | ||
4 | |||
5 | public abstract class StepDefs { | ||
6 | |||
7 | protected ResultActions actions; | ||
8 | |||
9 | } |
File src/test/java/hu/dns/honlap/cucumber/stepdefs/UserStepDefs.java added (mode: 100644) (index 0000000..8ef9d20) | |||
1 | package hu.dns.honlap.cucumber.stepdefs; | ||
2 | |||
3 | import io.cucumber.java.Before; | ||
4 | import io.cucumber.java.en.Then; | ||
5 | import io.cucumber.java.en.When; | ||
6 | |||
7 | import org.springframework.beans.factory.annotation.Autowired; | ||
8 | import org.springframework.http.MediaType; | ||
9 | import org.springframework.test.web.servlet.MockMvc; | ||
10 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
11 | |||
12 | import hu.dns.honlap.web.rest.UserResource; | ||
13 | |||
14 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
15 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
16 | |||
17 | public class UserStepDefs extends StepDefs { | ||
18 | |||
19 | @Autowired | ||
20 | private UserResource userResource; | ||
21 | |||
22 | private MockMvc restUserMockMvc; | ||
23 | |||
24 | @Before | ||
25 | public void setup() { | ||
26 | this.restUserMockMvc = MockMvcBuilders.standaloneSetup(userResource).build(); | ||
27 | } | ||
28 | |||
29 | @When("I search user {string}") | ||
30 | public void i_search_user(String userId) throws Throwable { | ||
31 | actions = restUserMockMvc.perform(get("/api/users/" + userId) | ||
32 | .accept(MediaType.APPLICATION_JSON)); | ||
33 | } | ||
34 | |||
35 | @Then("the user is found") | ||
36 | public void the_user_is_found() throws Throwable { | ||
37 | actions | ||
38 | .andExpect(status().isOk()) | ||
39 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)); | ||
40 | } | ||
41 | |||
42 | @Then("his last name is {string}") | ||
43 | public void his_last_name_is(String lastName) throws Throwable { | ||
44 | actions.andExpect(jsonPath("$.lastName").value(lastName)); | ||
45 | } | ||
46 | |||
47 | } |
File src/test/java/hu/dns/honlap/domain/PieceOfNewsTest.java added (mode: 100644) (index 0000000..17a28d9) | |||
1 | package hu.dns.honlap.domain; | ||
2 | |||
3 | import org.junit.jupiter.api.Test; | ||
4 | import static org.assertj.core.api.Assertions.assertThat; | ||
5 | import hu.dns.honlap.web.rest.TestUtil; | ||
6 | |||
7 | public class PieceOfNewsTest { | ||
8 | |||
9 | @Test | ||
10 | public void equalsVerifier() throws Exception { | ||
11 | TestUtil.equalsVerifier(PieceOfNews.class); | ||
12 | PieceOfNews pieceOfNews1 = new PieceOfNews(); | ||
13 | pieceOfNews1.setId(1L); | ||
14 | PieceOfNews pieceOfNews2 = new PieceOfNews(); | ||
15 | pieceOfNews2.setId(pieceOfNews1.getId()); | ||
16 | assertThat(pieceOfNews1).isEqualTo(pieceOfNews2); | ||
17 | pieceOfNews2.setId(2L); | ||
18 | assertThat(pieceOfNews1).isNotEqualTo(pieceOfNews2); | ||
19 | pieceOfNews1.setId(null); | ||
20 | assertThat(pieceOfNews1).isNotEqualTo(pieceOfNews2); | ||
21 | } | ||
22 | } |
File src/test/java/hu/dns/honlap/repository/CustomAuditEventRepositoryIT.java added (mode: 100644) (index 0000000..72c0a1b) | |||
1 | package hu.dns.honlap.repository; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | |||
5 | import hu.dns.honlap.config.Constants; | ||
6 | import hu.dns.honlap.config.audit.AuditEventConverter; | ||
7 | import hu.dns.honlap.domain.PersistentAuditEvent; | ||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import org.springframework.beans.factory.annotation.Autowired; | ||
11 | import org.springframework.boot.actuate.audit.AuditEvent; | ||
12 | import org.springframework.boot.test.context.SpringBootTest; | ||
13 | import org.springframework.mock.web.MockHttpServletRequest; | ||
14 | import org.springframework.mock.web.MockHttpSession; | ||
15 | import org.springframework.security.web.authentication.WebAuthenticationDetails; | ||
16 | import org.springframework.transaction.annotation.Transactional; | ||
17 | |||
18 | import javax.servlet.http.HttpSession; | ||
19 | import java.time.Instant; | ||
20 | import java.time.temporal.ChronoUnit; | ||
21 | import java.util.HashMap; | ||
22 | import java.util.List; | ||
23 | import java.util.Map; | ||
24 | |||
25 | import static org.assertj.core.api.Assertions.assertThat; | ||
26 | import static hu.dns.honlap.repository.CustomAuditEventRepository.EVENT_DATA_COLUMN_MAX_LENGTH; | ||
27 | |||
28 | /** | ||
29 | * Integration tests for {@link CustomAuditEventRepository}. | ||
30 | */ | ||
31 | @SpringBootTest(classes = HonlapApp.class) | ||
32 | @Transactional | ||
33 | public class CustomAuditEventRepositoryIT { | ||
34 | |||
35 | @Autowired | ||
36 | private PersistenceAuditEventRepository persistenceAuditEventRepository; | ||
37 | |||
38 | @Autowired | ||
39 | private AuditEventConverter auditEventConverter; | ||
40 | |||
41 | private CustomAuditEventRepository customAuditEventRepository; | ||
42 | |||
43 | @BeforeEach | ||
44 | public void setup() { | ||
45 | customAuditEventRepository = new CustomAuditEventRepository(persistenceAuditEventRepository, auditEventConverter); | ||
46 | persistenceAuditEventRepository.deleteAll(); | ||
47 | Instant oneHourAgo = Instant.now().minusSeconds(3600); | ||
48 | |||
49 | PersistentAuditEvent testUserEvent = new PersistentAuditEvent(); | ||
50 | testUserEvent.setPrincipal("test-user"); | ||
51 | testUserEvent.setAuditEventType("test-type"); | ||
52 | testUserEvent.setAuditEventDate(oneHourAgo); | ||
53 | Map<String, String> data = new HashMap<>(); | ||
54 | data.put("test-key", "test-value"); | ||
55 | testUserEvent.setData(data); | ||
56 | |||
57 | PersistentAuditEvent testOldUserEvent = new PersistentAuditEvent(); | ||
58 | testOldUserEvent.setPrincipal("test-user"); | ||
59 | testOldUserEvent.setAuditEventType("test-type"); | ||
60 | testOldUserEvent.setAuditEventDate(oneHourAgo.minusSeconds(10000)); | ||
61 | |||
62 | PersistentAuditEvent testOtherUserEvent = new PersistentAuditEvent(); | ||
63 | testOtherUserEvent.setPrincipal("other-test-user"); | ||
64 | testOtherUserEvent.setAuditEventType("test-type"); | ||
65 | testOtherUserEvent.setAuditEventDate(oneHourAgo); | ||
66 | } | ||
67 | |||
68 | @Test | ||
69 | public void addAuditEvent() { | ||
70 | Map<String, Object> data = new HashMap<>(); | ||
71 | data.put("test-key", "test-value"); | ||
72 | AuditEvent event = new AuditEvent("test-user", "test-type", data); | ||
73 | customAuditEventRepository.add(event); | ||
74 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
75 | assertThat(persistentAuditEvents).hasSize(1); | ||
76 | PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); | ||
77 | assertThat(persistentAuditEvent.getPrincipal()).isEqualTo(event.getPrincipal()); | ||
78 | assertThat(persistentAuditEvent.getAuditEventType()).isEqualTo(event.getType()); | ||
79 | assertThat(persistentAuditEvent.getData()).containsKey("test-key"); | ||
80 | assertThat(persistentAuditEvent.getData().get("test-key")).isEqualTo("test-value"); | ||
81 | assertThat(persistentAuditEvent.getAuditEventDate().truncatedTo(ChronoUnit.MILLIS)) | ||
82 | .isEqualTo(event.getTimestamp().truncatedTo(ChronoUnit.MILLIS)); | ||
83 | } | ||
84 | |||
85 | @Test | ||
86 | public void addAuditEventTruncateLargeData() { | ||
87 | Map<String, Object> data = new HashMap<>(); | ||
88 | StringBuilder largeData = new StringBuilder(); | ||
89 | for (int i = 0; i < EVENT_DATA_COLUMN_MAX_LENGTH + 10; i++) { | ||
90 | largeData.append("a"); | ||
91 | } | ||
92 | data.put("test-key", largeData); | ||
93 | AuditEvent event = new AuditEvent("test-user", "test-type", data); | ||
94 | customAuditEventRepository.add(event); | ||
95 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
96 | assertThat(persistentAuditEvents).hasSize(1); | ||
97 | PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); | ||
98 | assertThat(persistentAuditEvent.getPrincipal()).isEqualTo(event.getPrincipal()); | ||
99 | assertThat(persistentAuditEvent.getAuditEventType()).isEqualTo(event.getType()); | ||
100 | assertThat(persistentAuditEvent.getData()).containsKey("test-key"); | ||
101 | String actualData = persistentAuditEvent.getData().get("test-key"); | ||
102 | assertThat(actualData.length()).isEqualTo(EVENT_DATA_COLUMN_MAX_LENGTH); | ||
103 | assertThat(actualData).isSubstringOf(largeData); | ||
104 | assertThat(persistentAuditEvent.getAuditEventDate().truncatedTo(ChronoUnit.MILLIS)) | ||
105 | .isEqualTo(event.getTimestamp().truncatedTo(ChronoUnit.MILLIS)); | ||
106 | } | ||
107 | |||
108 | @Test | ||
109 | public void testAddEventWithWebAuthenticationDetails() { | ||
110 | HttpSession session = new MockHttpSession(null, "test-session-id"); | ||
111 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
112 | request.setSession(session); | ||
113 | request.setRemoteAddr("1.2.3.4"); | ||
114 | WebAuthenticationDetails details = new WebAuthenticationDetails(request); | ||
115 | Map<String, Object> data = new HashMap<>(); | ||
116 | data.put("test-key", details); | ||
117 | AuditEvent event = new AuditEvent("test-user", "test-type", data); | ||
118 | customAuditEventRepository.add(event); | ||
119 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
120 | assertThat(persistentAuditEvents).hasSize(1); | ||
121 | PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); | ||
122 | assertThat(persistentAuditEvent.getData().get("remoteAddress")).isEqualTo("1.2.3.4"); | ||
123 | assertThat(persistentAuditEvent.getData().get("sessionId")).isEqualTo("test-session-id"); | ||
124 | } | ||
125 | |||
126 | @Test | ||
127 | public void testAddEventWithNullData() { | ||
128 | Map<String, Object> data = new HashMap<>(); | ||
129 | data.put("test-key", null); | ||
130 | AuditEvent event = new AuditEvent("test-user", "test-type", data); | ||
131 | customAuditEventRepository.add(event); | ||
132 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
133 | assertThat(persistentAuditEvents).hasSize(1); | ||
134 | PersistentAuditEvent persistentAuditEvent = persistentAuditEvents.get(0); | ||
135 | assertThat(persistentAuditEvent.getData().get("test-key")).isEqualTo("null"); | ||
136 | } | ||
137 | |||
138 | @Test | ||
139 | public void addAuditEventWithAnonymousUser() { | ||
140 | Map<String, Object> data = new HashMap<>(); | ||
141 | data.put("test-key", "test-value"); | ||
142 | AuditEvent event = new AuditEvent(Constants.ANONYMOUS_USER, "test-type", data); | ||
143 | customAuditEventRepository.add(event); | ||
144 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
145 | assertThat(persistentAuditEvents).hasSize(0); | ||
146 | } | ||
147 | |||
148 | @Test | ||
149 | public void addAuditEventWithAuthorizationFailureType() { | ||
150 | Map<String, Object> data = new HashMap<>(); | ||
151 | data.put("test-key", "test-value"); | ||
152 | AuditEvent event = new AuditEvent("test-user", "AUTHORIZATION_FAILURE", data); | ||
153 | customAuditEventRepository.add(event); | ||
154 | List<PersistentAuditEvent> persistentAuditEvents = persistenceAuditEventRepository.findAll(); | ||
155 | assertThat(persistentAuditEvents).hasSize(0); | ||
156 | } | ||
157 | |||
158 | } |
File src/test/java/hu/dns/honlap/repository/timezone/DateTimeWrapper.java added (mode: 100644) (index 0000000..70442c3) | |||
1 | package hu.dns.honlap.repository.timezone; | ||
2 | |||
3 | import javax.persistence.*; | ||
4 | import java.io.Serializable; | ||
5 | import java.time.*; | ||
6 | import java.util.Objects; | ||
7 | |||
8 | @Entity | ||
9 | @Table(name = "auth_date_time_wrapper") | ||
10 | public class DateTimeWrapper implements Serializable { | ||
11 | |||
12 | private static final long serialVersionUID = 1L; | ||
13 | |||
14 | @Id | ||
15 | @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator") | ||
16 | @SequenceGenerator(name = "sequenceGenerator") | ||
17 | private Long id; | ||
18 | |||
19 | @Column(name = "instant") | ||
20 | private Instant instant; | ||
21 | |||
22 | @Column(name = "local_date_time") | ||
23 | private LocalDateTime localDateTime; | ||
24 | |||
25 | @Column(name = "offset_date_time") | ||
26 | private OffsetDateTime offsetDateTime; | ||
27 | |||
28 | @Column(name = "zoned_date_time") | ||
29 | private ZonedDateTime zonedDateTime; | ||
30 | |||
31 | @Column(name = "local_time") | ||
32 | private LocalTime localTime; | ||
33 | |||
34 | @Column(name = "offset_time") | ||
35 | private OffsetTime offsetTime; | ||
36 | |||
37 | @Column(name = "local_date") | ||
38 | private LocalDate localDate; | ||
39 | |||
40 | public Long getId() { | ||
41 | return id; | ||
42 | } | ||
43 | |||
44 | public void setId(Long id) { | ||
45 | this.id = id; | ||
46 | } | ||
47 | |||
48 | public Instant getInstant() { | ||
49 | return instant; | ||
50 | } | ||
51 | |||
52 | public void setInstant(Instant instant) { | ||
53 | this.instant = instant; | ||
54 | } | ||
55 | |||
56 | public LocalDateTime getLocalDateTime() { | ||
57 | return localDateTime; | ||
58 | } | ||
59 | |||
60 | public void setLocalDateTime(LocalDateTime localDateTime) { | ||
61 | this.localDateTime = localDateTime; | ||
62 | } | ||
63 | |||
64 | public OffsetDateTime getOffsetDateTime() { | ||
65 | return offsetDateTime; | ||
66 | } | ||
67 | |||
68 | public void setOffsetDateTime(OffsetDateTime offsetDateTime) { | ||
69 | this.offsetDateTime = offsetDateTime; | ||
70 | } | ||
71 | |||
72 | public ZonedDateTime getZonedDateTime() { | ||
73 | return zonedDateTime; | ||
74 | } | ||
75 | |||
76 | public void setZonedDateTime(ZonedDateTime zonedDateTime) { | ||
77 | this.zonedDateTime = zonedDateTime; | ||
78 | } | ||
79 | |||
80 | public LocalTime getLocalTime() { | ||
81 | return localTime; | ||
82 | } | ||
83 | |||
84 | public void setLocalTime(LocalTime localTime) { | ||
85 | this.localTime = localTime; | ||
86 | } | ||
87 | |||
88 | public OffsetTime getOffsetTime() { | ||
89 | return offsetTime; | ||
90 | } | ||
91 | |||
92 | public void setOffsetTime(OffsetTime offsetTime) { | ||
93 | this.offsetTime = offsetTime; | ||
94 | } | ||
95 | |||
96 | public LocalDate getLocalDate() { | ||
97 | return localDate; | ||
98 | } | ||
99 | |||
100 | public void setLocalDate(LocalDate localDate) { | ||
101 | this.localDate = localDate; | ||
102 | } | ||
103 | |||
104 | @Override | ||
105 | public boolean equals(Object o) { | ||
106 | if (this == o) { | ||
107 | return true; | ||
108 | } | ||
109 | if (o == null || getClass() != o.getClass()) { | ||
110 | return false; | ||
111 | } | ||
112 | |||
113 | DateTimeWrapper dateTimeWrapper = (DateTimeWrapper) o; | ||
114 | return !(dateTimeWrapper.getId() == null || getId() == null) && Objects.equals(getId(), dateTimeWrapper.getId()); | ||
115 | } | ||
116 | |||
117 | @Override | ||
118 | public int hashCode() { | ||
119 | return Objects.hashCode(getId()); | ||
120 | } | ||
121 | |||
122 | @Override | ||
123 | public String toString() { | ||
124 | return "TimeZoneTest{" + | ||
125 | "id=" + id + | ||
126 | ", instant=" + instant + | ||
127 | ", localDateTime=" + localDateTime + | ||
128 | ", offsetDateTime=" + offsetDateTime + | ||
129 | ", zonedDateTime=" + zonedDateTime + | ||
130 | '}'; | ||
131 | } | ||
132 | } |
File src/test/java/hu/dns/honlap/repository/timezone/DateTimeWrapperRepository.java added (mode: 100644) (index 0000000..bead6ba) | |||
1 | package hu.dns.honlap.repository.timezone; | ||
2 | |||
3 | import org.springframework.data.jpa.repository.JpaRepository; | ||
4 | import org.springframework.stereotype.Repository; | ||
5 | |||
6 | /** | ||
7 | * Spring Data JPA repository for the {@link DateTimeWrapper} entity. | ||
8 | */ | ||
9 | @Repository | ||
10 | public interface DateTimeWrapperRepository extends JpaRepository<DateTimeWrapper, Long> { | ||
11 | |||
12 | } |
File src/test/java/hu/dns/honlap/security/DomainUserDetailsServiceIT.java added (mode: 100644) (index 0000000..589c01d) | |||
1 | package hu.dns.honlap.security; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.domain.User; | ||
5 | import hu.dns.honlap.repository.UserRepository; | ||
6 | |||
7 | import org.apache.commons.lang3.RandomStringUtils; | ||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import org.springframework.beans.factory.annotation.Autowired; | ||
11 | import org.springframework.boot.test.context.SpringBootTest; | ||
12 | import org.springframework.security.core.userdetails.UserDetails; | ||
13 | import org.springframework.security.core.userdetails.UserDetailsService; | ||
14 | import org.springframework.transaction.annotation.Transactional; | ||
15 | |||
16 | import java.util.Locale; | ||
17 | |||
18 | import static org.assertj.core.api.Assertions.assertThat; | ||
19 | import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||
20 | |||
21 | /** | ||
22 | * Integrations tests for {@link DomainUserDetailsService}. | ||
23 | */ | ||
24 | @SpringBootTest(classes = HonlapApp.class) | ||
25 | @Transactional | ||
26 | public class DomainUserDetailsServiceIT { | ||
27 | |||
28 | private static final String USER_ONE_LOGIN = "test-user-one"; | ||
29 | private static final String USER_ONE_EMAIL = "test-user-one@localhost"; | ||
30 | private static final String USER_TWO_LOGIN = "test-user-two"; | ||
31 | private static final String USER_TWO_EMAIL = "test-user-two@localhost"; | ||
32 | private static final String USER_THREE_LOGIN = "test-user-three"; | ||
33 | private static final String USER_THREE_EMAIL = "test-user-three@localhost"; | ||
34 | |||
35 | @Autowired | ||
36 | private UserRepository userRepository; | ||
37 | |||
38 | @Autowired | ||
39 | private UserDetailsService domainUserDetailsService; | ||
40 | |||
41 | private User userOne; | ||
42 | private User userTwo; | ||
43 | private User userThree; | ||
44 | |||
45 | @BeforeEach | ||
46 | public void init() { | ||
47 | userOne = new User(); | ||
48 | userOne.setLogin(USER_ONE_LOGIN); | ||
49 | userOne.setPassword(RandomStringUtils.random(60)); | ||
50 | userOne.setActivated(true); | ||
51 | userOne.setEmail(USER_ONE_EMAIL); | ||
52 | userOne.setFirstName("userOne"); | ||
53 | userOne.setLastName("doe"); | ||
54 | userOne.setLangKey("en"); | ||
55 | userRepository.save(userOne); | ||
56 | |||
57 | userTwo = new User(); | ||
58 | userTwo.setLogin(USER_TWO_LOGIN); | ||
59 | userTwo.setPassword(RandomStringUtils.random(60)); | ||
60 | userTwo.setActivated(true); | ||
61 | userTwo.setEmail(USER_TWO_EMAIL); | ||
62 | userTwo.setFirstName("userTwo"); | ||
63 | userTwo.setLastName("doe"); | ||
64 | userTwo.setLangKey("en"); | ||
65 | userRepository.save(userTwo); | ||
66 | |||
67 | userThree = new User(); | ||
68 | userThree.setLogin(USER_THREE_LOGIN); | ||
69 | userThree.setPassword(RandomStringUtils.random(60)); | ||
70 | userThree.setActivated(false); | ||
71 | userThree.setEmail(USER_THREE_EMAIL); | ||
72 | userThree.setFirstName("userThree"); | ||
73 | userThree.setLastName("doe"); | ||
74 | userThree.setLangKey("en"); | ||
75 | userRepository.save(userThree); | ||
76 | } | ||
77 | |||
78 | @Test | ||
79 | @Transactional | ||
80 | public void assertThatUserCanBeFoundByLogin() { | ||
81 | UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN); | ||
82 | assertThat(userDetails).isNotNull(); | ||
83 | assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | @Transactional | ||
88 | public void assertThatUserCanBeFoundByLoginIgnoreCase() { | ||
89 | UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN.toUpperCase(Locale.ENGLISH)); | ||
90 | assertThat(userDetails).isNotNull(); | ||
91 | assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); | ||
92 | } | ||
93 | |||
94 | @Test | ||
95 | @Transactional | ||
96 | public void assertThatUserCanBeFoundByEmail() { | ||
97 | UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL); | ||
98 | assertThat(userDetails).isNotNull(); | ||
99 | assertThat(userDetails.getUsername()).isEqualTo(USER_TWO_LOGIN); | ||
100 | } | ||
101 | |||
102 | @Test | ||
103 | @Transactional | ||
104 | public void assertThatUserCanBeFoundByEmailIgnoreCase() { | ||
105 | UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL.toUpperCase(Locale.ENGLISH)); | ||
106 | assertThat(userDetails).isNotNull(); | ||
107 | assertThat(userDetails.getUsername()).isEqualTo(USER_TWO_LOGIN); | ||
108 | } | ||
109 | |||
110 | @Test | ||
111 | @Transactional | ||
112 | public void assertThatEmailIsPrioritizedOverLogin() { | ||
113 | UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_EMAIL); | ||
114 | assertThat(userDetails).isNotNull(); | ||
115 | assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN); | ||
116 | } | ||
117 | |||
118 | @Test | ||
119 | @Transactional | ||
120 | public void assertThatUserNotActivatedExceptionIsThrownForNotActivatedUsers() { | ||
121 | assertThatExceptionOfType(UserNotActivatedException.class).isThrownBy( | ||
122 | () -> domainUserDetailsService.loadUserByUsername(USER_THREE_LOGIN)); | ||
123 | } | ||
124 | |||
125 | } |
File src/test/java/hu/dns/honlap/security/SecurityUtilsUnitTest.java added (mode: 100644) (index 0000000..9a4ec97) | |||
1 | package hu.dns.honlap.security; | ||
2 | |||
3 | import org.junit.jupiter.api.Test; | ||
4 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
5 | import org.springframework.security.core.GrantedAuthority; | ||
6 | import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
7 | import org.springframework.security.core.context.SecurityContext; | ||
8 | import org.springframework.security.core.context.SecurityContextHolder; | ||
9 | |||
10 | import java.util.ArrayList; | ||
11 | import java.util.Collection; | ||
12 | import java.util.Optional; | ||
13 | |||
14 | import static org.assertj.core.api.Assertions.assertThat; | ||
15 | |||
16 | /** | ||
17 | * Test class for the {@link SecurityUtils} utility class. | ||
18 | */ | ||
19 | public class SecurityUtilsUnitTest { | ||
20 | |||
21 | @Test | ||
22 | public void testGetCurrentUserLogin() { | ||
23 | SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); | ||
24 | securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin")); | ||
25 | SecurityContextHolder.setContext(securityContext); | ||
26 | Optional<String> login = SecurityUtils.getCurrentUserLogin(); | ||
27 | assertThat(login).contains("admin"); | ||
28 | } | ||
29 | |||
30 | @Test | ||
31 | public void testgetCurrentUserJWT() { | ||
32 | SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); | ||
33 | securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "token")); | ||
34 | SecurityContextHolder.setContext(securityContext); | ||
35 | Optional<String> jwt = SecurityUtils.getCurrentUserJWT(); | ||
36 | assertThat(jwt).contains("token"); | ||
37 | } | ||
38 | |||
39 | @Test | ||
40 | public void testIsAuthenticated() { | ||
41 | SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); | ||
42 | securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin")); | ||
43 | SecurityContextHolder.setContext(securityContext); | ||
44 | boolean isAuthenticated = SecurityUtils.isAuthenticated(); | ||
45 | assertThat(isAuthenticated).isTrue(); | ||
46 | } | ||
47 | |||
48 | @Test | ||
49 | public void testAnonymousIsNotAuthenticated() { | ||
50 | SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); | ||
51 | Collection<GrantedAuthority> authorities = new ArrayList<>(); | ||
52 | authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS)); | ||
53 | securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities)); | ||
54 | SecurityContextHolder.setContext(securityContext); | ||
55 | boolean isAuthenticated = SecurityUtils.isAuthenticated(); | ||
56 | assertThat(isAuthenticated).isFalse(); | ||
57 | } | ||
58 | |||
59 | @Test | ||
60 | public void testIsCurrentUserInRole() { | ||
61 | SecurityContext securityContext = SecurityContextHolder.createEmptyContext(); | ||
62 | Collection<GrantedAuthority> authorities = new ArrayList<>(); | ||
63 | authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.USER)); | ||
64 | securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("user", "user", authorities)); | ||
65 | SecurityContextHolder.setContext(securityContext); | ||
66 | |||
67 | assertThat(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.USER)).isTrue(); | ||
68 | assertThat(SecurityUtils.isCurrentUserInRole(AuthoritiesConstants.ADMIN)).isFalse(); | ||
69 | } | ||
70 | |||
71 | } |
File src/test/java/hu/dns/honlap/security/jwt/JWTFilterTest.java added (mode: 100644) (index 0000000..5782e0a) | |||
1 | package hu.dns.honlap.security.jwt; | ||
2 | |||
3 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
4 | import io.github.jhipster.config.JHipsterProperties; | ||
5 | import io.jsonwebtoken.io.Decoders; | ||
6 | import io.jsonwebtoken.security.Keys; | ||
7 | |||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import org.springframework.http.HttpStatus; | ||
11 | import org.springframework.mock.web.MockFilterChain; | ||
12 | import org.springframework.mock.web.MockHttpServletRequest; | ||
13 | import org.springframework.mock.web.MockHttpServletResponse; | ||
14 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
15 | import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
16 | import org.springframework.security.core.context.SecurityContextHolder; | ||
17 | import org.springframework.test.util.ReflectionTestUtils; | ||
18 | |||
19 | import java.util.Collections; | ||
20 | |||
21 | import static org.assertj.core.api.Assertions.assertThat; | ||
22 | |||
23 | public class JWTFilterTest { | ||
24 | |||
25 | private TokenProvider tokenProvider; | ||
26 | |||
27 | private JWTFilter jwtFilter; | ||
28 | |||
29 | @BeforeEach | ||
30 | public void setup() { | ||
31 | JHipsterProperties jHipsterProperties = new JHipsterProperties(); | ||
32 | tokenProvider = new TokenProvider(jHipsterProperties); | ||
33 | ReflectionTestUtils.setField(tokenProvider, "key", | ||
34 | Keys.hmacShaKeyFor(Decoders.BASE64 | ||
35 | .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8"))); | ||
36 | |||
37 | ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", 60000); | ||
38 | jwtFilter = new JWTFilter(tokenProvider); | ||
39 | SecurityContextHolder.getContext().setAuthentication(null); | ||
40 | } | ||
41 | |||
42 | @Test | ||
43 | public void testJWTFilter() throws Exception { | ||
44 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | ||
45 | "test-user", | ||
46 | "test-password", | ||
47 | Collections.singletonList(new SimpleGrantedAuthority(AuthoritiesConstants.USER)) | ||
48 | ); | ||
49 | String jwt = tokenProvider.createToken(authentication, false); | ||
50 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
51 | request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); | ||
52 | request.setRequestURI("/api/test"); | ||
53 | MockHttpServletResponse response = new MockHttpServletResponse(); | ||
54 | MockFilterChain filterChain = new MockFilterChain(); | ||
55 | jwtFilter.doFilter(request, response, filterChain); | ||
56 | assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); | ||
57 | assertThat(SecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("test-user"); | ||
58 | assertThat(SecurityContextHolder.getContext().getAuthentication().getCredentials().toString()).isEqualTo(jwt); | ||
59 | } | ||
60 | |||
61 | @Test | ||
62 | public void testJWTFilterInvalidToken() throws Exception { | ||
63 | String jwt = "wrong_jwt"; | ||
64 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
65 | request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer " + jwt); | ||
66 | request.setRequestURI("/api/test"); | ||
67 | MockHttpServletResponse response = new MockHttpServletResponse(); | ||
68 | MockFilterChain filterChain = new MockFilterChain(); | ||
69 | jwtFilter.doFilter(request, response, filterChain); | ||
70 | assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); | ||
71 | assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); | ||
72 | } | ||
73 | |||
74 | @Test | ||
75 | public void testJWTFilterMissingAuthorization() throws Exception { | ||
76 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
77 | request.setRequestURI("/api/test"); | ||
78 | MockHttpServletResponse response = new MockHttpServletResponse(); | ||
79 | MockFilterChain filterChain = new MockFilterChain(); | ||
80 | jwtFilter.doFilter(request, response, filterChain); | ||
81 | assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); | ||
82 | assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); | ||
83 | } | ||
84 | |||
85 | @Test | ||
86 | public void testJWTFilterMissingToken() throws Exception { | ||
87 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
88 | request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Bearer "); | ||
89 | request.setRequestURI("/api/test"); | ||
90 | MockHttpServletResponse response = new MockHttpServletResponse(); | ||
91 | MockFilterChain filterChain = new MockFilterChain(); | ||
92 | jwtFilter.doFilter(request, response, filterChain); | ||
93 | assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); | ||
94 | assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); | ||
95 | } | ||
96 | |||
97 | @Test | ||
98 | public void testJWTFilterWrongScheme() throws Exception { | ||
99 | UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken( | ||
100 | "test-user", | ||
101 | "test-password", | ||
102 | Collections.singletonList(new SimpleGrantedAuthority(AuthoritiesConstants.USER)) | ||
103 | ); | ||
104 | String jwt = tokenProvider.createToken(authentication, false); | ||
105 | MockHttpServletRequest request = new MockHttpServletRequest(); | ||
106 | request.addHeader(JWTFilter.AUTHORIZATION_HEADER, "Basic " + jwt); | ||
107 | request.setRequestURI("/api/test"); | ||
108 | MockHttpServletResponse response = new MockHttpServletResponse(); | ||
109 | MockFilterChain filterChain = new MockFilterChain(); | ||
110 | jwtFilter.doFilter(request, response, filterChain); | ||
111 | assertThat(response.getStatus()).isEqualTo(HttpStatus.OK.value()); | ||
112 | assertThat(SecurityContextHolder.getContext().getAuthentication()).isNull(); | ||
113 | } | ||
114 | |||
115 | } |
File src/test/java/hu/dns/honlap/security/jwt/TokenProviderTest.java added (mode: 100644) (index 0000000..93157ac) | |||
1 | package hu.dns.honlap.security.jwt; | ||
2 | |||
3 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
4 | |||
5 | import java.security.Key; | ||
6 | import java.util.*; | ||
7 | |||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; | ||
11 | import org.springframework.security.core.Authentication; | ||
12 | import org.springframework.security.core.GrantedAuthority; | ||
13 | import org.springframework.security.core.authority.SimpleGrantedAuthority; | ||
14 | import org.springframework.test.util.ReflectionTestUtils; | ||
15 | |||
16 | import io.github.jhipster.config.JHipsterProperties; | ||
17 | import io.jsonwebtoken.Jwts; | ||
18 | import io.jsonwebtoken.SignatureAlgorithm; | ||
19 | import io.jsonwebtoken.io.Decoders; | ||
20 | import io.jsonwebtoken.security.Keys; | ||
21 | |||
22 | import static org.assertj.core.api.Assertions.assertThat; | ||
23 | |||
24 | public class TokenProviderTest { | ||
25 | |||
26 | private static final long ONE_MINUTE = 60000; | ||
27 | |||
28 | private Key key; | ||
29 | private TokenProvider tokenProvider; | ||
30 | |||
31 | @BeforeEach | ||
32 | public void setup() { | ||
33 | tokenProvider = new TokenProvider( new JHipsterProperties()); | ||
34 | key = Keys.hmacShaKeyFor(Decoders.BASE64 | ||
35 | .decode("fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")); | ||
36 | |||
37 | ReflectionTestUtils.setField(tokenProvider, "key", key); | ||
38 | ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE); | ||
39 | } | ||
40 | |||
41 | @Test | ||
42 | public void testReturnFalseWhenJWThasInvalidSignature() { | ||
43 | boolean isTokenValid = tokenProvider.validateToken(createTokenWithDifferentSignature()); | ||
44 | |||
45 | assertThat(isTokenValid).isEqualTo(false); | ||
46 | } | ||
47 | |||
48 | @Test | ||
49 | public void testReturnFalseWhenJWTisMalformed() { | ||
50 | Authentication authentication = createAuthentication(); | ||
51 | String token = tokenProvider.createToken(authentication, false); | ||
52 | String invalidToken = token.substring(1); | ||
53 | boolean isTokenValid = tokenProvider.validateToken(invalidToken); | ||
54 | |||
55 | assertThat(isTokenValid).isEqualTo(false); | ||
56 | } | ||
57 | |||
58 | @Test | ||
59 | public void testReturnFalseWhenJWTisExpired() { | ||
60 | ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", -ONE_MINUTE); | ||
61 | |||
62 | Authentication authentication = createAuthentication(); | ||
63 | String token = tokenProvider.createToken(authentication, false); | ||
64 | |||
65 | boolean isTokenValid = tokenProvider.validateToken(token); | ||
66 | |||
67 | assertThat(isTokenValid).isEqualTo(false); | ||
68 | } | ||
69 | |||
70 | @Test | ||
71 | public void testReturnFalseWhenJWTisUnsupported() { | ||
72 | String unsupportedToken = createUnsupportedToken(); | ||
73 | |||
74 | boolean isTokenValid = tokenProvider.validateToken(unsupportedToken); | ||
75 | |||
76 | assertThat(isTokenValid).isEqualTo(false); | ||
77 | } | ||
78 | |||
79 | @Test | ||
80 | public void testReturnFalseWhenJWTisInvalid() { | ||
81 | boolean isTokenValid = tokenProvider.validateToken(""); | ||
82 | |||
83 | assertThat(isTokenValid).isEqualTo(false); | ||
84 | } | ||
85 | |||
86 | private Authentication createAuthentication() { | ||
87 | Collection<GrantedAuthority> authorities = new ArrayList<>(); | ||
88 | authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS)); | ||
89 | return new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities); | ||
90 | } | ||
91 | |||
92 | private String createUnsupportedToken() { | ||
93 | return Jwts.builder() | ||
94 | .setPayload("payload") | ||
95 | .signWith(key, SignatureAlgorithm.HS512) | ||
96 | .compact(); | ||
97 | } | ||
98 | |||
99 | private String createTokenWithDifferentSignature() { | ||
100 | Key otherKey = Keys.hmacShaKeyFor(Decoders.BASE64 | ||
101 | .decode("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")); | ||
102 | |||
103 | return Jwts.builder() | ||
104 | .setSubject("anonymous") | ||
105 | .signWith(otherKey, SignatureAlgorithm.HS512) | ||
106 | .setExpiration(new Date(new Date().getTime() + ONE_MINUTE)) | ||
107 | .compact(); | ||
108 | } | ||
109 | } |
File src/test/java/hu/dns/honlap/service/AuditEventServiceIT.java added (mode: 100644) (index 0000000..6ec7776) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import hu.dns.honlap.domain.PersistentAuditEvent; | ||
4 | import hu.dns.honlap.repository.PersistenceAuditEventRepository; | ||
5 | import hu.dns.honlap.HonlapApp; | ||
6 | import io.github.jhipster.config.JHipsterProperties; | ||
7 | import org.junit.jupiter.api.BeforeEach; | ||
8 | import org.junit.jupiter.api.Test; | ||
9 | import org.springframework.beans.factory.annotation.Autowired; | ||
10 | import org.springframework.boot.test.context.SpringBootTest; | ||
11 | import org.springframework.transaction.annotation.Transactional; | ||
12 | import java.time.Instant; | ||
13 | import java.time.temporal.ChronoUnit; | ||
14 | |||
15 | import static org.assertj.core.api.Assertions.assertThat; | ||
16 | |||
17 | /** | ||
18 | * Integration tests for {@link AuditEventService}. | ||
19 | */ | ||
20 | @SpringBootTest(classes = HonlapApp.class) | ||
21 | @Transactional | ||
22 | public class AuditEventServiceIT { | ||
23 | @Autowired | ||
24 | private AuditEventService auditEventService; | ||
25 | |||
26 | @Autowired | ||
27 | private PersistenceAuditEventRepository persistenceAuditEventRepository; | ||
28 | |||
29 | @Autowired | ||
30 | private JHipsterProperties jHipsterProperties; | ||
31 | |||
32 | private PersistentAuditEvent auditEventOld; | ||
33 | |||
34 | private PersistentAuditEvent auditEventWithinRetention; | ||
35 | |||
36 | private PersistentAuditEvent auditEventNew; | ||
37 | |||
38 | @BeforeEach | ||
39 | public void init() { | ||
40 | auditEventOld = new PersistentAuditEvent(); | ||
41 | auditEventOld.setAuditEventDate(Instant.now().minus(jHipsterProperties.getAuditEvents().getRetentionPeriod() + 1, ChronoUnit.DAYS)); | ||
42 | auditEventOld.setPrincipal("test-user-old"); | ||
43 | auditEventOld.setAuditEventType("test-type"); | ||
44 | |||
45 | auditEventWithinRetention = new PersistentAuditEvent(); | ||
46 | auditEventWithinRetention.setAuditEventDate(Instant.now().minus(jHipsterProperties.getAuditEvents().getRetentionPeriod() - 1, ChronoUnit.DAYS)); | ||
47 | auditEventWithinRetention.setPrincipal("test-user-retention"); | ||
48 | auditEventWithinRetention.setAuditEventType("test-type"); | ||
49 | |||
50 | auditEventNew = new PersistentAuditEvent(); | ||
51 | auditEventNew.setAuditEventDate(Instant.now()); | ||
52 | auditEventNew.setPrincipal("test-user-new"); | ||
53 | auditEventNew.setAuditEventType("test-type"); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | @Transactional | ||
58 | public void verifyOldAuditEventsAreDeleted() { | ||
59 | persistenceAuditEventRepository.deleteAll(); | ||
60 | persistenceAuditEventRepository.save(auditEventOld); | ||
61 | persistenceAuditEventRepository.save(auditEventWithinRetention); | ||
62 | persistenceAuditEventRepository.save(auditEventNew); | ||
63 | |||
64 | persistenceAuditEventRepository.flush(); | ||
65 | auditEventService.removeOldAuditEvents(); | ||
66 | persistenceAuditEventRepository.flush(); | ||
67 | |||
68 | assertThat(persistenceAuditEventRepository.findAll().size()).isEqualTo(2); | ||
69 | assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-old")).isEmpty(); | ||
70 | assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-retention")).isNotEmpty(); | ||
71 | assertThat(persistenceAuditEventRepository.findByPrincipal("test-user-new")).isNotEmpty(); | ||
72 | } | ||
73 | } |
File src/test/java/hu/dns/honlap/service/MailServiceIT.java added (mode: 100644) (index 0000000..1c35ab9) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import hu.dns.honlap.config.Constants; | ||
4 | |||
5 | import hu.dns.honlap.HonlapApp; | ||
6 | import hu.dns.honlap.domain.User; | ||
7 | import io.github.jhipster.config.JHipsterProperties; | ||
8 | import org.junit.jupiter.api.BeforeEach; | ||
9 | import org.junit.jupiter.api.Test; | ||
10 | import org.mockito.ArgumentCaptor; | ||
11 | import org.mockito.Captor; | ||
12 | import org.mockito.MockitoAnnotations; | ||
13 | import org.mockito.Spy; | ||
14 | import org.springframework.beans.factory.annotation.Autowired; | ||
15 | import org.springframework.boot.test.context.SpringBootTest; | ||
16 | import org.springframework.context.MessageSource; | ||
17 | import org.springframework.mail.MailSendException; | ||
18 | import org.springframework.mail.javamail.JavaMailSenderImpl; | ||
19 | import org.thymeleaf.spring5.SpringTemplateEngine; | ||
20 | |||
21 | import javax.mail.Multipart; | ||
22 | import javax.mail.internet.MimeBodyPart; | ||
23 | import javax.mail.internet.MimeMessage; | ||
24 | import javax.mail.internet.MimeMultipart; | ||
25 | import java.io.ByteArrayOutputStream; | ||
26 | import java.io.File; | ||
27 | import java.io.FileInputStream; | ||
28 | import java.io.InputStreamReader; | ||
29 | import java.net.URI; | ||
30 | import java.net.URL; | ||
31 | import java.nio.charset.Charset; | ||
32 | import java.util.Properties; | ||
33 | import java.util.regex.Matcher; | ||
34 | import java.util.regex.Pattern; | ||
35 | |||
36 | import static org.assertj.core.api.Assertions.*; | ||
37 | import static org.mockito.ArgumentMatchers.any; | ||
38 | import static org.mockito.Mockito.*; | ||
39 | |||
40 | /** | ||
41 | * Integration tests for {@link MailService}. | ||
42 | */ | ||
43 | @SpringBootTest(classes = HonlapApp.class) | ||
44 | public class MailServiceIT { | ||
45 | |||
46 | private static final String[] languages = { | ||
47 | "hu", | ||
48 | "en" | ||
49 | // jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array | ||
50 | }; | ||
51 | private static final Pattern PATTERN_LOCALE_3 = Pattern.compile("([a-z]{2})-([a-zA-Z]{4})-([a-z]{2})"); | ||
52 | private static final Pattern PATTERN_LOCALE_2 = Pattern.compile("([a-z]{2})-([a-z]{2})"); | ||
53 | |||
54 | @Autowired | ||
55 | private JHipsterProperties jHipsterProperties; | ||
56 | |||
57 | @Autowired | ||
58 | private MessageSource messageSource; | ||
59 | |||
60 | @Autowired | ||
61 | private SpringTemplateEngine templateEngine; | ||
62 | |||
63 | @Spy | ||
64 | private JavaMailSenderImpl javaMailSender; | ||
65 | |||
66 | @Captor | ||
67 | private ArgumentCaptor<MimeMessage> messageCaptor; | ||
68 | |||
69 | private MailService mailService; | ||
70 | |||
71 | @BeforeEach | ||
72 | public void setup() { | ||
73 | MockitoAnnotations.initMocks(this); | ||
74 | doNothing().when(javaMailSender).send(any(MimeMessage.class)); | ||
75 | mailService = new MailService(jHipsterProperties, javaMailSender, messageSource, templateEngine); | ||
76 | } | ||
77 | |||
78 | @Test | ||
79 | public void testSendEmail() throws Exception { | ||
80 | mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false); | ||
81 | verify(javaMailSender).send(messageCaptor.capture()); | ||
82 | MimeMessage message = messageCaptor.getValue(); | ||
83 | assertThat(message.getSubject()).isEqualTo("testSubject"); | ||
84 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); | ||
85 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
86 | assertThat(message.getContent()).isInstanceOf(String.class); | ||
87 | assertThat(message.getContent().toString()).isEqualTo("testContent"); | ||
88 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8"); | ||
89 | } | ||
90 | |||
91 | @Test | ||
92 | public void testSendHtmlEmail() throws Exception { | ||
93 | mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, true); | ||
94 | verify(javaMailSender).send(messageCaptor.capture()); | ||
95 | MimeMessage message = messageCaptor.getValue(); | ||
96 | assertThat(message.getSubject()).isEqualTo("testSubject"); | ||
97 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); | ||
98 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
99 | assertThat(message.getContent()).isInstanceOf(String.class); | ||
100 | assertThat(message.getContent().toString()).isEqualTo("testContent"); | ||
101 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
102 | } | ||
103 | |||
104 | @Test | ||
105 | public void testSendMultipartEmail() throws Exception { | ||
106 | mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, false); | ||
107 | verify(javaMailSender).send(messageCaptor.capture()); | ||
108 | MimeMessage message = messageCaptor.getValue(); | ||
109 | MimeMultipart mp = (MimeMultipart) message.getContent(); | ||
110 | MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0); | ||
111 | ByteArrayOutputStream aos = new ByteArrayOutputStream(); | ||
112 | part.writeTo(aos); | ||
113 | assertThat(message.getSubject()).isEqualTo("testSubject"); | ||
114 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); | ||
115 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
116 | assertThat(message.getContent()).isInstanceOf(Multipart.class); | ||
117 | assertThat(aos.toString()).isEqualTo("\r\ntestContent"); | ||
118 | assertThat(part.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8"); | ||
119 | } | ||
120 | |||
121 | @Test | ||
122 | public void testSendMultipartHtmlEmail() throws Exception { | ||
123 | mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, true); | ||
124 | verify(javaMailSender).send(messageCaptor.capture()); | ||
125 | MimeMessage message = messageCaptor.getValue(); | ||
126 | MimeMultipart mp = (MimeMultipart) message.getContent(); | ||
127 | MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0); | ||
128 | ByteArrayOutputStream aos = new ByteArrayOutputStream(); | ||
129 | part.writeTo(aos); | ||
130 | assertThat(message.getSubject()).isEqualTo("testSubject"); | ||
131 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo("john.doe@example.com"); | ||
132 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
133 | assertThat(message.getContent()).isInstanceOf(Multipart.class); | ||
134 | assertThat(aos.toString()).isEqualTo("\r\ntestContent"); | ||
135 | assertThat(part.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
136 | } | ||
137 | |||
138 | @Test | ||
139 | public void testSendEmailFromTemplate() throws Exception { | ||
140 | User user = new User(); | ||
141 | user.setLogin("john"); | ||
142 | user.setEmail("john.doe@example.com"); | ||
143 | user.setLangKey("en"); | ||
144 | mailService.sendEmailFromTemplate(user, "mail/testEmail", "email.test.title"); | ||
145 | verify(javaMailSender).send(messageCaptor.capture()); | ||
146 | MimeMessage message = messageCaptor.getValue(); | ||
147 | assertThat(message.getSubject()).isEqualTo("test title"); | ||
148 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); | ||
149 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
150 | assertThat(message.getContent().toString()).isEqualToNormalizingNewlines("<html>test title, http://127.0.0.1:8080, john</html>\n"); | ||
151 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
152 | } | ||
153 | |||
154 | @Test | ||
155 | public void testSendActivationEmail() throws Exception { | ||
156 | User user = new User(); | ||
157 | user.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
158 | user.setLogin("john"); | ||
159 | user.setEmail("john.doe@example.com"); | ||
160 | mailService.sendActivationEmail(user); | ||
161 | verify(javaMailSender).send(messageCaptor.capture()); | ||
162 | MimeMessage message = messageCaptor.getValue(); | ||
163 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); | ||
164 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
165 | assertThat(message.getContent().toString()).isNotEmpty(); | ||
166 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
167 | } | ||
168 | |||
169 | @Test | ||
170 | public void testCreationEmail() throws Exception { | ||
171 | User user = new User(); | ||
172 | user.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
173 | user.setLogin("john"); | ||
174 | user.setEmail("john.doe@example.com"); | ||
175 | mailService.sendCreationEmail(user); | ||
176 | verify(javaMailSender).send(messageCaptor.capture()); | ||
177 | MimeMessage message = messageCaptor.getValue(); | ||
178 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); | ||
179 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
180 | assertThat(message.getContent().toString()).isNotEmpty(); | ||
181 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
182 | } | ||
183 | |||
184 | @Test | ||
185 | public void testSendPasswordResetMail() throws Exception { | ||
186 | User user = new User(); | ||
187 | user.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
188 | user.setLogin("john"); | ||
189 | user.setEmail("john.doe@example.com"); | ||
190 | mailService.sendPasswordResetMail(user); | ||
191 | verify(javaMailSender).send(messageCaptor.capture()); | ||
192 | MimeMessage message = messageCaptor.getValue(); | ||
193 | assertThat(message.getAllRecipients()[0].toString()).isEqualTo(user.getEmail()); | ||
194 | assertThat(message.getFrom()[0].toString()).isEqualTo(jHipsterProperties.getMail().getFrom()); | ||
195 | assertThat(message.getContent().toString()).isNotEmpty(); | ||
196 | assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8"); | ||
197 | } | ||
198 | |||
199 | @Test | ||
200 | public void testSendEmailWithException() { | ||
201 | doThrow(MailSendException.class).when(javaMailSender).send(any(MimeMessage.class)); | ||
202 | try { | ||
203 | mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false); | ||
204 | } catch (Exception e) { | ||
205 | fail("Exception shouldn't have been thrown"); | ||
206 | } | ||
207 | } | ||
208 | |||
209 | @Test | ||
210 | public void testSendLocalizedEmailForAllSupportedLanguages() throws Exception { | ||
211 | User user = new User(); | ||
212 | user.setLogin("john"); | ||
213 | user.setEmail("john.doe@example.com"); | ||
214 | for (String langKey : languages) { | ||
215 | user.setLangKey(langKey); | ||
216 | mailService.sendEmailFromTemplate(user, "mail/testEmail", "email.test.title"); | ||
217 | verify(javaMailSender, atLeastOnce()).send(messageCaptor.capture()); | ||
218 | MimeMessage message = messageCaptor.getValue(); | ||
219 | |||
220 | String propertyFilePath = "i18n/messages_" + getJavaLocale(langKey) + ".properties"; | ||
221 | URL resource = this.getClass().getClassLoader().getResource(propertyFilePath); | ||
222 | File file = new File(new URI(resource.getFile()).getPath()); | ||
223 | Properties properties = new Properties(); | ||
224 | properties.load(new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-8"))); | ||
225 | |||
226 | String emailTitle = (String) properties.get("email.test.title"); | ||
227 | assertThat(message.getSubject()).isEqualTo(emailTitle); | ||
228 | assertThat(message.getContent().toString()).isEqualToNormalizingNewlines("<html>" + emailTitle + ", http://127.0.0.1:8080, john</html>\n"); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * Convert a lang key to the Java locale. | ||
234 | */ | ||
235 | private String getJavaLocale(String langKey) { | ||
236 | String javaLangKey = langKey; | ||
237 | Matcher matcher2 = PATTERN_LOCALE_2.matcher(langKey); | ||
238 | if (matcher2.matches()) { | ||
239 | javaLangKey = matcher2.group(1) + "_"+ matcher2.group(2).toUpperCase(); | ||
240 | } | ||
241 | Matcher matcher3 = PATTERN_LOCALE_3.matcher(langKey); | ||
242 | if (matcher3.matches()) { | ||
243 | javaLangKey = matcher3.group(1) + "_" + matcher3.group(2) + "_" + matcher3.group(3).toUpperCase(); | ||
244 | } | ||
245 | return javaLangKey; | ||
246 | } | ||
247 | } |
File src/test/java/hu/dns/honlap/service/UserServiceIT.java added (mode: 100644) (index 0000000..1af0638) | |||
1 | package hu.dns.honlap.service; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.config.Constants; | ||
5 | import hu.dns.honlap.domain.User; | ||
6 | import hu.dns.honlap.repository.UserRepository; | ||
7 | import hu.dns.honlap.service.dto.UserDTO; | ||
8 | |||
9 | import io.github.jhipster.security.RandomUtil; | ||
10 | |||
11 | import org.apache.commons.lang3.RandomStringUtils; | ||
12 | import org.junit.jupiter.api.BeforeEach; | ||
13 | import org.junit.jupiter.api.Test; | ||
14 | import org.mockito.Mock; | ||
15 | import org.springframework.beans.factory.annotation.Autowired; | ||
16 | import org.springframework.boot.test.context.SpringBootTest; | ||
17 | import org.springframework.data.auditing.AuditingHandler; | ||
18 | import org.springframework.data.auditing.DateTimeProvider; | ||
19 | import org.springframework.data.domain.Page; | ||
20 | import org.springframework.data.domain.PageRequest; | ||
21 | import org.springframework.transaction.annotation.Transactional; | ||
22 | import java.time.Instant; | ||
23 | import java.time.temporal.ChronoUnit; | ||
24 | import java.time.LocalDateTime; | ||
25 | import java.util.Optional; | ||
26 | import java.util.List; | ||
27 | |||
28 | import static org.assertj.core.api.Assertions.assertThat; | ||
29 | import static org.mockito.Mockito.when; | ||
30 | |||
31 | /** | ||
32 | * Integration tests for {@link UserService}. | ||
33 | */ | ||
34 | @SpringBootTest(classes = HonlapApp.class) | ||
35 | @Transactional | ||
36 | public class UserServiceIT { | ||
37 | |||
38 | private static final String DEFAULT_LOGIN = "johndoe"; | ||
39 | |||
40 | private static final String DEFAULT_EMAIL = "johndoe@localhost"; | ||
41 | |||
42 | private static final String DEFAULT_FIRSTNAME = "john"; | ||
43 | |||
44 | private static final String DEFAULT_LASTNAME = "doe"; | ||
45 | |||
46 | private static final String DEFAULT_IMAGEURL = "http://placehold.it/50x50"; | ||
47 | |||
48 | private static final String DEFAULT_LANGKEY = "dummy"; | ||
49 | |||
50 | @Autowired | ||
51 | private UserRepository userRepository; | ||
52 | |||
53 | @Autowired | ||
54 | private UserService userService; | ||
55 | |||
56 | @Autowired | ||
57 | private AuditingHandler auditingHandler; | ||
58 | |||
59 | @Mock | ||
60 | private DateTimeProvider dateTimeProvider; | ||
61 | |||
62 | private User user; | ||
63 | |||
64 | @BeforeEach | ||
65 | public void init() { | ||
66 | user = new User(); | ||
67 | user.setLogin(DEFAULT_LOGIN); | ||
68 | user.setPassword(RandomStringUtils.random(60)); | ||
69 | user.setActivated(true); | ||
70 | user.setEmail(DEFAULT_EMAIL); | ||
71 | user.setFirstName(DEFAULT_FIRSTNAME); | ||
72 | user.setLastName(DEFAULT_LASTNAME); | ||
73 | user.setImageUrl(DEFAULT_IMAGEURL); | ||
74 | user.setLangKey(DEFAULT_LANGKEY); | ||
75 | |||
76 | when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.now())); | ||
77 | auditingHandler.setDateTimeProvider(dateTimeProvider); | ||
78 | } | ||
79 | |||
80 | @Test | ||
81 | @Transactional | ||
82 | public void assertThatUserMustExistToResetPassword() { | ||
83 | userRepository.saveAndFlush(user); | ||
84 | Optional<User> maybeUser = userService.requestPasswordReset("invalid.login@localhost"); | ||
85 | assertThat(maybeUser).isNotPresent(); | ||
86 | |||
87 | maybeUser = userService.requestPasswordReset(user.getEmail()); | ||
88 | assertThat(maybeUser).isPresent(); | ||
89 | assertThat(maybeUser.orElse(null).getEmail()).isEqualTo(user.getEmail()); | ||
90 | assertThat(maybeUser.orElse(null).getResetDate()).isNotNull(); | ||
91 | assertThat(maybeUser.orElse(null).getResetKey()).isNotNull(); | ||
92 | } | ||
93 | |||
94 | @Test | ||
95 | @Transactional | ||
96 | public void assertThatOnlyActivatedUserCanRequestPasswordReset() { | ||
97 | user.setActivated(false); | ||
98 | userRepository.saveAndFlush(user); | ||
99 | |||
100 | Optional<User> maybeUser = userService.requestPasswordReset(user.getLogin()); | ||
101 | assertThat(maybeUser).isNotPresent(); | ||
102 | userRepository.delete(user); | ||
103 | } | ||
104 | |||
105 | @Test | ||
106 | @Transactional | ||
107 | public void assertThatResetKeyMustNotBeOlderThan24Hours() { | ||
108 | Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS); | ||
109 | String resetKey = RandomUtil.generateResetKey(); | ||
110 | user.setActivated(true); | ||
111 | user.setResetDate(daysAgo); | ||
112 | user.setResetKey(resetKey); | ||
113 | userRepository.saveAndFlush(user); | ||
114 | |||
115 | Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); | ||
116 | assertThat(maybeUser).isNotPresent(); | ||
117 | userRepository.delete(user); | ||
118 | } | ||
119 | |||
120 | @Test | ||
121 | @Transactional | ||
122 | public void assertThatResetKeyMustBeValid() { | ||
123 | Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS); | ||
124 | user.setActivated(true); | ||
125 | user.setResetDate(daysAgo); | ||
126 | user.setResetKey("1234"); | ||
127 | userRepository.saveAndFlush(user); | ||
128 | |||
129 | Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); | ||
130 | assertThat(maybeUser).isNotPresent(); | ||
131 | userRepository.delete(user); | ||
132 | } | ||
133 | |||
134 | @Test | ||
135 | @Transactional | ||
136 | public void assertThatUserCanResetPassword() { | ||
137 | String oldPassword = user.getPassword(); | ||
138 | Instant daysAgo = Instant.now().minus(2, ChronoUnit.HOURS); | ||
139 | String resetKey = RandomUtil.generateResetKey(); | ||
140 | user.setActivated(true); | ||
141 | user.setResetDate(daysAgo); | ||
142 | user.setResetKey(resetKey); | ||
143 | userRepository.saveAndFlush(user); | ||
144 | |||
145 | Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey()); | ||
146 | assertThat(maybeUser).isPresent(); | ||
147 | assertThat(maybeUser.orElse(null).getResetDate()).isNull(); | ||
148 | assertThat(maybeUser.orElse(null).getResetKey()).isNull(); | ||
149 | assertThat(maybeUser.orElse(null).getPassword()).isNotEqualTo(oldPassword); | ||
150 | |||
151 | userRepository.delete(user); | ||
152 | } | ||
153 | |||
154 | @Test | ||
155 | @Transactional | ||
156 | public void assertThatNotActivatedUsersWithNotNullActivationKeyCreatedBefore3DaysAreDeleted() { | ||
157 | Instant now = Instant.now(); | ||
158 | when(dateTimeProvider.getNow()).thenReturn(Optional.of(now.minus(4, ChronoUnit.DAYS))); | ||
159 | user.setActivated(false); | ||
160 | user.setActivationKey(RandomStringUtils.random(20)); | ||
161 | User dbUser = userRepository.saveAndFlush(user); | ||
162 | dbUser.setCreatedDate(now.minus(4, ChronoUnit.DAYS)); | ||
163 | userRepository.saveAndFlush(user); | ||
164 | List<User> users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(now.minus(3, ChronoUnit.DAYS)); | ||
165 | assertThat(users).isNotEmpty(); | ||
166 | userService.removeNotActivatedUsers(); | ||
167 | users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(now.minus(3, ChronoUnit.DAYS)); | ||
168 | assertThat(users).isEmpty(); | ||
169 | } | ||
170 | |||
171 | @Test | ||
172 | @Transactional | ||
173 | public void assertThatNotActivatedUsersWithNullActivationKeyCreatedBefore3DaysAreNotDeleted() { | ||
174 | Instant now = Instant.now(); | ||
175 | when(dateTimeProvider.getNow()).thenReturn(Optional.of(now.minus(4, ChronoUnit.DAYS))); | ||
176 | user.setActivated(false); | ||
177 | User dbUser = userRepository.saveAndFlush(user); | ||
178 | dbUser.setCreatedDate(now.minus(4, ChronoUnit.DAYS)); | ||
179 | userRepository.saveAndFlush(user); | ||
180 | List<User> users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(now.minus(3, ChronoUnit.DAYS)); | ||
181 | assertThat(users).isEmpty(); | ||
182 | userService.removeNotActivatedUsers(); | ||
183 | Optional<User> maybeDbUser = userRepository.findById(dbUser.getId()); | ||
184 | assertThat(maybeDbUser).contains(dbUser); | ||
185 | } | ||
186 | |||
187 | @Test | ||
188 | @Transactional | ||
189 | public void assertThatAnonymousUserIsNotGet() { | ||
190 | user.setLogin(Constants.ANONYMOUS_USER); | ||
191 | if (!userRepository.findOneByLogin(Constants.ANONYMOUS_USER).isPresent()) { | ||
192 | userRepository.saveAndFlush(user); | ||
193 | } | ||
194 | final PageRequest pageable = PageRequest.of(0, (int) userRepository.count()); | ||
195 | final Page<UserDTO> allManagedUsers = userService.getAllManagedUsers(pageable); | ||
196 | assertThat(allManagedUsers.getContent().stream() | ||
197 | .noneMatch(user -> Constants.ANONYMOUS_USER.equals(user.getLogin()))) | ||
198 | .isTrue(); | ||
199 | } | ||
200 | |||
201 | } |
File src/test/java/hu/dns/honlap/service/mapper/UserMapperTest.java added (mode: 100644) (index 0000000..8b4fdd9) | |||
1 | package hu.dns.honlap.service.mapper; | ||
2 | |||
3 | import hu.dns.honlap.domain.User; | ||
4 | import hu.dns.honlap.service.dto.UserDTO; | ||
5 | import org.apache.commons.lang3.RandomStringUtils; | ||
6 | import org.junit.jupiter.api.BeforeEach; | ||
7 | import org.junit.jupiter.api.Test; | ||
8 | |||
9 | import java.util.ArrayList; | ||
10 | import java.util.HashSet; | ||
11 | import java.util.List; | ||
12 | import java.util.Set; | ||
13 | |||
14 | import static org.assertj.core.api.Assertions.assertThat; | ||
15 | |||
16 | /** | ||
17 | * Unit tests for {@link UserMapper}. | ||
18 | */ | ||
19 | public class UserMapperTest { | ||
20 | |||
21 | private static final String DEFAULT_LOGIN = "johndoe"; | ||
22 | private static final Long DEFAULT_ID = 1L; | ||
23 | |||
24 | private UserMapper userMapper; | ||
25 | private User user; | ||
26 | private UserDTO userDto; | ||
27 | |||
28 | @BeforeEach | ||
29 | public void init() { | ||
30 | userMapper = new UserMapper(); | ||
31 | user = new User(); | ||
32 | user.setLogin(DEFAULT_LOGIN); | ||
33 | user.setPassword(RandomStringUtils.random(60)); | ||
34 | user.setActivated(true); | ||
35 | user.setEmail("johndoe@localhost"); | ||
36 | user.setFirstName("john"); | ||
37 | user.setLastName("doe"); | ||
38 | user.setImageUrl("image_url"); | ||
39 | user.setLangKey("en"); | ||
40 | |||
41 | userDto = new UserDTO(user); | ||
42 | } | ||
43 | |||
44 | @Test | ||
45 | public void usersToUserDTOsShouldMapOnlyNonNullUsers() { | ||
46 | List<User> users = new ArrayList<>(); | ||
47 | users.add(user); | ||
48 | users.add(null); | ||
49 | |||
50 | List<UserDTO> userDTOS = userMapper.usersToUserDTOs(users); | ||
51 | |||
52 | assertThat(userDTOS).isNotEmpty(); | ||
53 | assertThat(userDTOS).size().isEqualTo(1); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | public void userDTOsToUsersShouldMapOnlyNonNullUsers() { | ||
58 | List<UserDTO> usersDto = new ArrayList<>(); | ||
59 | usersDto.add(userDto); | ||
60 | usersDto.add(null); | ||
61 | |||
62 | List<User> users = userMapper.userDTOsToUsers(usersDto); | ||
63 | |||
64 | assertThat(users).isNotEmpty(); | ||
65 | assertThat(users).size().isEqualTo(1); | ||
66 | } | ||
67 | |||
68 | @Test | ||
69 | public void userDTOsToUsersWithAuthoritiesStringShouldMapToUsersWithAuthoritiesDomain() { | ||
70 | Set<String> authoritiesAsString = new HashSet<>(); | ||
71 | authoritiesAsString.add("ADMIN"); | ||
72 | userDto.setAuthorities(authoritiesAsString); | ||
73 | |||
74 | List<UserDTO> usersDto = new ArrayList<>(); | ||
75 | usersDto.add(userDto); | ||
76 | |||
77 | List<User> users = userMapper.userDTOsToUsers(usersDto); | ||
78 | |||
79 | assertThat(users).isNotEmpty(); | ||
80 | assertThat(users).size().isEqualTo(1); | ||
81 | assertThat(users.get(0).getAuthorities()).isNotNull(); | ||
82 | assertThat(users.get(0).getAuthorities()).isNotEmpty(); | ||
83 | assertThat(users.get(0).getAuthorities().iterator().next().getName()).isEqualTo("ADMIN"); | ||
84 | } | ||
85 | |||
86 | @Test | ||
87 | public void userDTOsToUsersMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() { | ||
88 | userDto.setAuthorities(null); | ||
89 | |||
90 | List<UserDTO> usersDto = new ArrayList<>(); | ||
91 | usersDto.add(userDto); | ||
92 | |||
93 | List<User> users = userMapper.userDTOsToUsers(usersDto); | ||
94 | |||
95 | assertThat(users).isNotEmpty(); | ||
96 | assertThat(users).size().isEqualTo(1); | ||
97 | assertThat(users.get(0).getAuthorities()).isNotNull(); | ||
98 | assertThat(users.get(0).getAuthorities()).isEmpty(); | ||
99 | } | ||
100 | |||
101 | @Test | ||
102 | public void userDTOToUserMapWithAuthoritiesStringShouldReturnUserWithAuthorities() { | ||
103 | Set<String> authoritiesAsString = new HashSet<>(); | ||
104 | authoritiesAsString.add("ADMIN"); | ||
105 | userDto.setAuthorities(authoritiesAsString); | ||
106 | |||
107 | User user = userMapper.userDTOToUser(userDto); | ||
108 | |||
109 | assertThat(user).isNotNull(); | ||
110 | assertThat(user.getAuthorities()).isNotNull(); | ||
111 | assertThat(user.getAuthorities()).isNotEmpty(); | ||
112 | assertThat(user.getAuthorities().iterator().next().getName()).isEqualTo("ADMIN"); | ||
113 | } | ||
114 | |||
115 | @Test | ||
116 | public void userDTOToUserMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() { | ||
117 | userDto.setAuthorities(null); | ||
118 | |||
119 | User user = userMapper.userDTOToUser(userDto); | ||
120 | |||
121 | assertThat(user).isNotNull(); | ||
122 | assertThat(user.getAuthorities()).isNotNull(); | ||
123 | assertThat(user.getAuthorities()).isEmpty(); | ||
124 | } | ||
125 | |||
126 | @Test | ||
127 | public void userDTOToUserMapWithNullUserShouldReturnNull() { | ||
128 | assertThat(userMapper.userDTOToUser(null)).isNull(); | ||
129 | } | ||
130 | |||
131 | @Test | ||
132 | public void testUserFromId() { | ||
133 | assertThat(userMapper.userFromId(DEFAULT_ID).getId()).isEqualTo(DEFAULT_ID); | ||
134 | assertThat(userMapper.userFromId(null)).isNull(); | ||
135 | } | ||
136 | } |
File src/test/java/hu/dns/honlap/web/rest/AccountResourceIT.java added (mode: 100644) (index 0000000..865be6e) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.config.Constants; | ||
5 | import hu.dns.honlap.domain.Authority; | ||
6 | import hu.dns.honlap.domain.User; | ||
7 | import hu.dns.honlap.repository.AuthorityRepository; | ||
8 | import hu.dns.honlap.repository.UserRepository; | ||
9 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
10 | import hu.dns.honlap.service.UserService; | ||
11 | import hu.dns.honlap.service.dto.PasswordChangeDTO; | ||
12 | import hu.dns.honlap.service.dto.UserDTO; | ||
13 | import hu.dns.honlap.web.rest.vm.KeyAndPasswordVM; | ||
14 | import hu.dns.honlap.web.rest.vm.ManagedUserVM; | ||
15 | import org.apache.commons.lang3.RandomStringUtils; | ||
16 | |||
17 | import org.junit.jupiter.api.BeforeEach; | ||
18 | import org.junit.jupiter.api.Test; | ||
19 | import org.springframework.beans.factory.annotation.Autowired; | ||
20 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
21 | import org.springframework.boot.test.context.SpringBootTest; | ||
22 | import org.springframework.http.MediaType; | ||
23 | import org.springframework.http.converter.HttpMessageConverter; | ||
24 | import org.springframework.security.crypto.password.PasswordEncoder; | ||
25 | import org.springframework.security.test.context.support.WithMockUser; | ||
26 | import org.springframework.test.web.servlet.MockMvc; | ||
27 | import org.springframework.transaction.annotation.Transactional; | ||
28 | |||
29 | import java.time.Instant; | ||
30 | import java.util.*; | ||
31 | |||
32 | import static org.assertj.core.api.Assertions.assertThat; | ||
33 | import static hu.dns.honlap.web.rest.AccountResourceIT.TEST_USER_LOGIN; | ||
34 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | ||
35 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
36 | |||
37 | /** | ||
38 | * Integration tests for the {@link AccountResource} REST controller. | ||
39 | */ | ||
40 | @AutoConfigureMockMvc | ||
41 | @WithMockUser(value = TEST_USER_LOGIN) | ||
42 | @SpringBootTest(classes = HonlapApp.class) | ||
43 | public class AccountResourceIT { | ||
44 | static final String TEST_USER_LOGIN = "test"; | ||
45 | |||
46 | @Autowired | ||
47 | private UserRepository userRepository; | ||
48 | |||
49 | @Autowired | ||
50 | private AuthorityRepository authorityRepository; | ||
51 | |||
52 | @Autowired | ||
53 | private UserService userService; | ||
54 | |||
55 | @Autowired | ||
56 | private PasswordEncoder passwordEncoder; | ||
57 | |||
58 | @Autowired | ||
59 | private MockMvc restAccountMockMvc; | ||
60 | |||
61 | @Test | ||
62 | @WithUnauthenticatedMockUser | ||
63 | public void testNonAuthenticatedUser() throws Exception { | ||
64 | restAccountMockMvc.perform(get("/api/authenticate") | ||
65 | .accept(MediaType.APPLICATION_JSON)) | ||
66 | .andExpect(status().isOk()) | ||
67 | .andExpect(content().string("")); | ||
68 | } | ||
69 | |||
70 | @Test | ||
71 | public void testAuthenticatedUser() throws Exception { | ||
72 | restAccountMockMvc.perform(get("/api/authenticate") | ||
73 | .with(request -> { | ||
74 | request.setRemoteUser(TEST_USER_LOGIN); | ||
75 | return request; | ||
76 | }) | ||
77 | .accept(MediaType.APPLICATION_JSON)) | ||
78 | .andExpect(status().isOk()) | ||
79 | .andExpect(content().string(TEST_USER_LOGIN)); | ||
80 | } | ||
81 | |||
82 | @Test | ||
83 | public void testGetExistingAccount() throws Exception { | ||
84 | Set<String> authorities = new HashSet<>(); | ||
85 | authorities.add(AuthoritiesConstants.ADMIN); | ||
86 | |||
87 | UserDTO user = new UserDTO(); | ||
88 | user.setLogin(TEST_USER_LOGIN); | ||
89 | user.setFirstName("john"); | ||
90 | user.setLastName("doe"); | ||
91 | user.setEmail("john.doe@jhipster.com"); | ||
92 | user.setImageUrl("http://placehold.it/50x50"); | ||
93 | user.setLangKey("en"); | ||
94 | user.setAuthorities(authorities); | ||
95 | userService.createUser(user); | ||
96 | |||
97 | restAccountMockMvc.perform(get("/api/account") | ||
98 | .accept(MediaType.APPLICATION_JSON)) | ||
99 | .andExpect(status().isOk()) | ||
100 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
101 | .andExpect(jsonPath("$.login").value(TEST_USER_LOGIN)) | ||
102 | .andExpect(jsonPath("$.firstName").value("john")) | ||
103 | .andExpect(jsonPath("$.lastName").value("doe")) | ||
104 | .andExpect(jsonPath("$.email").value("john.doe@jhipster.com")) | ||
105 | .andExpect(jsonPath("$.imageUrl").value("http://placehold.it/50x50")) | ||
106 | .andExpect(jsonPath("$.langKey").value("en")) | ||
107 | .andExpect(jsonPath("$.authorities").value(AuthoritiesConstants.ADMIN)); | ||
108 | } | ||
109 | |||
110 | @Test | ||
111 | public void testGetUnknownAccount() throws Exception { | ||
112 | restAccountMockMvc.perform(get("/api/account") | ||
113 | .accept(MediaType.APPLICATION_PROBLEM_JSON)) | ||
114 | .andExpect(status().isInternalServerError()); | ||
115 | } | ||
116 | |||
117 | @Test | ||
118 | @Transactional | ||
119 | public void testRegisterValid() throws Exception { | ||
120 | ManagedUserVM validUser = new ManagedUserVM(); | ||
121 | validUser.setLogin("test-register-valid"); | ||
122 | validUser.setPassword("password"); | ||
123 | validUser.setFirstName("Alice"); | ||
124 | validUser.setLastName("Test"); | ||
125 | validUser.setEmail("test-register-valid@example.com"); | ||
126 | validUser.setImageUrl("http://placehold.it/50x50"); | ||
127 | validUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
128 | validUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
129 | assertThat(userRepository.findOneByLogin("test-register-valid").isPresent()).isFalse(); | ||
130 | |||
131 | restAccountMockMvc.perform( | ||
132 | post("/api/register") | ||
133 | .contentType(MediaType.APPLICATION_JSON) | ||
134 | .content(TestUtil.convertObjectToJsonBytes(validUser))) | ||
135 | .andExpect(status().isCreated()); | ||
136 | |||
137 | assertThat(userRepository.findOneByLogin("test-register-valid").isPresent()).isTrue(); | ||
138 | } | ||
139 | |||
140 | @Test | ||
141 | @Transactional | ||
142 | public void testRegisterInvalidLogin() throws Exception { | ||
143 | ManagedUserVM invalidUser = new ManagedUserVM(); | ||
144 | invalidUser.setLogin("funky-log!n");// <-- invalid | ||
145 | invalidUser.setPassword("password"); | ||
146 | invalidUser.setFirstName("Funky"); | ||
147 | invalidUser.setLastName("One"); | ||
148 | invalidUser.setEmail("funky@example.com"); | ||
149 | invalidUser.setActivated(true); | ||
150 | invalidUser.setImageUrl("http://placehold.it/50x50"); | ||
151 | invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
152 | invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
153 | |||
154 | restAccountMockMvc.perform( | ||
155 | post("/api/register") | ||
156 | .contentType(MediaType.APPLICATION_JSON) | ||
157 | .content(TestUtil.convertObjectToJsonBytes(invalidUser))) | ||
158 | .andExpect(status().isBadRequest()); | ||
159 | |||
160 | Optional<User> user = userRepository.findOneByEmailIgnoreCase("funky@example.com"); | ||
161 | assertThat(user.isPresent()).isFalse(); | ||
162 | } | ||
163 | |||
164 | @Test | ||
165 | @Transactional | ||
166 | public void testRegisterInvalidEmail() throws Exception { | ||
167 | ManagedUserVM invalidUser = new ManagedUserVM(); | ||
168 | invalidUser.setLogin("bob"); | ||
169 | invalidUser.setPassword("password"); | ||
170 | invalidUser.setFirstName("Bob"); | ||
171 | invalidUser.setLastName("Green"); | ||
172 | invalidUser.setEmail("invalid");// <-- invalid | ||
173 | invalidUser.setActivated(true); | ||
174 | invalidUser.setImageUrl("http://placehold.it/50x50"); | ||
175 | invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
176 | invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
177 | |||
178 | restAccountMockMvc.perform( | ||
179 | post("/api/register") | ||
180 | .contentType(MediaType.APPLICATION_JSON) | ||
181 | .content(TestUtil.convertObjectToJsonBytes(invalidUser))) | ||
182 | .andExpect(status().isBadRequest()); | ||
183 | |||
184 | Optional<User> user = userRepository.findOneByLogin("bob"); | ||
185 | assertThat(user.isPresent()).isFalse(); | ||
186 | } | ||
187 | |||
188 | @Test | ||
189 | @Transactional | ||
190 | public void testRegisterInvalidPassword() throws Exception { | ||
191 | ManagedUserVM invalidUser = new ManagedUserVM(); | ||
192 | invalidUser.setLogin("bob"); | ||
193 | invalidUser.setPassword("123");// password with only 3 digits | ||
194 | invalidUser.setFirstName("Bob"); | ||
195 | invalidUser.setLastName("Green"); | ||
196 | invalidUser.setEmail("bob@example.com"); | ||
197 | invalidUser.setActivated(true); | ||
198 | invalidUser.setImageUrl("http://placehold.it/50x50"); | ||
199 | invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
200 | invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
201 | |||
202 | restAccountMockMvc.perform( | ||
203 | post("/api/register") | ||
204 | .contentType(MediaType.APPLICATION_JSON) | ||
205 | .content(TestUtil.convertObjectToJsonBytes(invalidUser))) | ||
206 | .andExpect(status().isBadRequest()); | ||
207 | |||
208 | Optional<User> user = userRepository.findOneByLogin("bob"); | ||
209 | assertThat(user.isPresent()).isFalse(); | ||
210 | } | ||
211 | |||
212 | @Test | ||
213 | @Transactional | ||
214 | public void testRegisterNullPassword() throws Exception { | ||
215 | ManagedUserVM invalidUser = new ManagedUserVM(); | ||
216 | invalidUser.setLogin("bob"); | ||
217 | invalidUser.setPassword(null);// invalid null password | ||
218 | invalidUser.setFirstName("Bob"); | ||
219 | invalidUser.setLastName("Green"); | ||
220 | invalidUser.setEmail("bob@example.com"); | ||
221 | invalidUser.setActivated(true); | ||
222 | invalidUser.setImageUrl("http://placehold.it/50x50"); | ||
223 | invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
224 | invalidUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
225 | |||
226 | restAccountMockMvc.perform( | ||
227 | post("/api/register") | ||
228 | .contentType(MediaType.APPLICATION_JSON) | ||
229 | .content(TestUtil.convertObjectToJsonBytes(invalidUser))) | ||
230 | .andExpect(status().isBadRequest()); | ||
231 | |||
232 | Optional<User> user = userRepository.findOneByLogin("bob"); | ||
233 | assertThat(user.isPresent()).isFalse(); | ||
234 | } | ||
235 | |||
236 | @Test | ||
237 | @Transactional | ||
238 | public void testRegisterDuplicateLogin() throws Exception { | ||
239 | // First registration | ||
240 | ManagedUserVM firstUser = new ManagedUserVM(); | ||
241 | firstUser.setLogin("alice"); | ||
242 | firstUser.setPassword("password"); | ||
243 | firstUser.setFirstName("Alice"); | ||
244 | firstUser.setLastName("Something"); | ||
245 | firstUser.setEmail("alice@example.com"); | ||
246 | firstUser.setImageUrl("http://placehold.it/50x50"); | ||
247 | firstUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
248 | firstUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
249 | |||
250 | // Duplicate login, different email | ||
251 | ManagedUserVM secondUser = new ManagedUserVM(); | ||
252 | secondUser.setLogin(firstUser.getLogin()); | ||
253 | secondUser.setPassword(firstUser.getPassword()); | ||
254 | secondUser.setFirstName(firstUser.getFirstName()); | ||
255 | secondUser.setLastName(firstUser.getLastName()); | ||
256 | secondUser.setEmail("alice2@example.com"); | ||
257 | secondUser.setImageUrl(firstUser.getImageUrl()); | ||
258 | secondUser.setLangKey(firstUser.getLangKey()); | ||
259 | secondUser.setCreatedBy(firstUser.getCreatedBy()); | ||
260 | secondUser.setCreatedDate(firstUser.getCreatedDate()); | ||
261 | secondUser.setLastModifiedBy(firstUser.getLastModifiedBy()); | ||
262 | secondUser.setLastModifiedDate(firstUser.getLastModifiedDate()); | ||
263 | secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities())); | ||
264 | |||
265 | // First user | ||
266 | restAccountMockMvc.perform( | ||
267 | post("/api/register") | ||
268 | .contentType(MediaType.APPLICATION_JSON) | ||
269 | .content(TestUtil.convertObjectToJsonBytes(firstUser))) | ||
270 | .andExpect(status().isCreated()); | ||
271 | |||
272 | // Second (non activated) user | ||
273 | restAccountMockMvc.perform( | ||
274 | post("/api/register") | ||
275 | .contentType(MediaType.APPLICATION_JSON) | ||
276 | .content(TestUtil.convertObjectToJsonBytes(secondUser))) | ||
277 | .andExpect(status().isCreated()); | ||
278 | |||
279 | Optional<User> testUser = userRepository.findOneByEmailIgnoreCase("alice2@example.com"); | ||
280 | assertThat(testUser.isPresent()).isTrue(); | ||
281 | testUser.get().setActivated(true); | ||
282 | userRepository.save(testUser.get()); | ||
283 | |||
284 | // Second (already activated) user | ||
285 | restAccountMockMvc.perform( | ||
286 | post("/api/register") | ||
287 | .contentType(MediaType.APPLICATION_JSON) | ||
288 | .content(TestUtil.convertObjectToJsonBytes(secondUser))) | ||
289 | .andExpect(status().is4xxClientError()); | ||
290 | } | ||
291 | |||
292 | @Test | ||
293 | @Transactional | ||
294 | public void testRegisterDuplicateEmail() throws Exception { | ||
295 | // First user | ||
296 | ManagedUserVM firstUser = new ManagedUserVM(); | ||
297 | firstUser.setLogin("test-register-duplicate-email"); | ||
298 | firstUser.setPassword("password"); | ||
299 | firstUser.setFirstName("Alice"); | ||
300 | firstUser.setLastName("Test"); | ||
301 | firstUser.setEmail("test-register-duplicate-email@example.com"); | ||
302 | firstUser.setImageUrl("http://placehold.it/50x50"); | ||
303 | firstUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
304 | firstUser.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
305 | |||
306 | // Register first user | ||
307 | restAccountMockMvc.perform( | ||
308 | post("/api/register") | ||
309 | .contentType(MediaType.APPLICATION_JSON) | ||
310 | .content(TestUtil.convertObjectToJsonBytes(firstUser))) | ||
311 | .andExpect(status().isCreated()); | ||
312 | |||
313 | Optional<User> testUser1 = userRepository.findOneByLogin("test-register-duplicate-email"); | ||
314 | assertThat(testUser1.isPresent()).isTrue(); | ||
315 | |||
316 | // Duplicate email, different login | ||
317 | ManagedUserVM secondUser = new ManagedUserVM(); | ||
318 | secondUser.setLogin("test-register-duplicate-email-2"); | ||
319 | secondUser.setPassword(firstUser.getPassword()); | ||
320 | secondUser.setFirstName(firstUser.getFirstName()); | ||
321 | secondUser.setLastName(firstUser.getLastName()); | ||
322 | secondUser.setEmail(firstUser.getEmail()); | ||
323 | secondUser.setImageUrl(firstUser.getImageUrl()); | ||
324 | secondUser.setLangKey(firstUser.getLangKey()); | ||
325 | secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities())); | ||
326 | |||
327 | // Register second (non activated) user | ||
328 | restAccountMockMvc.perform( | ||
329 | post("/api/register") | ||
330 | .contentType(MediaType.APPLICATION_JSON) | ||
331 | .content(TestUtil.convertObjectToJsonBytes(secondUser))) | ||
332 | .andExpect(status().isCreated()); | ||
333 | |||
334 | Optional<User> testUser2 = userRepository.findOneByLogin("test-register-duplicate-email"); | ||
335 | assertThat(testUser2.isPresent()).isFalse(); | ||
336 | |||
337 | Optional<User> testUser3 = userRepository.findOneByLogin("test-register-duplicate-email-2"); | ||
338 | assertThat(testUser3.isPresent()).isTrue(); | ||
339 | |||
340 | // Duplicate email - with uppercase email address | ||
341 | ManagedUserVM userWithUpperCaseEmail = new ManagedUserVM(); | ||
342 | userWithUpperCaseEmail.setId(firstUser.getId()); | ||
343 | userWithUpperCaseEmail.setLogin("test-register-duplicate-email-3"); | ||
344 | userWithUpperCaseEmail.setPassword(firstUser.getPassword()); | ||
345 | userWithUpperCaseEmail.setFirstName(firstUser.getFirstName()); | ||
346 | userWithUpperCaseEmail.setLastName(firstUser.getLastName()); | ||
347 | userWithUpperCaseEmail.setEmail("TEST-register-duplicate-email@example.com"); | ||
348 | userWithUpperCaseEmail.setImageUrl(firstUser.getImageUrl()); | ||
349 | userWithUpperCaseEmail.setLangKey(firstUser.getLangKey()); | ||
350 | userWithUpperCaseEmail.setAuthorities(new HashSet<>(firstUser.getAuthorities())); | ||
351 | |||
352 | // Register third (not activated) user | ||
353 | restAccountMockMvc.perform( | ||
354 | post("/api/register") | ||
355 | .contentType(MediaType.APPLICATION_JSON) | ||
356 | .content(TestUtil.convertObjectToJsonBytes(userWithUpperCaseEmail))) | ||
357 | .andExpect(status().isCreated()); | ||
358 | |||
359 | Optional<User> testUser4 = userRepository.findOneByLogin("test-register-duplicate-email-3"); | ||
360 | assertThat(testUser4.isPresent()).isTrue(); | ||
361 | assertThat(testUser4.get().getEmail()).isEqualTo("test-register-duplicate-email@example.com"); | ||
362 | |||
363 | testUser4.get().setActivated(true); | ||
364 | userService.updateUser((new UserDTO(testUser4.get()))); | ||
365 | |||
366 | // Register 4th (already activated) user | ||
367 | restAccountMockMvc.perform( | ||
368 | post("/api/register") | ||
369 | .contentType(MediaType.APPLICATION_JSON) | ||
370 | .content(TestUtil.convertObjectToJsonBytes(secondUser))) | ||
371 | .andExpect(status().is4xxClientError()); | ||
372 | } | ||
373 | |||
374 | @Test | ||
375 | @Transactional | ||
376 | public void testRegisterAdminIsIgnored() throws Exception { | ||
377 | ManagedUserVM validUser = new ManagedUserVM(); | ||
378 | validUser.setLogin("badguy"); | ||
379 | validUser.setPassword("password"); | ||
380 | validUser.setFirstName("Bad"); | ||
381 | validUser.setLastName("Guy"); | ||
382 | validUser.setEmail("badguy@example.com"); | ||
383 | validUser.setActivated(true); | ||
384 | validUser.setImageUrl("http://placehold.it/50x50"); | ||
385 | validUser.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
386 | validUser.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); | ||
387 | |||
388 | restAccountMockMvc.perform( | ||
389 | post("/api/register") | ||
390 | .contentType(MediaType.APPLICATION_JSON) | ||
391 | .content(TestUtil.convertObjectToJsonBytes(validUser))) | ||
392 | .andExpect(status().isCreated()); | ||
393 | |||
394 | Optional<User> userDup = userRepository.findOneByLogin("badguy"); | ||
395 | assertThat(userDup.isPresent()).isTrue(); | ||
396 | assertThat(userDup.get().getAuthorities()).hasSize(1) | ||
397 | .containsExactly(authorityRepository.findById(AuthoritiesConstants.USER).get()); | ||
398 | } | ||
399 | |||
400 | @Test | ||
401 | @Transactional | ||
402 | public void testActivateAccount() throws Exception { | ||
403 | final String activationKey = "some activation key"; | ||
404 | User user = new User(); | ||
405 | user.setLogin("activate-account"); | ||
406 | user.setEmail("activate-account@example.com"); | ||
407 | user.setPassword(RandomStringUtils.random(60)); | ||
408 | user.setActivated(false); | ||
409 | user.setActivationKey(activationKey); | ||
410 | |||
411 | userRepository.saveAndFlush(user); | ||
412 | |||
413 | restAccountMockMvc.perform(get("/api/activate?key={activationKey}", activationKey)) | ||
414 | .andExpect(status().isOk()); | ||
415 | |||
416 | user = userRepository.findOneByLogin(user.getLogin()).orElse(null); | ||
417 | assertThat(user.getActivated()).isTrue(); | ||
418 | } | ||
419 | |||
420 | @Test | ||
421 | @Transactional | ||
422 | public void testActivateAccountWithWrongKey() throws Exception { | ||
423 | restAccountMockMvc.perform(get("/api/activate?key=wrongActivationKey")) | ||
424 | .andExpect(status().isInternalServerError()); | ||
425 | } | ||
426 | |||
427 | @Test | ||
428 | @Transactional | ||
429 | @WithMockUser("save-account") | ||
430 | public void testSaveAccount() throws Exception { | ||
431 | User user = new User(); | ||
432 | user.setLogin("save-account"); | ||
433 | user.setEmail("save-account@example.com"); | ||
434 | user.setPassword(RandomStringUtils.random(60)); | ||
435 | user.setActivated(true); | ||
436 | |||
437 | userRepository.saveAndFlush(user); | ||
438 | |||
439 | UserDTO userDTO = new UserDTO(); | ||
440 | userDTO.setLogin("not-used"); | ||
441 | userDTO.setFirstName("firstname"); | ||
442 | userDTO.setLastName("lastname"); | ||
443 | userDTO.setEmail("save-account@example.com"); | ||
444 | userDTO.setActivated(false); | ||
445 | userDTO.setImageUrl("http://placehold.it/50x50"); | ||
446 | userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
447 | userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); | ||
448 | |||
449 | restAccountMockMvc.perform( | ||
450 | post("/api/account") | ||
451 | .contentType(MediaType.APPLICATION_JSON) | ||
452 | .content(TestUtil.convertObjectToJsonBytes(userDTO))) | ||
453 | .andExpect(status().isOk()); | ||
454 | |||
455 | User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); | ||
456 | assertThat(updatedUser.getFirstName()).isEqualTo(userDTO.getFirstName()); | ||
457 | assertThat(updatedUser.getLastName()).isEqualTo(userDTO.getLastName()); | ||
458 | assertThat(updatedUser.getEmail()).isEqualTo(userDTO.getEmail()); | ||
459 | assertThat(updatedUser.getLangKey()).isEqualTo(userDTO.getLangKey()); | ||
460 | assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); | ||
461 | assertThat(updatedUser.getImageUrl()).isEqualTo(userDTO.getImageUrl()); | ||
462 | assertThat(updatedUser.getActivated()).isEqualTo(true); | ||
463 | assertThat(updatedUser.getAuthorities()).isEmpty(); | ||
464 | } | ||
465 | |||
466 | @Test | ||
467 | @Transactional | ||
468 | @WithMockUser("save-invalid-email") | ||
469 | public void testSaveInvalidEmail() throws Exception { | ||
470 | User user = new User(); | ||
471 | user.setLogin("save-invalid-email"); | ||
472 | user.setEmail("save-invalid-email@example.com"); | ||
473 | user.setPassword(RandomStringUtils.random(60)); | ||
474 | user.setActivated(true); | ||
475 | |||
476 | userRepository.saveAndFlush(user); | ||
477 | |||
478 | UserDTO userDTO = new UserDTO(); | ||
479 | userDTO.setLogin("not-used"); | ||
480 | userDTO.setFirstName("firstname"); | ||
481 | userDTO.setLastName("lastname"); | ||
482 | userDTO.setEmail("invalid email"); | ||
483 | userDTO.setActivated(false); | ||
484 | userDTO.setImageUrl("http://placehold.it/50x50"); | ||
485 | userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
486 | userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); | ||
487 | |||
488 | restAccountMockMvc.perform( | ||
489 | post("/api/account") | ||
490 | .contentType(MediaType.APPLICATION_JSON) | ||
491 | .content(TestUtil.convertObjectToJsonBytes(userDTO))) | ||
492 | .andExpect(status().isBadRequest()); | ||
493 | |||
494 | assertThat(userRepository.findOneByEmailIgnoreCase("invalid email")).isNotPresent(); | ||
495 | } | ||
496 | |||
497 | @Test | ||
498 | @Transactional | ||
499 | @WithMockUser("save-existing-email") | ||
500 | public void testSaveExistingEmail() throws Exception { | ||
501 | User user = new User(); | ||
502 | user.setLogin("save-existing-email"); | ||
503 | user.setEmail("save-existing-email@example.com"); | ||
504 | user.setPassword(RandomStringUtils.random(60)); | ||
505 | user.setActivated(true); | ||
506 | |||
507 | userRepository.saveAndFlush(user); | ||
508 | |||
509 | User anotherUser = new User(); | ||
510 | anotherUser.setLogin("save-existing-email2"); | ||
511 | anotherUser.setEmail("save-existing-email2@example.com"); | ||
512 | anotherUser.setPassword(RandomStringUtils.random(60)); | ||
513 | anotherUser.setActivated(true); | ||
514 | |||
515 | userRepository.saveAndFlush(anotherUser); | ||
516 | |||
517 | UserDTO userDTO = new UserDTO(); | ||
518 | userDTO.setLogin("not-used"); | ||
519 | userDTO.setFirstName("firstname"); | ||
520 | userDTO.setLastName("lastname"); | ||
521 | userDTO.setEmail("save-existing-email2@example.com"); | ||
522 | userDTO.setActivated(false); | ||
523 | userDTO.setImageUrl("http://placehold.it/50x50"); | ||
524 | userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
525 | userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); | ||
526 | |||
527 | restAccountMockMvc.perform( | ||
528 | post("/api/account") | ||
529 | .contentType(MediaType.APPLICATION_JSON) | ||
530 | .content(TestUtil.convertObjectToJsonBytes(userDTO))) | ||
531 | .andExpect(status().isBadRequest()); | ||
532 | |||
533 | User updatedUser = userRepository.findOneByLogin("save-existing-email").orElse(null); | ||
534 | assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email@example.com"); | ||
535 | } | ||
536 | |||
537 | @Test | ||
538 | @Transactional | ||
539 | @WithMockUser("save-existing-email-and-login") | ||
540 | public void testSaveExistingEmailAndLogin() throws Exception { | ||
541 | User user = new User(); | ||
542 | user.setLogin("save-existing-email-and-login"); | ||
543 | user.setEmail("save-existing-email-and-login@example.com"); | ||
544 | user.setPassword(RandomStringUtils.random(60)); | ||
545 | user.setActivated(true); | ||
546 | |||
547 | userRepository.saveAndFlush(user); | ||
548 | |||
549 | UserDTO userDTO = new UserDTO(); | ||
550 | userDTO.setLogin("not-used"); | ||
551 | userDTO.setFirstName("firstname"); | ||
552 | userDTO.setLastName("lastname"); | ||
553 | userDTO.setEmail("save-existing-email-and-login@example.com"); | ||
554 | userDTO.setActivated(false); | ||
555 | userDTO.setImageUrl("http://placehold.it/50x50"); | ||
556 | userDTO.setLangKey(Constants.DEFAULT_LANGUAGE); | ||
557 | userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.ADMIN)); | ||
558 | |||
559 | restAccountMockMvc.perform( | ||
560 | post("/api/account") | ||
561 | .contentType(MediaType.APPLICATION_JSON) | ||
562 | .content(TestUtil.convertObjectToJsonBytes(userDTO))) | ||
563 | .andExpect(status().isOk()); | ||
564 | |||
565 | User updatedUser = userRepository.findOneByLogin("save-existing-email-and-login").orElse(null); | ||
566 | assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email-and-login@example.com"); | ||
567 | } | ||
568 | |||
569 | @Test | ||
570 | @Transactional | ||
571 | @WithMockUser("change-password-wrong-existing-password") | ||
572 | public void testChangePasswordWrongExistingPassword() throws Exception { | ||
573 | User user = new User(); | ||
574 | String currentPassword = RandomStringUtils.random(60); | ||
575 | user.setPassword(passwordEncoder.encode(currentPassword)); | ||
576 | user.setLogin("change-password-wrong-existing-password"); | ||
577 | user.setEmail("change-password-wrong-existing-password@example.com"); | ||
578 | userRepository.saveAndFlush(user); | ||
579 | |||
580 | restAccountMockMvc.perform(post("/api/account/change-password") | ||
581 | .contentType(MediaType.APPLICATION_JSON) | ||
582 | .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO("1"+currentPassword, "new password"))) | ||
583 | ) | ||
584 | .andExpect(status().isBadRequest()); | ||
585 | |||
586 | User updatedUser = userRepository.findOneByLogin("change-password-wrong-existing-password").orElse(null); | ||
587 | assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isFalse(); | ||
588 | assertThat(passwordEncoder.matches(currentPassword, updatedUser.getPassword())).isTrue(); | ||
589 | } | ||
590 | |||
591 | @Test | ||
592 | @Transactional | ||
593 | @WithMockUser("change-password") | ||
594 | public void testChangePassword() throws Exception { | ||
595 | User user = new User(); | ||
596 | String currentPassword = RandomStringUtils.random(60); | ||
597 | user.setPassword(passwordEncoder.encode(currentPassword)); | ||
598 | user.setLogin("change-password"); | ||
599 | user.setEmail("change-password@example.com"); | ||
600 | userRepository.saveAndFlush(user); | ||
601 | |||
602 | restAccountMockMvc.perform(post("/api/account/change-password") | ||
603 | .contentType(MediaType.APPLICATION_JSON) | ||
604 | .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, "new password"))) | ||
605 | ) | ||
606 | .andExpect(status().isOk()); | ||
607 | |||
608 | User updatedUser = userRepository.findOneByLogin("change-password").orElse(null); | ||
609 | assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isTrue(); | ||
610 | } | ||
611 | |||
612 | @Test | ||
613 | @Transactional | ||
614 | @WithMockUser("change-password-too-small") | ||
615 | public void testChangePasswordTooSmall() throws Exception { | ||
616 | User user = new User(); | ||
617 | String currentPassword = RandomStringUtils.random(60); | ||
618 | user.setPassword(passwordEncoder.encode(currentPassword)); | ||
619 | user.setLogin("change-password-too-small"); | ||
620 | user.setEmail("change-password-too-small@example.com"); | ||
621 | userRepository.saveAndFlush(user); | ||
622 | |||
623 | String newPassword = RandomStringUtils.random(ManagedUserVM.PASSWORD_MIN_LENGTH - 1); | ||
624 | |||
625 | restAccountMockMvc.perform(post("/api/account/change-password") | ||
626 | .contentType(MediaType.APPLICATION_JSON) | ||
627 | .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, newPassword))) | ||
628 | ) | ||
629 | .andExpect(status().isBadRequest()); | ||
630 | |||
631 | User updatedUser = userRepository.findOneByLogin("change-password-too-small").orElse(null); | ||
632 | assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); | ||
633 | } | ||
634 | |||
635 | @Test | ||
636 | @Transactional | ||
637 | @WithMockUser("change-password-too-long") | ||
638 | public void testChangePasswordTooLong() throws Exception { | ||
639 | User user = new User(); | ||
640 | String currentPassword = RandomStringUtils.random(60); | ||
641 | user.setPassword(passwordEncoder.encode(currentPassword)); | ||
642 | user.setLogin("change-password-too-long"); | ||
643 | user.setEmail("change-password-too-long@example.com"); | ||
644 | userRepository.saveAndFlush(user); | ||
645 | |||
646 | String newPassword = RandomStringUtils.random(ManagedUserVM.PASSWORD_MAX_LENGTH + 1); | ||
647 | |||
648 | restAccountMockMvc.perform(post("/api/account/change-password") | ||
649 | .contentType(MediaType.APPLICATION_JSON) | ||
650 | .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, newPassword))) | ||
651 | ) | ||
652 | .andExpect(status().isBadRequest()); | ||
653 | |||
654 | User updatedUser = userRepository.findOneByLogin("change-password-too-long").orElse(null); | ||
655 | assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); | ||
656 | } | ||
657 | |||
658 | @Test | ||
659 | @Transactional | ||
660 | @WithMockUser("change-password-empty") | ||
661 | public void testChangePasswordEmpty() throws Exception { | ||
662 | User user = new User(); | ||
663 | String currentPassword = RandomStringUtils.random(60); | ||
664 | user.setPassword(passwordEncoder.encode(currentPassword)); | ||
665 | user.setLogin("change-password-empty"); | ||
666 | user.setEmail("change-password-empty@example.com"); | ||
667 | userRepository.saveAndFlush(user); | ||
668 | |||
669 | restAccountMockMvc.perform(post("/api/account/change-password") | ||
670 | .contentType(MediaType.APPLICATION_JSON) | ||
671 | .content(TestUtil.convertObjectToJsonBytes(new PasswordChangeDTO(currentPassword, ""))) | ||
672 | ) | ||
673 | .andExpect(status().isBadRequest()); | ||
674 | |||
675 | User updatedUser = userRepository.findOneByLogin("change-password-empty").orElse(null); | ||
676 | assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword()); | ||
677 | } | ||
678 | |||
679 | @Test | ||
680 | @Transactional | ||
681 | public void testRequestPasswordReset() throws Exception { | ||
682 | User user = new User(); | ||
683 | user.setPassword(RandomStringUtils.random(60)); | ||
684 | user.setActivated(true); | ||
685 | user.setLogin("password-reset"); | ||
686 | user.setEmail("password-reset@example.com"); | ||
687 | userRepository.saveAndFlush(user); | ||
688 | |||
689 | restAccountMockMvc.perform(post("/api/account/reset-password/init") | ||
690 | .content("password-reset@example.com") | ||
691 | ) | ||
692 | .andExpect(status().isOk()); | ||
693 | } | ||
694 | |||
695 | @Test | ||
696 | @Transactional | ||
697 | public void testRequestPasswordResetUpperCaseEmail() throws Exception { | ||
698 | User user = new User(); | ||
699 | user.setPassword(RandomStringUtils.random(60)); | ||
700 | user.setActivated(true); | ||
701 | user.setLogin("password-reset"); | ||
702 | user.setEmail("password-reset@example.com"); | ||
703 | userRepository.saveAndFlush(user); | ||
704 | |||
705 | restAccountMockMvc.perform(post("/api/account/reset-password/init") | ||
706 | .content("password-reset@EXAMPLE.COM") | ||
707 | ) | ||
708 | .andExpect(status().isOk()); | ||
709 | } | ||
710 | |||
711 | @Test | ||
712 | public void testRequestPasswordResetWrongEmail() throws Exception { | ||
713 | restAccountMockMvc.perform( | ||
714 | post("/api/account/reset-password/init") | ||
715 | .content("password-reset-wrong-email@example.com")) | ||
716 | .andExpect(status().isOk()); | ||
717 | } | ||
718 | |||
719 | @Test | ||
720 | @Transactional | ||
721 | public void testFinishPasswordReset() throws Exception { | ||
722 | User user = new User(); | ||
723 | user.setPassword(RandomStringUtils.random(60)); | ||
724 | user.setLogin("finish-password-reset"); | ||
725 | user.setEmail("finish-password-reset@example.com"); | ||
726 | user.setResetDate(Instant.now().plusSeconds(60)); | ||
727 | user.setResetKey("reset key"); | ||
728 | userRepository.saveAndFlush(user); | ||
729 | |||
730 | KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); | ||
731 | keyAndPassword.setKey(user.getResetKey()); | ||
732 | keyAndPassword.setNewPassword("new password"); | ||
733 | |||
734 | restAccountMockMvc.perform( | ||
735 | post("/api/account/reset-password/finish") | ||
736 | .contentType(MediaType.APPLICATION_JSON) | ||
737 | .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) | ||
738 | .andExpect(status().isOk()); | ||
739 | |||
740 | User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); | ||
741 | assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isTrue(); | ||
742 | } | ||
743 | |||
744 | @Test | ||
745 | @Transactional | ||
746 | public void testFinishPasswordResetTooSmall() throws Exception { | ||
747 | User user = new User(); | ||
748 | user.setPassword(RandomStringUtils.random(60)); | ||
749 | user.setLogin("finish-password-reset-too-small"); | ||
750 | user.setEmail("finish-password-reset-too-small@example.com"); | ||
751 | user.setResetDate(Instant.now().plusSeconds(60)); | ||
752 | user.setResetKey("reset key too small"); | ||
753 | userRepository.saveAndFlush(user); | ||
754 | |||
755 | KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); | ||
756 | keyAndPassword.setKey(user.getResetKey()); | ||
757 | keyAndPassword.setNewPassword("foo"); | ||
758 | |||
759 | restAccountMockMvc.perform( | ||
760 | post("/api/account/reset-password/finish") | ||
761 | .contentType(MediaType.APPLICATION_JSON) | ||
762 | .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) | ||
763 | .andExpect(status().isBadRequest()); | ||
764 | |||
765 | User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null); | ||
766 | assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isFalse(); | ||
767 | } | ||
768 | |||
769 | @Test | ||
770 | @Transactional | ||
771 | public void testFinishPasswordResetWrongKey() throws Exception { | ||
772 | KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM(); | ||
773 | keyAndPassword.setKey("wrong reset key"); | ||
774 | keyAndPassword.setNewPassword("new password"); | ||
775 | |||
776 | restAccountMockMvc.perform( | ||
777 | post("/api/account/reset-password/finish") | ||
778 | .contentType(MediaType.APPLICATION_JSON) | ||
779 | .content(TestUtil.convertObjectToJsonBytes(keyAndPassword))) | ||
780 | .andExpect(status().isInternalServerError()); | ||
781 | } | ||
782 | } |
File src/test/java/hu/dns/honlap/web/rest/AuditResourceIT.java added (mode: 100644) (index 0000000..c44bb84) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import io.github.jhipster.config.JHipsterProperties; | ||
5 | import hu.dns.honlap.config.audit.AuditEventConverter; | ||
6 | import hu.dns.honlap.domain.PersistentAuditEvent; | ||
7 | import hu.dns.honlap.repository.PersistenceAuditEventRepository; | ||
8 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
9 | |||
10 | import hu.dns.honlap.service.AuditEventService; | ||
11 | import org.junit.jupiter.api.BeforeEach; | ||
12 | import org.junit.jupiter.api.Test; | ||
13 | import org.mockito.MockitoAnnotations; | ||
14 | import org.springframework.beans.factory.annotation.Autowired; | ||
15 | import org.springframework.beans.factory.annotation.Qualifier; | ||
16 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
17 | import org.springframework.boot.test.context.SpringBootTest; | ||
18 | import org.springframework.data.web.PageableHandlerMethodArgumentResolver; | ||
19 | import org.springframework.format.support.FormattingConversionService; | ||
20 | import org.springframework.http.MediaType; | ||
21 | import org.springframework.security.test.context.support.WithMockUser; | ||
22 | import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; | ||
23 | import org.springframework.test.web.servlet.MockMvc; | ||
24 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
25 | import org.springframework.transaction.annotation.Transactional; | ||
26 | |||
27 | import java.time.Instant; | ||
28 | |||
29 | import static org.assertj.core.api.AssertionsForClassTypes.assertThat; | ||
30 | import static org.hamcrest.Matchers.hasItem; | ||
31 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
32 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
33 | |||
34 | /** | ||
35 | * Integration tests for the {@link AuditResource} REST controller. | ||
36 | */ | ||
37 | @AutoConfigureMockMvc | ||
38 | @WithMockUser(authorities = AuthoritiesConstants.ADMIN) | ||
39 | @SpringBootTest(classes = HonlapApp.class) | ||
40 | @Transactional | ||
41 | public class AuditResourceIT { | ||
42 | |||
43 | private static final String SAMPLE_PRINCIPAL = "SAMPLE_PRINCIPAL"; | ||
44 | private static final String SAMPLE_TYPE = "SAMPLE_TYPE"; | ||
45 | private static final Instant SAMPLE_TIMESTAMP = Instant.parse("2015-08-04T10:11:30Z"); | ||
46 | private static final long SECONDS_PER_DAY = 60 * 60 * 24; | ||
47 | |||
48 | @Autowired | ||
49 | private PersistenceAuditEventRepository auditEventRepository; | ||
50 | |||
51 | private PersistentAuditEvent auditEvent; | ||
52 | |||
53 | @Autowired | ||
54 | private MockMvc restAuditMockMvc; | ||
55 | |||
56 | @BeforeEach | ||
57 | public void initTest() { | ||
58 | auditEventRepository.deleteAll(); | ||
59 | auditEvent = new PersistentAuditEvent(); | ||
60 | auditEvent.setAuditEventType(SAMPLE_TYPE); | ||
61 | auditEvent.setPrincipal(SAMPLE_PRINCIPAL); | ||
62 | auditEvent.setAuditEventDate(SAMPLE_TIMESTAMP); | ||
63 | } | ||
64 | |||
65 | @Test | ||
66 | public void getAllAudits() throws Exception { | ||
67 | // Initialize the database | ||
68 | auditEventRepository.save(auditEvent); | ||
69 | |||
70 | // Get all the audits | ||
71 | restAuditMockMvc.perform(get("/management/audits")) | ||
72 | .andExpect(status().isOk()) | ||
73 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
74 | .andExpect(jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))); | ||
75 | } | ||
76 | |||
77 | @Test | ||
78 | public void getAudit() throws Exception { | ||
79 | // Initialize the database | ||
80 | auditEventRepository.save(auditEvent); | ||
81 | |||
82 | // Get the audit | ||
83 | restAuditMockMvc.perform(get("/management/audits/{id}", auditEvent.getId())) | ||
84 | .andExpect(status().isOk()) | ||
85 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
86 | .andExpect(jsonPath("$.principal").value(SAMPLE_PRINCIPAL)); | ||
87 | } | ||
88 | |||
89 | @Test | ||
90 | public void getAuditsByDate() throws Exception { | ||
91 | // Initialize the database | ||
92 | auditEventRepository.save(auditEvent); | ||
93 | |||
94 | // Generate dates for selecting audits by date, making sure the period will contain the audit | ||
95 | String fromDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); | ||
96 | String toDate = SAMPLE_TIMESTAMP.plusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); | ||
97 | |||
98 | // Get the audit | ||
99 | restAuditMockMvc.perform(get("/management/audits?fromDate="+fromDate+"&toDate="+toDate)) | ||
100 | .andExpect(status().isOk()) | ||
101 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
102 | .andExpect(jsonPath("$.[*].principal").value(hasItem(SAMPLE_PRINCIPAL))); | ||
103 | } | ||
104 | |||
105 | @Test | ||
106 | public void getNonExistingAuditsByDate() throws Exception { | ||
107 | // Initialize the database | ||
108 | auditEventRepository.save(auditEvent); | ||
109 | |||
110 | // Generate dates for selecting audits by date, making sure the period will not contain the sample audit | ||
111 | String fromDate = SAMPLE_TIMESTAMP.minusSeconds(2*SECONDS_PER_DAY).toString().substring(0, 10); | ||
112 | String toDate = SAMPLE_TIMESTAMP.minusSeconds(SECONDS_PER_DAY).toString().substring(0, 10); | ||
113 | |||
114 | // Query audits but expect no results | ||
115 | restAuditMockMvc.perform(get("/management/audits?fromDate=" + fromDate + "&toDate=" + toDate)) | ||
116 | .andExpect(status().isOk()) | ||
117 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
118 | .andExpect(header().string("X-Total-Count", "0")); | ||
119 | } | ||
120 | |||
121 | @Test | ||
122 | public void getNonExistingAudit() throws Exception { | ||
123 | // Get the audit | ||
124 | restAuditMockMvc.perform(get("/management/audits/{id}", Long.MAX_VALUE)) | ||
125 | .andExpect(status().isNotFound()); | ||
126 | } | ||
127 | |||
128 | @Test | ||
129 | @Transactional | ||
130 | public void testPersistentAuditEventEquals() throws Exception { | ||
131 | TestUtil.equalsVerifier(PersistentAuditEvent.class); | ||
132 | PersistentAuditEvent auditEvent1 = new PersistentAuditEvent(); | ||
133 | auditEvent1.setId(1L); | ||
134 | PersistentAuditEvent auditEvent2 = new PersistentAuditEvent(); | ||
135 | auditEvent2.setId(auditEvent1.getId()); | ||
136 | assertThat(auditEvent1).isEqualTo(auditEvent2); | ||
137 | auditEvent2.setId(2L); | ||
138 | assertThat(auditEvent1).isNotEqualTo(auditEvent2); | ||
139 | auditEvent1.setId(null); | ||
140 | assertThat(auditEvent1).isNotEqualTo(auditEvent2); | ||
141 | } | ||
142 | } |
File src/test/java/hu/dns/honlap/web/rest/ClientForwardControllerTest.java added (mode: 100644) (index 0000000..37037c2) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import org.junit.jupiter.api.BeforeEach; | ||
4 | import org.junit.jupiter.api.Test; | ||
5 | import org.springframework.http.MediaType; | ||
6 | import org.springframework.test.web.servlet.MockMvc; | ||
7 | import org.springframework.test.web.servlet.ResultActions; | ||
8 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
9 | import org.springframework.web.bind.annotation.RequestMapping; | ||
10 | import org.springframework.web.bind.annotation.RestController; | ||
11 | |||
12 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
13 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | ||
14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.forwardedUrl; | ||
15 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
16 | |||
17 | /** | ||
18 | * Unit tests for the {@link ClientForwardController} REST controller. | ||
19 | */ | ||
20 | public class ClientForwardControllerTest { | ||
21 | |||
22 | private MockMvc restMockMvc; | ||
23 | |||
24 | @BeforeEach | ||
25 | public void setup() { | ||
26 | ClientForwardController clientForwardController = new ClientForwardController(); | ||
27 | this.restMockMvc = MockMvcBuilders | ||
28 | .standaloneSetup(clientForwardController, new TestController()) | ||
29 | .build(); | ||
30 | } | ||
31 | |||
32 | @Test | ||
33 | public void getBackendEndpoint() throws Exception { | ||
34 | restMockMvc.perform(get("/test")) | ||
35 | .andExpect(status().isOk()) | ||
36 | .andExpect(content().contentTypeCompatibleWith(MediaType.TEXT_PLAIN_VALUE)) | ||
37 | .andExpect(content().string("test")); | ||
38 | } | ||
39 | |||
40 | @Test | ||
41 | public void getClientEndpoint() throws Exception { | ||
42 | ResultActions perform = restMockMvc.perform(get("/non-existant-mapping")); | ||
43 | perform | ||
44 | .andExpect(status().isOk()) | ||
45 | .andExpect(forwardedUrl("/")); | ||
46 | } | ||
47 | |||
48 | @Test | ||
49 | public void getNestedClientEndpoint() throws Exception { | ||
50 | restMockMvc.perform(get("/admin/user-management")) | ||
51 | .andExpect(status().isOk()) | ||
52 | .andExpect(forwardedUrl("/")); | ||
53 | } | ||
54 | |||
55 | |||
56 | @RestController | ||
57 | public static class TestController { | ||
58 | |||
59 | @RequestMapping(value = "/test") | ||
60 | public String test() { | ||
61 | return "test"; | ||
62 | } | ||
63 | } | ||
64 | } |
File src/test/java/hu/dns/honlap/web/rest/PieceOfNewsResourceIT.java added (mode: 100644) (index 0000000..f43fe2b) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.domain.PieceOfNews; | ||
5 | import hu.dns.honlap.repository.PieceOfNewsRepository; | ||
6 | |||
7 | import org.junit.jupiter.api.BeforeEach; | ||
8 | import org.junit.jupiter.api.Test; | ||
9 | import org.springframework.beans.factory.annotation.Autowired; | ||
10 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
11 | import org.springframework.boot.test.context.SpringBootTest; | ||
12 | import org.springframework.http.MediaType; | ||
13 | import org.springframework.security.test.context.support.WithMockUser; | ||
14 | import org.springframework.test.web.servlet.MockMvc; | ||
15 | import org.springframework.transaction.annotation.Transactional; | ||
16 | import javax.persistence.EntityManager; | ||
17 | import java.time.Instant; | ||
18 | import java.time.temporal.ChronoUnit; | ||
19 | import java.util.List; | ||
20 | |||
21 | import static org.assertj.core.api.Assertions.assertThat; | ||
22 | import static org.hamcrest.Matchers.hasItem; | ||
23 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | ||
24 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
25 | |||
26 | /** | ||
27 | * Integration tests for the {@link PieceOfNewsResource} REST controller. | ||
28 | */ | ||
29 | @SpringBootTest(classes = HonlapApp.class) | ||
30 | |||
31 | @AutoConfigureMockMvc | ||
32 | @WithMockUser | ||
33 | public class PieceOfNewsResourceIT { | ||
34 | |||
35 | private static final Integer DEFAULT_APP_ID = 1; | ||
36 | private static final Integer UPDATED_APP_ID = 2; | ||
37 | |||
38 | private static final Instant DEFAULT_NEWS_DATE = Instant.ofEpochMilli(0L); | ||
39 | private static final Instant UPDATED_NEWS_DATE = Instant.now().truncatedTo(ChronoUnit.MILLIS); | ||
40 | |||
41 | private static final String DEFAULT_HEADLINE = "AAAAAAAAAA"; | ||
42 | private static final String UPDATED_HEADLINE = "BBBBBBBBBB"; | ||
43 | |||
44 | private static final String DEFAULT_CONTENT = "AAAAAAAAAA"; | ||
45 | private static final String UPDATED_CONTENT = "BBBBBBBBBB"; | ||
46 | |||
47 | private static final String DEFAULT_LINK = "AAAAAAAAAA"; | ||
48 | private static final String UPDATED_LINK = "BBBBBBBBBB"; | ||
49 | |||
50 | private static final Instant DEFAULT_PUBLISH_DATE = Instant.ofEpochMilli(0L); | ||
51 | private static final Instant UPDATED_PUBLISH_DATE = Instant.now().truncatedTo(ChronoUnit.MILLIS); | ||
52 | |||
53 | private static final String DEFAULT_CREATED_BY = "AAAAAAAAAA"; | ||
54 | private static final String UPDATED_CREATED_BY = "BBBBBBBBBB"; | ||
55 | |||
56 | private static final Instant DEFAULT_CREATED_DATE = Instant.ofEpochMilli(0L); | ||
57 | private static final Instant UPDATED_CREATED_DATE = Instant.now().truncatedTo(ChronoUnit.MILLIS); | ||
58 | |||
59 | private static final String DEFAULT_LAST_MODIFIED_BY = "AAAAAAAAAA"; | ||
60 | private static final String UPDATED_LAST_MODIFIED_BY = "BBBBBBBBBB"; | ||
61 | |||
62 | private static final Instant DEFAULT_LAST_MODIFIED_DATE = Instant.ofEpochMilli(0L); | ||
63 | private static final Instant UPDATED_LAST_MODIFIED_DATE = Instant.now().truncatedTo(ChronoUnit.MILLIS); | ||
64 | |||
65 | @Autowired | ||
66 | private PieceOfNewsRepository pieceOfNewsRepository; | ||
67 | |||
68 | @Autowired | ||
69 | private EntityManager em; | ||
70 | |||
71 | @Autowired | ||
72 | private MockMvc restPieceOfNewsMockMvc; | ||
73 | |||
74 | private PieceOfNews pieceOfNews; | ||
75 | |||
76 | /** | ||
77 | * Create an entity for this test. | ||
78 | * | ||
79 | * This is a static method, as tests for other entities might also need it, | ||
80 | * if they test an entity which requires the current entity. | ||
81 | */ | ||
82 | public static PieceOfNews createEntity(EntityManager em) { | ||
83 | PieceOfNews pieceOfNews = new PieceOfNews() | ||
84 | .appId(DEFAULT_APP_ID) | ||
85 | .newsDate(DEFAULT_NEWS_DATE) | ||
86 | .headline(DEFAULT_HEADLINE) | ||
87 | .content(DEFAULT_CONTENT) | ||
88 | .link(DEFAULT_LINK) | ||
89 | .publishDate(DEFAULT_PUBLISH_DATE) | ||
90 | .createdBy(DEFAULT_CREATED_BY) | ||
91 | .createdDate(DEFAULT_CREATED_DATE) | ||
92 | .lastModifiedBy(DEFAULT_LAST_MODIFIED_BY) | ||
93 | .lastModifiedDate(DEFAULT_LAST_MODIFIED_DATE); | ||
94 | return pieceOfNews; | ||
95 | } | ||
96 | /** | ||
97 | * Create an updated entity for this test. | ||
98 | * | ||
99 | * This is a static method, as tests for other entities might also need it, | ||
100 | * if they test an entity which requires the current entity. | ||
101 | */ | ||
102 | public static PieceOfNews createUpdatedEntity(EntityManager em) { | ||
103 | PieceOfNews pieceOfNews = new PieceOfNews() | ||
104 | .appId(UPDATED_APP_ID) | ||
105 | .newsDate(UPDATED_NEWS_DATE) | ||
106 | .headline(UPDATED_HEADLINE) | ||
107 | .content(UPDATED_CONTENT) | ||
108 | .link(UPDATED_LINK) | ||
109 | .publishDate(UPDATED_PUBLISH_DATE) | ||
110 | .createdBy(UPDATED_CREATED_BY) | ||
111 | .createdDate(UPDATED_CREATED_DATE) | ||
112 | .lastModifiedBy(UPDATED_LAST_MODIFIED_BY) | ||
113 | .lastModifiedDate(UPDATED_LAST_MODIFIED_DATE); | ||
114 | return pieceOfNews; | ||
115 | } | ||
116 | |||
117 | @BeforeEach | ||
118 | public void initTest() { | ||
119 | pieceOfNews = createEntity(em); | ||
120 | } | ||
121 | |||
122 | @Test | ||
123 | @Transactional | ||
124 | public void createPieceOfNews() throws Exception { | ||
125 | int databaseSizeBeforeCreate = pieceOfNewsRepository.findAll().size(); | ||
126 | |||
127 | // Create the PieceOfNews | ||
128 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
129 | .contentType(MediaType.APPLICATION_JSON) | ||
130 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
131 | .andExpect(status().isCreated()); | ||
132 | |||
133 | // Validate the PieceOfNews in the database | ||
134 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
135 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeCreate + 1); | ||
136 | PieceOfNews testPieceOfNews = pieceOfNewsList.get(pieceOfNewsList.size() - 1); | ||
137 | assertThat(testPieceOfNews.getAppId()).isEqualTo(DEFAULT_APP_ID); | ||
138 | assertThat(testPieceOfNews.getNewsDate()).isEqualTo(DEFAULT_NEWS_DATE); | ||
139 | assertThat(testPieceOfNews.getHeadline()).isEqualTo(DEFAULT_HEADLINE); | ||
140 | assertThat(testPieceOfNews.getContent()).isEqualTo(DEFAULT_CONTENT); | ||
141 | assertThat(testPieceOfNews.getLink()).isEqualTo(DEFAULT_LINK); | ||
142 | assertThat(testPieceOfNews.getPublishDate()).isEqualTo(DEFAULT_PUBLISH_DATE); | ||
143 | assertThat(testPieceOfNews.getCreatedBy()).isEqualTo(DEFAULT_CREATED_BY); | ||
144 | assertThat(testPieceOfNews.getCreatedDate()).isEqualTo(DEFAULT_CREATED_DATE); | ||
145 | assertThat(testPieceOfNews.getLastModifiedBy()).isEqualTo(DEFAULT_LAST_MODIFIED_BY); | ||
146 | assertThat(testPieceOfNews.getLastModifiedDate()).isEqualTo(DEFAULT_LAST_MODIFIED_DATE); | ||
147 | } | ||
148 | |||
149 | @Test | ||
150 | @Transactional | ||
151 | public void createPieceOfNewsWithExistingId() throws Exception { | ||
152 | int databaseSizeBeforeCreate = pieceOfNewsRepository.findAll().size(); | ||
153 | |||
154 | // Create the PieceOfNews with an existing ID | ||
155 | pieceOfNews.setId(1L); | ||
156 | |||
157 | // An entity with an existing ID cannot be created, so this API call must fail | ||
158 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
159 | .contentType(MediaType.APPLICATION_JSON) | ||
160 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
161 | .andExpect(status().isBadRequest()); | ||
162 | |||
163 | // Validate the PieceOfNews in the database | ||
164 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
165 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeCreate); | ||
166 | } | ||
167 | |||
168 | |||
169 | @Test | ||
170 | @Transactional | ||
171 | public void checkAppIdIsRequired() throws Exception { | ||
172 | int databaseSizeBeforeTest = pieceOfNewsRepository.findAll().size(); | ||
173 | // set the field null | ||
174 | pieceOfNews.setAppId(null); | ||
175 | |||
176 | // Create the PieceOfNews, which fails. | ||
177 | |||
178 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
179 | .contentType(MediaType.APPLICATION_JSON) | ||
180 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
181 | .andExpect(status().isBadRequest()); | ||
182 | |||
183 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
184 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeTest); | ||
185 | } | ||
186 | |||
187 | @Test | ||
188 | @Transactional | ||
189 | public void checkNewsDateIsRequired() throws Exception { | ||
190 | int databaseSizeBeforeTest = pieceOfNewsRepository.findAll().size(); | ||
191 | // set the field null | ||
192 | pieceOfNews.setNewsDate(null); | ||
193 | |||
194 | // Create the PieceOfNews, which fails. | ||
195 | |||
196 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
197 | .contentType(MediaType.APPLICATION_JSON) | ||
198 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
199 | .andExpect(status().isBadRequest()); | ||
200 | |||
201 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
202 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeTest); | ||
203 | } | ||
204 | |||
205 | @Test | ||
206 | @Transactional | ||
207 | public void checkHeadlineIsRequired() throws Exception { | ||
208 | int databaseSizeBeforeTest = pieceOfNewsRepository.findAll().size(); | ||
209 | // set the field null | ||
210 | pieceOfNews.setHeadline(null); | ||
211 | |||
212 | // Create the PieceOfNews, which fails. | ||
213 | |||
214 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
215 | .contentType(MediaType.APPLICATION_JSON) | ||
216 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
217 | .andExpect(status().isBadRequest()); | ||
218 | |||
219 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
220 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeTest); | ||
221 | } | ||
222 | |||
223 | @Test | ||
224 | @Transactional | ||
225 | public void checkContentIsRequired() throws Exception { | ||
226 | int databaseSizeBeforeTest = pieceOfNewsRepository.findAll().size(); | ||
227 | // set the field null | ||
228 | pieceOfNews.setContent(null); | ||
229 | |||
230 | // Create the PieceOfNews, which fails. | ||
231 | |||
232 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
233 | .contentType(MediaType.APPLICATION_JSON) | ||
234 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
235 | .andExpect(status().isBadRequest()); | ||
236 | |||
237 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
238 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeTest); | ||
239 | } | ||
240 | |||
241 | @Test | ||
242 | @Transactional | ||
243 | public void checkLinkIsRequired() throws Exception { | ||
244 | int databaseSizeBeforeTest = pieceOfNewsRepository.findAll().size(); | ||
245 | // set the field null | ||
246 | pieceOfNews.setLink(null); | ||
247 | |||
248 | // Create the PieceOfNews, which fails. | ||
249 | |||
250 | restPieceOfNewsMockMvc.perform(post("/api/piece-of-news") | ||
251 | .contentType(MediaType.APPLICATION_JSON) | ||
252 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
253 | .andExpect(status().isBadRequest()); | ||
254 | |||
255 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
256 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeTest); | ||
257 | } | ||
258 | |||
259 | @Test | ||
260 | @Transactional | ||
261 | public void getAllPieceOfNews() throws Exception { | ||
262 | // Initialize the database | ||
263 | pieceOfNewsRepository.saveAndFlush(pieceOfNews); | ||
264 | |||
265 | // Get all the pieceOfNewsList | ||
266 | restPieceOfNewsMockMvc.perform(get("/api/piece-of-news?sort=id,desc")) | ||
267 | .andExpect(status().isOk()) | ||
268 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
269 | .andExpect(jsonPath("$.[*].id").value(hasItem(pieceOfNews.getId().intValue()))) | ||
270 | .andExpect(jsonPath("$.[*].appId").value(hasItem(DEFAULT_APP_ID))) | ||
271 | .andExpect(jsonPath("$.[*].newsDate").value(hasItem(DEFAULT_NEWS_DATE.toString()))) | ||
272 | .andExpect(jsonPath("$.[*].headline").value(hasItem(DEFAULT_HEADLINE))) | ||
273 | .andExpect(jsonPath("$.[*].content").value(hasItem(DEFAULT_CONTENT))) | ||
274 | .andExpect(jsonPath("$.[*].link").value(hasItem(DEFAULT_LINK))) | ||
275 | .andExpect(jsonPath("$.[*].publishDate").value(hasItem(DEFAULT_PUBLISH_DATE.toString()))) | ||
276 | .andExpect(jsonPath("$.[*].createdBy").value(hasItem(DEFAULT_CREATED_BY))) | ||
277 | .andExpect(jsonPath("$.[*].createdDate").value(hasItem(DEFAULT_CREATED_DATE.toString()))) | ||
278 | .andExpect(jsonPath("$.[*].lastModifiedBy").value(hasItem(DEFAULT_LAST_MODIFIED_BY))) | ||
279 | .andExpect(jsonPath("$.[*].lastModifiedDate").value(hasItem(DEFAULT_LAST_MODIFIED_DATE.toString()))); | ||
280 | } | ||
281 | |||
282 | @Test | ||
283 | @Transactional | ||
284 | public void getPieceOfNews() throws Exception { | ||
285 | // Initialize the database | ||
286 | pieceOfNewsRepository.saveAndFlush(pieceOfNews); | ||
287 | |||
288 | // Get the pieceOfNews | ||
289 | restPieceOfNewsMockMvc.perform(get("/api/piece-of-news/{id}", pieceOfNews.getId())) | ||
290 | .andExpect(status().isOk()) | ||
291 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
292 | .andExpect(jsonPath("$.id").value(pieceOfNews.getId().intValue())) | ||
293 | .andExpect(jsonPath("$.appId").value(DEFAULT_APP_ID)) | ||
294 | .andExpect(jsonPath("$.newsDate").value(DEFAULT_NEWS_DATE.toString())) | ||
295 | .andExpect(jsonPath("$.headline").value(DEFAULT_HEADLINE)) | ||
296 | .andExpect(jsonPath("$.content").value(DEFAULT_CONTENT)) | ||
297 | .andExpect(jsonPath("$.link").value(DEFAULT_LINK)) | ||
298 | .andExpect(jsonPath("$.publishDate").value(DEFAULT_PUBLISH_DATE.toString())) | ||
299 | .andExpect(jsonPath("$.createdBy").value(DEFAULT_CREATED_BY)) | ||
300 | .andExpect(jsonPath("$.createdDate").value(DEFAULT_CREATED_DATE.toString())) | ||
301 | .andExpect(jsonPath("$.lastModifiedBy").value(DEFAULT_LAST_MODIFIED_BY)) | ||
302 | .andExpect(jsonPath("$.lastModifiedDate").value(DEFAULT_LAST_MODIFIED_DATE.toString())); | ||
303 | } | ||
304 | |||
305 | @Test | ||
306 | @Transactional | ||
307 | public void getNonExistingPieceOfNews() throws Exception { | ||
308 | // Get the pieceOfNews | ||
309 | restPieceOfNewsMockMvc.perform(get("/api/piece-of-news/{id}", Long.MAX_VALUE)) | ||
310 | .andExpect(status().isNotFound()); | ||
311 | } | ||
312 | |||
313 | @Test | ||
314 | @Transactional | ||
315 | public void updatePieceOfNews() throws Exception { | ||
316 | // Initialize the database | ||
317 | pieceOfNewsRepository.saveAndFlush(pieceOfNews); | ||
318 | |||
319 | int databaseSizeBeforeUpdate = pieceOfNewsRepository.findAll().size(); | ||
320 | |||
321 | // Update the pieceOfNews | ||
322 | PieceOfNews updatedPieceOfNews = pieceOfNewsRepository.findById(pieceOfNews.getId()).get(); | ||
323 | // Disconnect from session so that the updates on updatedPieceOfNews are not directly saved in db | ||
324 | em.detach(updatedPieceOfNews); | ||
325 | updatedPieceOfNews | ||
326 | .appId(UPDATED_APP_ID) | ||
327 | .newsDate(UPDATED_NEWS_DATE) | ||
328 | .headline(UPDATED_HEADLINE) | ||
329 | .content(UPDATED_CONTENT) | ||
330 | .link(UPDATED_LINK) | ||
331 | .publishDate(UPDATED_PUBLISH_DATE) | ||
332 | .createdBy(UPDATED_CREATED_BY) | ||
333 | .createdDate(UPDATED_CREATED_DATE) | ||
334 | .lastModifiedBy(UPDATED_LAST_MODIFIED_BY) | ||
335 | .lastModifiedDate(UPDATED_LAST_MODIFIED_DATE); | ||
336 | |||
337 | restPieceOfNewsMockMvc.perform(put("/api/piece-of-news") | ||
338 | .contentType(MediaType.APPLICATION_JSON) | ||
339 | .content(TestUtil.convertObjectToJsonBytes(updatedPieceOfNews))) | ||
340 | .andExpect(status().isOk()); | ||
341 | |||
342 | // Validate the PieceOfNews in the database | ||
343 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
344 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeUpdate); | ||
345 | PieceOfNews testPieceOfNews = pieceOfNewsList.get(pieceOfNewsList.size() - 1); | ||
346 | assertThat(testPieceOfNews.getAppId()).isEqualTo(UPDATED_APP_ID); | ||
347 | assertThat(testPieceOfNews.getNewsDate()).isEqualTo(UPDATED_NEWS_DATE); | ||
348 | assertThat(testPieceOfNews.getHeadline()).isEqualTo(UPDATED_HEADLINE); | ||
349 | assertThat(testPieceOfNews.getContent()).isEqualTo(UPDATED_CONTENT); | ||
350 | assertThat(testPieceOfNews.getLink()).isEqualTo(UPDATED_LINK); | ||
351 | assertThat(testPieceOfNews.getPublishDate()).isEqualTo(UPDATED_PUBLISH_DATE); | ||
352 | assertThat(testPieceOfNews.getCreatedBy()).isEqualTo(UPDATED_CREATED_BY); | ||
353 | assertThat(testPieceOfNews.getCreatedDate()).isEqualTo(UPDATED_CREATED_DATE); | ||
354 | assertThat(testPieceOfNews.getLastModifiedBy()).isEqualTo(UPDATED_LAST_MODIFIED_BY); | ||
355 | assertThat(testPieceOfNews.getLastModifiedDate()).isEqualTo(UPDATED_LAST_MODIFIED_DATE); | ||
356 | } | ||
357 | |||
358 | @Test | ||
359 | @Transactional | ||
360 | public void updateNonExistingPieceOfNews() throws Exception { | ||
361 | int databaseSizeBeforeUpdate = pieceOfNewsRepository.findAll().size(); | ||
362 | |||
363 | // Create the PieceOfNews | ||
364 | |||
365 | // If the entity doesn't have an ID, it will throw BadRequestAlertException | ||
366 | restPieceOfNewsMockMvc.perform(put("/api/piece-of-news") | ||
367 | .contentType(MediaType.APPLICATION_JSON) | ||
368 | .content(TestUtil.convertObjectToJsonBytes(pieceOfNews))) | ||
369 | .andExpect(status().isBadRequest()); | ||
370 | |||
371 | // Validate the PieceOfNews in the database | ||
372 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
373 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeUpdate); | ||
374 | } | ||
375 | |||
376 | @Test | ||
377 | @Transactional | ||
378 | public void deletePieceOfNews() throws Exception { | ||
379 | // Initialize the database | ||
380 | pieceOfNewsRepository.saveAndFlush(pieceOfNews); | ||
381 | |||
382 | int databaseSizeBeforeDelete = pieceOfNewsRepository.findAll().size(); | ||
383 | |||
384 | // Delete the pieceOfNews | ||
385 | restPieceOfNewsMockMvc.perform(delete("/api/piece-of-news/{id}", pieceOfNews.getId()) | ||
386 | .accept(MediaType.APPLICATION_JSON)) | ||
387 | .andExpect(status().isNoContent()); | ||
388 | |||
389 | // Validate the database contains one less item | ||
390 | List<PieceOfNews> pieceOfNewsList = pieceOfNewsRepository.findAll(); | ||
391 | assertThat(pieceOfNewsList).hasSize(databaseSizeBeforeDelete - 1); | ||
392 | } | ||
393 | } |
File src/test/java/hu/dns/honlap/web/rest/TestUtil.java added (mode: 100644) (index 0000000..a097a9e) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import com.fasterxml.jackson.annotation.JsonInclude; | ||
4 | import com.fasterxml.jackson.databind.ObjectMapper; | ||
5 | import com.fasterxml.jackson.databind.SerializationFeature; | ||
6 | import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; | ||
7 | import org.hamcrest.Description; | ||
8 | import org.hamcrest.TypeSafeDiagnosingMatcher; | ||
9 | import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar; | ||
10 | import org.springframework.format.support.DefaultFormattingConversionService; | ||
11 | import org.springframework.format.support.FormattingConversionService; | ||
12 | |||
13 | import java.io.IOException; | ||
14 | import java.time.ZonedDateTime; | ||
15 | import java.time.format.DateTimeParseException; | ||
16 | import java.util.List; | ||
17 | |||
18 | import javax.persistence.EntityManager; | ||
19 | import javax.persistence.TypedQuery; | ||
20 | import javax.persistence.criteria.CriteriaBuilder; | ||
21 | import javax.persistence.criteria.CriteriaQuery; | ||
22 | import javax.persistence.criteria.Root; | ||
23 | |||
24 | import static org.assertj.core.api.Assertions.assertThat; | ||
25 | |||
26 | /** | ||
27 | * Utility class for testing REST controllers. | ||
28 | */ | ||
29 | public final class TestUtil { | ||
30 | |||
31 | private static final ObjectMapper mapper = createObjectMapper(); | ||
32 | |||
33 | private static ObjectMapper createObjectMapper() { | ||
34 | ObjectMapper mapper = new ObjectMapper(); | ||
35 | mapper.configure(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false); | ||
36 | mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); | ||
37 | mapper.registerModule(new JavaTimeModule()); | ||
38 | return mapper; | ||
39 | } | ||
40 | |||
41 | /** | ||
42 | * Convert an object to JSON byte array. | ||
43 | * | ||
44 | * @param object the object to convert. | ||
45 | * @return the JSON byte array. | ||
46 | * @throws IOException | ||
47 | */ | ||
48 | public static byte[] convertObjectToJsonBytes(Object object) throws IOException { | ||
49 | return mapper.writeValueAsBytes(object); | ||
50 | } | ||
51 | |||
52 | /** | ||
53 | * Create a byte array with a specific size filled with specified data. | ||
54 | * | ||
55 | * @param size the size of the byte array. | ||
56 | * @param data the data to put in the byte array. | ||
57 | * @return the JSON byte array. | ||
58 | */ | ||
59 | public static byte[] createByteArray(int size, String data) { | ||
60 | byte[] byteArray = new byte[size]; | ||
61 | for (int i = 0; i < size; i++) { | ||
62 | byteArray[i] = Byte.parseByte(data, 2); | ||
63 | } | ||
64 | return byteArray; | ||
65 | } | ||
66 | |||
67 | /** | ||
68 | * A matcher that tests that the examined string represents the same instant as the reference datetime. | ||
69 | */ | ||
70 | public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher<String> { | ||
71 | |||
72 | private final ZonedDateTime date; | ||
73 | |||
74 | public ZonedDateTimeMatcher(ZonedDateTime date) { | ||
75 | this.date = date; | ||
76 | } | ||
77 | |||
78 | @Override | ||
79 | protected boolean matchesSafely(String item, Description mismatchDescription) { | ||
80 | try { | ||
81 | if (!date.isEqual(ZonedDateTime.parse(item))) { | ||
82 | mismatchDescription.appendText("was ").appendValue(item); | ||
83 | return false; | ||
84 | } | ||
85 | return true; | ||
86 | } catch (DateTimeParseException e) { | ||
87 | mismatchDescription.appendText("was ").appendValue(item) | ||
88 | .appendText(", which could not be parsed as a ZonedDateTime"); | ||
89 | return false; | ||
90 | } | ||
91 | |||
92 | } | ||
93 | |||
94 | @Override | ||
95 | public void describeTo(Description description) { | ||
96 | description.appendText("a String representing the same Instant as ").appendValue(date); | ||
97 | } | ||
98 | } | ||
99 | |||
100 | /** | ||
101 | * Creates a matcher that matches when the examined string represents the same instant as the reference datetime. | ||
102 | * | ||
103 | * @param date the reference datetime against which the examined string is checked. | ||
104 | */ | ||
105 | public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) { | ||
106 | return new ZonedDateTimeMatcher(date); | ||
107 | } | ||
108 | |||
109 | /** | ||
110 | * Verifies the equals/hashcode contract on the domain object. | ||
111 | */ | ||
112 | public static <T> void equalsVerifier(Class<T> clazz) throws Exception { | ||
113 | T domainObject1 = clazz.getConstructor().newInstance(); | ||
114 | assertThat(domainObject1.toString()).isNotNull(); | ||
115 | assertThat(domainObject1).isEqualTo(domainObject1); | ||
116 | assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode()); | ||
117 | // Test with an instance of another class | ||
118 | Object testOtherObject = new Object(); | ||
119 | assertThat(domainObject1).isNotEqualTo(testOtherObject); | ||
120 | assertThat(domainObject1).isNotEqualTo(null); | ||
121 | // Test with an instance of the same class | ||
122 | T domainObject2 = clazz.getConstructor().newInstance(); | ||
123 | assertThat(domainObject1).isNotEqualTo(domainObject2); | ||
124 | // HashCodes are equals because the objects are not persisted yet | ||
125 | assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode()); | ||
126 | } | ||
127 | |||
128 | /** | ||
129 | * Create a {@link FormattingConversionService} which use ISO date format, instead of the localized one. | ||
130 | * @return the {@link FormattingConversionService}. | ||
131 | */ | ||
132 | public static FormattingConversionService createFormattingConversionService() { | ||
133 | DefaultFormattingConversionService dfcs = new DefaultFormattingConversionService (); | ||
134 | DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar(); | ||
135 | registrar.setUseIsoFormat(true); | ||
136 | registrar.registerFormatters(dfcs); | ||
137 | return dfcs; | ||
138 | } | ||
139 | |||
140 | /** | ||
141 | * Makes a an executes a query to the EntityManager finding all stored objects. | ||
142 | * @param <T> The type of objects to be searched | ||
143 | * @param em The instance of the EntityManager | ||
144 | * @param clss The class type to be searched | ||
145 | * @return A list of all found objects | ||
146 | */ | ||
147 | public static <T> List<T> findAll(EntityManager em, Class<T> clss) { | ||
148 | CriteriaBuilder cb = em.getCriteriaBuilder(); | ||
149 | CriteriaQuery<T> cq = cb.createQuery(clss); | ||
150 | Root<T> rootEntry = cq.from(clss); | ||
151 | CriteriaQuery<T> all = cq.select(rootEntry); | ||
152 | TypedQuery<T> allQuery = em.createQuery(all); | ||
153 | return allQuery.getResultList(); | ||
154 | } | ||
155 | |||
156 | private TestUtil() {} | ||
157 | } |
File src/test/java/hu/dns/honlap/web/rest/UserJWTControllerIT.java added (mode: 100644) (index 0000000..2c9d2ae) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.domain.User; | ||
5 | import hu.dns.honlap.repository.UserRepository; | ||
6 | import hu.dns.honlap.web.rest.vm.LoginVM; | ||
7 | import org.junit.jupiter.api.Test; | ||
8 | import org.springframework.beans.factory.annotation.Autowired; | ||
9 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
10 | import org.springframework.boot.test.context.SpringBootTest; | ||
11 | import org.springframework.http.MediaType; | ||
12 | import org.springframework.security.crypto.password.PasswordEncoder; | ||
13 | import org.springframework.test.web.servlet.MockMvc; | ||
14 | import org.springframework.test.web.servlet.setup.MockMvcBuilders; | ||
15 | import org.springframework.transaction.annotation.Transactional; | ||
16 | |||
17 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||
18 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; | ||
19 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
20 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header; | ||
21 | import static org.hamcrest.Matchers.nullValue; | ||
22 | import static org.hamcrest.Matchers.emptyString; | ||
23 | import static org.hamcrest.Matchers.is; | ||
24 | import static org.hamcrest.Matchers.not; | ||
25 | |||
26 | /** | ||
27 | * Integration tests for the {@link UserJWTController} REST controller. | ||
28 | */ | ||
29 | @AutoConfigureMockMvc | ||
30 | @SpringBootTest(classes = HonlapApp.class) | ||
31 | public class UserJWTControllerIT { | ||
32 | |||
33 | @Autowired | ||
34 | private UserRepository userRepository; | ||
35 | |||
36 | @Autowired | ||
37 | private PasswordEncoder passwordEncoder; | ||
38 | |||
39 | @Autowired | ||
40 | private MockMvc mockMvc; | ||
41 | |||
42 | @Test | ||
43 | @Transactional | ||
44 | public void testAuthorize() throws Exception { | ||
45 | User user = new User(); | ||
46 | user.setLogin("user-jwt-controller"); | ||
47 | user.setEmail("user-jwt-controller@example.com"); | ||
48 | user.setActivated(true); | ||
49 | user.setPassword(passwordEncoder.encode("test")); | ||
50 | |||
51 | userRepository.saveAndFlush(user); | ||
52 | |||
53 | LoginVM login = new LoginVM(); | ||
54 | login.setUsername("user-jwt-controller"); | ||
55 | login.setPassword("test"); | ||
56 | mockMvc.perform(post("/api/authenticate") | ||
57 | .contentType(MediaType.APPLICATION_JSON) | ||
58 | .content(TestUtil.convertObjectToJsonBytes(login))) | ||
59 | .andExpect(status().isOk()) | ||
60 | .andExpect(jsonPath("$.id_token").isString()) | ||
61 | .andExpect(jsonPath("$.id_token").isNotEmpty()) | ||
62 | .andExpect(header().string("Authorization", not(nullValue()))) | ||
63 | .andExpect(header().string("Authorization", not(is(emptyString())))); | ||
64 | } | ||
65 | |||
66 | @Test | ||
67 | @Transactional | ||
68 | public void testAuthorizeWithRememberMe() throws Exception { | ||
69 | User user = new User(); | ||
70 | user.setLogin("user-jwt-controller-remember-me"); | ||
71 | user.setEmail("user-jwt-controller-remember-me@example.com"); | ||
72 | user.setActivated(true); | ||
73 | user.setPassword(passwordEncoder.encode("test")); | ||
74 | |||
75 | userRepository.saveAndFlush(user); | ||
76 | |||
77 | LoginVM login = new LoginVM(); | ||
78 | login.setUsername("user-jwt-controller-remember-me"); | ||
79 | login.setPassword("test"); | ||
80 | login.setRememberMe(true); | ||
81 | mockMvc.perform(post("/api/authenticate") | ||
82 | .contentType(MediaType.APPLICATION_JSON) | ||
83 | .content(TestUtil.convertObjectToJsonBytes(login))) | ||
84 | .andExpect(status().isOk()) | ||
85 | .andExpect(jsonPath("$.id_token").isString()) | ||
86 | .andExpect(jsonPath("$.id_token").isNotEmpty()) | ||
87 | .andExpect(header().string("Authorization", not(nullValue()))) | ||
88 | .andExpect(header().string("Authorization", not(is(emptyString())))); | ||
89 | } | ||
90 | |||
91 | @Test | ||
92 | public void testAuthorizeFails() throws Exception { | ||
93 | LoginVM login = new LoginVM(); | ||
94 | login.setUsername("wrong-user"); | ||
95 | login.setPassword("wrong password"); | ||
96 | mockMvc.perform(post("/api/authenticate") | ||
97 | .contentType(MediaType.APPLICATION_JSON) | ||
98 | .content(TestUtil.convertObjectToJsonBytes(login))) | ||
99 | .andExpect(status().isUnauthorized()) | ||
100 | .andExpect(jsonPath("$.id_token").doesNotExist()) | ||
101 | .andExpect(header().doesNotExist("Authorization")); | ||
102 | } | ||
103 | } |
File src/test/java/hu/dns/honlap/web/rest/UserResourceIT.java added (mode: 100644) (index 0000000..5971462) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import hu.dns.honlap.domain.Authority; | ||
5 | import hu.dns.honlap.domain.User; | ||
6 | import hu.dns.honlap.repository.UserRepository; | ||
7 | import hu.dns.honlap.security.AuthoritiesConstants; | ||
8 | import hu.dns.honlap.service.dto.UserDTO; | ||
9 | import hu.dns.honlap.service.mapper.UserMapper; | ||
10 | import hu.dns.honlap.web.rest.vm.ManagedUserVM; | ||
11 | import org.apache.commons.lang3.RandomStringUtils; | ||
12 | import org.junit.jupiter.api.BeforeEach; | ||
13 | import org.junit.jupiter.api.Test; | ||
14 | import org.springframework.beans.factory.annotation.Autowired; | ||
15 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
16 | import org.springframework.boot.test.context.SpringBootTest; | ||
17 | import org.springframework.cache.CacheManager; | ||
18 | import org.springframework.http.MediaType; | ||
19 | import org.springframework.security.test.context.support.WithMockUser; | ||
20 | import org.springframework.test.web.servlet.MockMvc; | ||
21 | import org.springframework.transaction.annotation.Transactional; | ||
22 | |||
23 | import javax.persistence.EntityManager; | ||
24 | import java.time.Instant; | ||
25 | import java.util.*; | ||
26 | import java.util.function.Consumer; | ||
27 | |||
28 | import static org.assertj.core.api.Assertions.assertThat; | ||
29 | import static org.hamcrest.Matchers.hasItems; | ||
30 | import static org.hamcrest.Matchers.hasItem; | ||
31 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; | ||
32 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; | ||
33 | |||
34 | /** | ||
35 | * Integration tests for the {@link UserResource} REST controller. | ||
36 | */ | ||
37 | @AutoConfigureMockMvc | ||
38 | @WithMockUser(authorities = AuthoritiesConstants.ADMIN) | ||
39 | @SpringBootTest(classes = HonlapApp.class) | ||
40 | public class UserResourceIT { | ||
41 | |||
42 | private static final String DEFAULT_LOGIN = "johndoe"; | ||
43 | private static final String UPDATED_LOGIN = "jhipster"; | ||
44 | |||
45 | private static final Long DEFAULT_ID = 1L; | ||
46 | |||
47 | private static final String DEFAULT_PASSWORD = "passjohndoe"; | ||
48 | private static final String UPDATED_PASSWORD = "passjhipster"; | ||
49 | |||
50 | private static final String DEFAULT_EMAIL = "johndoe@localhost"; | ||
51 | private static final String UPDATED_EMAIL = "jhipster@localhost"; | ||
52 | |||
53 | private static final String DEFAULT_FIRSTNAME = "john"; | ||
54 | private static final String UPDATED_FIRSTNAME = "jhipsterFirstName"; | ||
55 | |||
56 | private static final String DEFAULT_LASTNAME = "doe"; | ||
57 | private static final String UPDATED_LASTNAME = "jhipsterLastName"; | ||
58 | |||
59 | private static final String DEFAULT_IMAGEURL = "http://placehold.it/50x50"; | ||
60 | private static final String UPDATED_IMAGEURL = "http://placehold.it/40x40"; | ||
61 | |||
62 | private static final String DEFAULT_LANGKEY = "en"; | ||
63 | private static final String UPDATED_LANGKEY = "fr"; | ||
64 | |||
65 | @Autowired | ||
66 | private UserRepository userRepository; | ||
67 | |||
68 | @Autowired | ||
69 | private UserMapper userMapper; | ||
70 | |||
71 | @Autowired | ||
72 | private EntityManager em; | ||
73 | |||
74 | @Autowired | ||
75 | private CacheManager cacheManager; | ||
76 | |||
77 | @Autowired | ||
78 | private MockMvc restUserMockMvc; | ||
79 | |||
80 | private User user; | ||
81 | |||
82 | @BeforeEach | ||
83 | public void setup() { | ||
84 | cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).clear(); | ||
85 | cacheManager.getCache(UserRepository.USERS_BY_EMAIL_CACHE).clear(); | ||
86 | } | ||
87 | |||
88 | /** | ||
89 | * Create a User. | ||
90 | * | ||
91 | * This is a static method, as tests for other entities might also need it, | ||
92 | * if they test an entity which has a required relationship to the User entity. | ||
93 | */ | ||
94 | public static User createEntity(EntityManager em) { | ||
95 | User user = new User(); | ||
96 | user.setLogin(DEFAULT_LOGIN + RandomStringUtils.randomAlphabetic(5)); | ||
97 | user.setPassword(RandomStringUtils.random(60)); | ||
98 | user.setActivated(true); | ||
99 | user.setEmail(RandomStringUtils.randomAlphabetic(5) + DEFAULT_EMAIL); | ||
100 | user.setFirstName(DEFAULT_FIRSTNAME); | ||
101 | user.setLastName(DEFAULT_LASTNAME); | ||
102 | user.setImageUrl(DEFAULT_IMAGEURL); | ||
103 | user.setLangKey(DEFAULT_LANGKEY); | ||
104 | return user; | ||
105 | } | ||
106 | |||
107 | @BeforeEach | ||
108 | public void initTest() { | ||
109 | user = createEntity(em); | ||
110 | user.setLogin(DEFAULT_LOGIN); | ||
111 | user.setEmail(DEFAULT_EMAIL); | ||
112 | } | ||
113 | |||
114 | @Test | ||
115 | @Transactional | ||
116 | public void createUser() throws Exception { | ||
117 | int databaseSizeBeforeCreate = userRepository.findAll().size(); | ||
118 | |||
119 | // Create the User | ||
120 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
121 | managedUserVM.setLogin(DEFAULT_LOGIN); | ||
122 | managedUserVM.setPassword(DEFAULT_PASSWORD); | ||
123 | managedUserVM.setFirstName(DEFAULT_FIRSTNAME); | ||
124 | managedUserVM.setLastName(DEFAULT_LASTNAME); | ||
125 | managedUserVM.setEmail(DEFAULT_EMAIL); | ||
126 | managedUserVM.setActivated(true); | ||
127 | managedUserVM.setImageUrl(DEFAULT_IMAGEURL); | ||
128 | managedUserVM.setLangKey(DEFAULT_LANGKEY); | ||
129 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
130 | |||
131 | restUserMockMvc.perform(post("/api/users") | ||
132 | .contentType(MediaType.APPLICATION_JSON) | ||
133 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
134 | .andExpect(status().isCreated()); | ||
135 | |||
136 | // Validate the User in the database | ||
137 | assertPersistedUsers(users -> { | ||
138 | assertThat(users).hasSize(databaseSizeBeforeCreate + 1); | ||
139 | User testUser = users.get(users.size() - 1); | ||
140 | assertThat(testUser.getLogin()).isEqualTo(DEFAULT_LOGIN); | ||
141 | assertThat(testUser.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); | ||
142 | assertThat(testUser.getLastName()).isEqualTo(DEFAULT_LASTNAME); | ||
143 | assertThat(testUser.getEmail()).isEqualTo(DEFAULT_EMAIL); | ||
144 | assertThat(testUser.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); | ||
145 | assertThat(testUser.getLangKey()).isEqualTo(DEFAULT_LANGKEY); | ||
146 | }); | ||
147 | } | ||
148 | |||
149 | @Test | ||
150 | @Transactional | ||
151 | public void createUserWithExistingId() throws Exception { | ||
152 | int databaseSizeBeforeCreate = userRepository.findAll().size(); | ||
153 | |||
154 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
155 | managedUserVM.setId(1L); | ||
156 | managedUserVM.setLogin(DEFAULT_LOGIN); | ||
157 | managedUserVM.setPassword(DEFAULT_PASSWORD); | ||
158 | managedUserVM.setFirstName(DEFAULT_FIRSTNAME); | ||
159 | managedUserVM.setLastName(DEFAULT_LASTNAME); | ||
160 | managedUserVM.setEmail(DEFAULT_EMAIL); | ||
161 | managedUserVM.setActivated(true); | ||
162 | managedUserVM.setImageUrl(DEFAULT_IMAGEURL); | ||
163 | managedUserVM.setLangKey(DEFAULT_LANGKEY); | ||
164 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
165 | |||
166 | // An entity with an existing ID cannot be created, so this API call must fail | ||
167 | restUserMockMvc.perform(post("/api/users") | ||
168 | .contentType(MediaType.APPLICATION_JSON) | ||
169 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
170 | .andExpect(status().isBadRequest()); | ||
171 | |||
172 | // Validate the User in the database | ||
173 | assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate)); | ||
174 | } | ||
175 | |||
176 | @Test | ||
177 | @Transactional | ||
178 | public void createUserWithExistingLogin() throws Exception { | ||
179 | // Initialize the database | ||
180 | userRepository.saveAndFlush(user); | ||
181 | int databaseSizeBeforeCreate = userRepository.findAll().size(); | ||
182 | |||
183 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
184 | managedUserVM.setLogin(DEFAULT_LOGIN);// this login should already be used | ||
185 | managedUserVM.setPassword(DEFAULT_PASSWORD); | ||
186 | managedUserVM.setFirstName(DEFAULT_FIRSTNAME); | ||
187 | managedUserVM.setLastName(DEFAULT_LASTNAME); | ||
188 | managedUserVM.setEmail("anothermail@localhost"); | ||
189 | managedUserVM.setActivated(true); | ||
190 | managedUserVM.setImageUrl(DEFAULT_IMAGEURL); | ||
191 | managedUserVM.setLangKey(DEFAULT_LANGKEY); | ||
192 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
193 | |||
194 | // Create the User | ||
195 | restUserMockMvc.perform(post("/api/users") | ||
196 | .contentType(MediaType.APPLICATION_JSON) | ||
197 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
198 | .andExpect(status().isBadRequest()); | ||
199 | |||
200 | // Validate the User in the database | ||
201 | assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate)); | ||
202 | } | ||
203 | |||
204 | @Test | ||
205 | @Transactional | ||
206 | public void createUserWithExistingEmail() throws Exception { | ||
207 | // Initialize the database | ||
208 | userRepository.saveAndFlush(user); | ||
209 | int databaseSizeBeforeCreate = userRepository.findAll().size(); | ||
210 | |||
211 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
212 | managedUserVM.setLogin("anotherlogin"); | ||
213 | managedUserVM.setPassword(DEFAULT_PASSWORD); | ||
214 | managedUserVM.setFirstName(DEFAULT_FIRSTNAME); | ||
215 | managedUserVM.setLastName(DEFAULT_LASTNAME); | ||
216 | managedUserVM.setEmail(DEFAULT_EMAIL);// this email should already be used | ||
217 | managedUserVM.setActivated(true); | ||
218 | managedUserVM.setImageUrl(DEFAULT_IMAGEURL); | ||
219 | managedUserVM.setLangKey(DEFAULT_LANGKEY); | ||
220 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
221 | |||
222 | // Create the User | ||
223 | restUserMockMvc.perform(post("/api/users") | ||
224 | .contentType(MediaType.APPLICATION_JSON) | ||
225 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
226 | .andExpect(status().isBadRequest()); | ||
227 | |||
228 | // Validate the User in the database | ||
229 | assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate)); | ||
230 | } | ||
231 | |||
232 | @Test | ||
233 | @Transactional | ||
234 | public void getAllUsers() throws Exception { | ||
235 | // Initialize the database | ||
236 | userRepository.saveAndFlush(user); | ||
237 | |||
238 | // Get all the users | ||
239 | restUserMockMvc.perform(get("/api/users?sort=id,desc") | ||
240 | .accept(MediaType.APPLICATION_JSON)) | ||
241 | .andExpect(status().isOk()) | ||
242 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
243 | .andExpect(jsonPath("$.[*].login").value(hasItem(DEFAULT_LOGIN))) | ||
244 | .andExpect(jsonPath("$.[*].firstName").value(hasItem(DEFAULT_FIRSTNAME))) | ||
245 | .andExpect(jsonPath("$.[*].lastName").value(hasItem(DEFAULT_LASTNAME))) | ||
246 | .andExpect(jsonPath("$.[*].email").value(hasItem(DEFAULT_EMAIL))) | ||
247 | .andExpect(jsonPath("$.[*].imageUrl").value(hasItem(DEFAULT_IMAGEURL))) | ||
248 | .andExpect(jsonPath("$.[*].langKey").value(hasItem(DEFAULT_LANGKEY))); | ||
249 | } | ||
250 | |||
251 | @Test | ||
252 | @Transactional | ||
253 | public void getUser() throws Exception { | ||
254 | // Initialize the database | ||
255 | userRepository.saveAndFlush(user); | ||
256 | |||
257 | assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin())).isNull(); | ||
258 | |||
259 | // Get the user | ||
260 | restUserMockMvc.perform(get("/api/users/{login}", user.getLogin())) | ||
261 | .andExpect(status().isOk()) | ||
262 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
263 | .andExpect(jsonPath("$.login").value(user.getLogin())) | ||
264 | .andExpect(jsonPath("$.firstName").value(DEFAULT_FIRSTNAME)) | ||
265 | .andExpect(jsonPath("$.lastName").value(DEFAULT_LASTNAME)) | ||
266 | .andExpect(jsonPath("$.email").value(DEFAULT_EMAIL)) | ||
267 | .andExpect(jsonPath("$.imageUrl").value(DEFAULT_IMAGEURL)) | ||
268 | .andExpect(jsonPath("$.langKey").value(DEFAULT_LANGKEY)); | ||
269 | |||
270 | assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin())).isNotNull(); | ||
271 | } | ||
272 | |||
273 | @Test | ||
274 | @Transactional | ||
275 | public void getNonExistingUser() throws Exception { | ||
276 | restUserMockMvc.perform(get("/api/users/unknown")) | ||
277 | .andExpect(status().isNotFound()); | ||
278 | } | ||
279 | |||
280 | @Test | ||
281 | @Transactional | ||
282 | public void updateUser() throws Exception { | ||
283 | // Initialize the database | ||
284 | userRepository.saveAndFlush(user); | ||
285 | int databaseSizeBeforeUpdate = userRepository.findAll().size(); | ||
286 | |||
287 | // Update the user | ||
288 | User updatedUser = userRepository.findById(user.getId()).get(); | ||
289 | |||
290 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
291 | managedUserVM.setId(updatedUser.getId()); | ||
292 | managedUserVM.setLogin(updatedUser.getLogin()); | ||
293 | managedUserVM.setPassword(UPDATED_PASSWORD); | ||
294 | managedUserVM.setFirstName(UPDATED_FIRSTNAME); | ||
295 | managedUserVM.setLastName(UPDATED_LASTNAME); | ||
296 | managedUserVM.setEmail(UPDATED_EMAIL); | ||
297 | managedUserVM.setActivated(updatedUser.getActivated()); | ||
298 | managedUserVM.setImageUrl(UPDATED_IMAGEURL); | ||
299 | managedUserVM.setLangKey(UPDATED_LANGKEY); | ||
300 | managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); | ||
301 | managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); | ||
302 | managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); | ||
303 | managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); | ||
304 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
305 | |||
306 | restUserMockMvc.perform(put("/api/users") | ||
307 | .contentType(MediaType.APPLICATION_JSON) | ||
308 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
309 | .andExpect(status().isOk()); | ||
310 | |||
311 | // Validate the User in the database | ||
312 | assertPersistedUsers(users -> { | ||
313 | assertThat(users).hasSize(databaseSizeBeforeUpdate); | ||
314 | User testUser = users.get(users.size() - 1); | ||
315 | assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME); | ||
316 | assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME); | ||
317 | assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL); | ||
318 | assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL); | ||
319 | assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY); | ||
320 | }); | ||
321 | } | ||
322 | |||
323 | @Test | ||
324 | @Transactional | ||
325 | public void updateUserLogin() throws Exception { | ||
326 | // Initialize the database | ||
327 | userRepository.saveAndFlush(user); | ||
328 | int databaseSizeBeforeUpdate = userRepository.findAll().size(); | ||
329 | |||
330 | // Update the user | ||
331 | User updatedUser = userRepository.findById(user.getId()).get(); | ||
332 | |||
333 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
334 | managedUserVM.setId(updatedUser.getId()); | ||
335 | managedUserVM.setLogin(UPDATED_LOGIN); | ||
336 | managedUserVM.setPassword(UPDATED_PASSWORD); | ||
337 | managedUserVM.setFirstName(UPDATED_FIRSTNAME); | ||
338 | managedUserVM.setLastName(UPDATED_LASTNAME); | ||
339 | managedUserVM.setEmail(UPDATED_EMAIL); | ||
340 | managedUserVM.setActivated(updatedUser.getActivated()); | ||
341 | managedUserVM.setImageUrl(UPDATED_IMAGEURL); | ||
342 | managedUserVM.setLangKey(UPDATED_LANGKEY); | ||
343 | managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); | ||
344 | managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); | ||
345 | managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); | ||
346 | managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); | ||
347 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
348 | |||
349 | restUserMockMvc.perform(put("/api/users") | ||
350 | .contentType(MediaType.APPLICATION_JSON) | ||
351 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
352 | .andExpect(status().isOk()); | ||
353 | |||
354 | // Validate the User in the database | ||
355 | assertPersistedUsers(users -> { | ||
356 | assertThat(users).hasSize(databaseSizeBeforeUpdate); | ||
357 | User testUser = users.get(users.size() - 1); | ||
358 | assertThat(testUser.getLogin()).isEqualTo(UPDATED_LOGIN); | ||
359 | assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME); | ||
360 | assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME); | ||
361 | assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL); | ||
362 | assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL); | ||
363 | assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY); | ||
364 | }); | ||
365 | } | ||
366 | |||
367 | @Test | ||
368 | @Transactional | ||
369 | public void updateUserExistingEmail() throws Exception { | ||
370 | // Initialize the database with 2 users | ||
371 | userRepository.saveAndFlush(user); | ||
372 | |||
373 | User anotherUser = new User(); | ||
374 | anotherUser.setLogin("jhipster"); | ||
375 | anotherUser.setPassword(RandomStringUtils.random(60)); | ||
376 | anotherUser.setActivated(true); | ||
377 | anotherUser.setEmail("jhipster@localhost"); | ||
378 | anotherUser.setFirstName("java"); | ||
379 | anotherUser.setLastName("hipster"); | ||
380 | anotherUser.setImageUrl(""); | ||
381 | anotherUser.setLangKey("en"); | ||
382 | userRepository.saveAndFlush(anotherUser); | ||
383 | |||
384 | // Update the user | ||
385 | User updatedUser = userRepository.findById(user.getId()).get(); | ||
386 | |||
387 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
388 | managedUserVM.setId(updatedUser.getId()); | ||
389 | managedUserVM.setLogin(updatedUser.getLogin()); | ||
390 | managedUserVM.setPassword(updatedUser.getPassword()); | ||
391 | managedUserVM.setFirstName(updatedUser.getFirstName()); | ||
392 | managedUserVM.setLastName(updatedUser.getLastName()); | ||
393 | managedUserVM.setEmail("jhipster@localhost");// this email should already be used by anotherUser | ||
394 | managedUserVM.setActivated(updatedUser.getActivated()); | ||
395 | managedUserVM.setImageUrl(updatedUser.getImageUrl()); | ||
396 | managedUserVM.setLangKey(updatedUser.getLangKey()); | ||
397 | managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); | ||
398 | managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); | ||
399 | managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); | ||
400 | managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); | ||
401 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
402 | |||
403 | restUserMockMvc.perform(put("/api/users") | ||
404 | .contentType(MediaType.APPLICATION_JSON) | ||
405 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
406 | .andExpect(status().isBadRequest()); | ||
407 | } | ||
408 | |||
409 | @Test | ||
410 | @Transactional | ||
411 | public void updateUserExistingLogin() throws Exception { | ||
412 | // Initialize the database | ||
413 | userRepository.saveAndFlush(user); | ||
414 | |||
415 | User anotherUser = new User(); | ||
416 | anotherUser.setLogin("jhipster"); | ||
417 | anotherUser.setPassword(RandomStringUtils.random(60)); | ||
418 | anotherUser.setActivated(true); | ||
419 | anotherUser.setEmail("jhipster@localhost"); | ||
420 | anotherUser.setFirstName("java"); | ||
421 | anotherUser.setLastName("hipster"); | ||
422 | anotherUser.setImageUrl(""); | ||
423 | anotherUser.setLangKey("en"); | ||
424 | userRepository.saveAndFlush(anotherUser); | ||
425 | |||
426 | // Update the user | ||
427 | User updatedUser = userRepository.findById(user.getId()).get(); | ||
428 | |||
429 | ManagedUserVM managedUserVM = new ManagedUserVM(); | ||
430 | managedUserVM.setId(updatedUser.getId()); | ||
431 | managedUserVM.setLogin("jhipster");// this login should already be used by anotherUser | ||
432 | managedUserVM.setPassword(updatedUser.getPassword()); | ||
433 | managedUserVM.setFirstName(updatedUser.getFirstName()); | ||
434 | managedUserVM.setLastName(updatedUser.getLastName()); | ||
435 | managedUserVM.setEmail(updatedUser.getEmail()); | ||
436 | managedUserVM.setActivated(updatedUser.getActivated()); | ||
437 | managedUserVM.setImageUrl(updatedUser.getImageUrl()); | ||
438 | managedUserVM.setLangKey(updatedUser.getLangKey()); | ||
439 | managedUserVM.setCreatedBy(updatedUser.getCreatedBy()); | ||
440 | managedUserVM.setCreatedDate(updatedUser.getCreatedDate()); | ||
441 | managedUserVM.setLastModifiedBy(updatedUser.getLastModifiedBy()); | ||
442 | managedUserVM.setLastModifiedDate(updatedUser.getLastModifiedDate()); | ||
443 | managedUserVM.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
444 | |||
445 | restUserMockMvc.perform(put("/api/users") | ||
446 | .contentType(MediaType.APPLICATION_JSON) | ||
447 | .content(TestUtil.convertObjectToJsonBytes(managedUserVM))) | ||
448 | .andExpect(status().isBadRequest()); | ||
449 | } | ||
450 | |||
451 | @Test | ||
452 | @Transactional | ||
453 | public void deleteUser() throws Exception { | ||
454 | // Initialize the database | ||
455 | userRepository.saveAndFlush(user); | ||
456 | int databaseSizeBeforeDelete = userRepository.findAll().size(); | ||
457 | |||
458 | // Delete the user | ||
459 | restUserMockMvc.perform(delete("/api/users/{login}", user.getLogin()) | ||
460 | .accept(MediaType.APPLICATION_JSON)) | ||
461 | .andExpect(status().isNoContent()); | ||
462 | |||
463 | assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin())).isNull(); | ||
464 | |||
465 | // Validate the database is empty | ||
466 | assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeDelete - 1)); | ||
467 | } | ||
468 | |||
469 | @Test | ||
470 | @Transactional | ||
471 | public void getAllAuthorities() throws Exception { | ||
472 | restUserMockMvc.perform(get("/api/users/authorities") | ||
473 | .accept(MediaType.APPLICATION_JSON) | ||
474 | .contentType(MediaType.APPLICATION_JSON)) | ||
475 | .andExpect(status().isOk()) | ||
476 | .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) | ||
477 | .andExpect(jsonPath("$").isArray()) | ||
478 | .andExpect(jsonPath("$").value(hasItems(AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN))); | ||
479 | } | ||
480 | |||
481 | @Test | ||
482 | @Transactional | ||
483 | public void testUserEquals() throws Exception { | ||
484 | TestUtil.equalsVerifier(User.class); | ||
485 | User user1 = new User(); | ||
486 | user1.setId(1L); | ||
487 | User user2 = new User(); | ||
488 | user2.setId(user1.getId()); | ||
489 | assertThat(user1).isEqualTo(user2); | ||
490 | user2.setId(2L); | ||
491 | assertThat(user1).isNotEqualTo(user2); | ||
492 | user1.setId(null); | ||
493 | assertThat(user1).isNotEqualTo(user2); | ||
494 | } | ||
495 | |||
496 | @Test | ||
497 | public void testUserDTOtoUser() { | ||
498 | UserDTO userDTO = new UserDTO(); | ||
499 | userDTO.setId(DEFAULT_ID); | ||
500 | userDTO.setLogin(DEFAULT_LOGIN); | ||
501 | userDTO.setFirstName(DEFAULT_FIRSTNAME); | ||
502 | userDTO.setLastName(DEFAULT_LASTNAME); | ||
503 | userDTO.setEmail(DEFAULT_EMAIL); | ||
504 | userDTO.setActivated(true); | ||
505 | userDTO.setImageUrl(DEFAULT_IMAGEURL); | ||
506 | userDTO.setLangKey(DEFAULT_LANGKEY); | ||
507 | userDTO.setCreatedBy(DEFAULT_LOGIN); | ||
508 | userDTO.setLastModifiedBy(DEFAULT_LOGIN); | ||
509 | userDTO.setAuthorities(Collections.singleton(AuthoritiesConstants.USER)); | ||
510 | |||
511 | User user = userMapper.userDTOToUser(userDTO); | ||
512 | assertThat(user.getId()).isEqualTo(DEFAULT_ID); | ||
513 | assertThat(user.getLogin()).isEqualTo(DEFAULT_LOGIN); | ||
514 | assertThat(user.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); | ||
515 | assertThat(user.getLastName()).isEqualTo(DEFAULT_LASTNAME); | ||
516 | assertThat(user.getEmail()).isEqualTo(DEFAULT_EMAIL); | ||
517 | assertThat(user.getActivated()).isEqualTo(true); | ||
518 | assertThat(user.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); | ||
519 | assertThat(user.getLangKey()).isEqualTo(DEFAULT_LANGKEY); | ||
520 | assertThat(user.getCreatedBy()).isNull(); | ||
521 | assertThat(user.getCreatedDate()).isNotNull(); | ||
522 | assertThat(user.getLastModifiedBy()).isNull(); | ||
523 | assertThat(user.getLastModifiedDate()).isNotNull(); | ||
524 | assertThat(user.getAuthorities()).extracting("name").containsExactly(AuthoritiesConstants.USER); | ||
525 | } | ||
526 | |||
527 | @Test | ||
528 | public void testUserToUserDTO() { | ||
529 | user.setId(DEFAULT_ID); | ||
530 | user.setCreatedBy(DEFAULT_LOGIN); | ||
531 | user.setCreatedDate(Instant.now()); | ||
532 | user.setLastModifiedBy(DEFAULT_LOGIN); | ||
533 | user.setLastModifiedDate(Instant.now()); | ||
534 | Set<Authority> authorities = new HashSet<>(); | ||
535 | Authority authority = new Authority(); | ||
536 | authority.setName(AuthoritiesConstants.USER); | ||
537 | authorities.add(authority); | ||
538 | user.setAuthorities(authorities); | ||
539 | |||
540 | UserDTO userDTO = userMapper.userToUserDTO(user); | ||
541 | |||
542 | assertThat(userDTO.getId()).isEqualTo(DEFAULT_ID); | ||
543 | assertThat(userDTO.getLogin()).isEqualTo(DEFAULT_LOGIN); | ||
544 | assertThat(userDTO.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME); | ||
545 | assertThat(userDTO.getLastName()).isEqualTo(DEFAULT_LASTNAME); | ||
546 | assertThat(userDTO.getEmail()).isEqualTo(DEFAULT_EMAIL); | ||
547 | assertThat(userDTO.isActivated()).isEqualTo(true); | ||
548 | assertThat(userDTO.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL); | ||
549 | assertThat(userDTO.getLangKey()).isEqualTo(DEFAULT_LANGKEY); | ||
550 | assertThat(userDTO.getCreatedBy()).isEqualTo(DEFAULT_LOGIN); | ||
551 | assertThat(userDTO.getCreatedDate()).isEqualTo(user.getCreatedDate()); | ||
552 | assertThat(userDTO.getLastModifiedBy()).isEqualTo(DEFAULT_LOGIN); | ||
553 | assertThat(userDTO.getLastModifiedDate()).isEqualTo(user.getLastModifiedDate()); | ||
554 | assertThat(userDTO.getAuthorities()).containsExactly(AuthoritiesConstants.USER); | ||
555 | assertThat(userDTO.toString()).isNotNull(); | ||
556 | } | ||
557 | |||
558 | @Test | ||
559 | public void testAuthorityEquals() { | ||
560 | Authority authorityA = new Authority(); | ||
561 | assertThat(authorityA).isEqualTo(authorityA); | ||
562 | assertThat(authorityA).isNotEqualTo(null); | ||
563 | assertThat(authorityA).isNotEqualTo(new Object()); | ||
564 | assertThat(authorityA.hashCode()).isEqualTo(0); | ||
565 | assertThat(authorityA.toString()).isNotNull(); | ||
566 | |||
567 | Authority authorityB = new Authority(); | ||
568 | assertThat(authorityA).isEqualTo(authorityB); | ||
569 | |||
570 | authorityB.setName(AuthoritiesConstants.ADMIN); | ||
571 | assertThat(authorityA).isNotEqualTo(authorityB); | ||
572 | |||
573 | authorityA.setName(AuthoritiesConstants.USER); | ||
574 | assertThat(authorityA).isNotEqualTo(authorityB); | ||
575 | |||
576 | authorityB.setName(AuthoritiesConstants.USER); | ||
577 | assertThat(authorityA).isEqualTo(authorityB); | ||
578 | assertThat(authorityA.hashCode()).isEqualTo(authorityB.hashCode()); | ||
579 | } | ||
580 | |||
581 | private void assertPersistedUsers(Consumer<List<User>> userAssertion) { | ||
582 | userAssertion.accept(userRepository.findAll()); | ||
583 | } | ||
584 | } |
File src/test/java/hu/dns/honlap/web/rest/WithUnauthenticatedMockUser.java added (mode: 100644) (index 0000000..6f2fc7c) | |||
1 | package hu.dns.honlap.web.rest; | ||
2 | |||
3 | import org.springframework.security.core.context.SecurityContext; | ||
4 | import org.springframework.security.core.context.SecurityContextHolder; | ||
5 | import org.springframework.security.test.context.support.WithSecurityContext; | ||
6 | import org.springframework.security.test.context.support.WithSecurityContextFactory; | ||
7 | |||
8 | import java.lang.annotation.ElementType; | ||
9 | import java.lang.annotation.Retention; | ||
10 | import java.lang.annotation.RetentionPolicy; | ||
11 | import java.lang.annotation.Target; | ||
12 | |||
13 | @Target({ElementType.METHOD, ElementType.TYPE}) | ||
14 | @Retention(RetentionPolicy.RUNTIME) | ||
15 | @WithSecurityContext(factory = WithUnauthenticatedMockUser.Factory.class) | ||
16 | public @interface WithUnauthenticatedMockUser { | ||
17 | |||
18 | class Factory implements WithSecurityContextFactory<WithUnauthenticatedMockUser> { | ||
19 | @Override | ||
20 | public SecurityContext createSecurityContext(WithUnauthenticatedMockUser annotation) { | ||
21 | return SecurityContextHolder.createEmptyContext(); | ||
22 | } | ||
23 | } | ||
24 | } |
File src/test/java/hu/dns/honlap/web/rest/errors/ExceptionTranslatorIT.java added (mode: 100644) (index 0000000..52ee83b) | |||
1 | package hu.dns.honlap.web.rest.errors; | ||
2 | |||
3 | import hu.dns.honlap.HonlapApp; | ||
4 | import org.junit.jupiter.api.Test; | ||
5 | import org.springframework.beans.factory.annotation.Autowired; | ||
6 | import org.springframework.boot.test.context.SpringBootTest; | ||
7 | import org.springframework.security.test.context.support.WithMockUser; | ||
8 | import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; | ||
9 | import org.springframework.http.MediaType; | ||
10 | import org.springframework.test.web.servlet.MockMvc; | ||
11 | |||
12 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get; | ||
13 | import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; | ||
14 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; | ||
15 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; | ||
16 | import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; | ||
17 | |||
18 | /** | ||
19 | * Integration tests {@link ExceptionTranslator} controller advice. | ||
20 | */ | ||
21 | @WithMockUser | ||
22 | @AutoConfigureMockMvc | ||
23 | @SpringBootTest(classes = HonlapApp.class) | ||
24 | public class ExceptionTranslatorIT { | ||
25 | |||
26 | @Autowired | ||
27 | private MockMvc mockMvc; | ||
28 | |||
29 | @Test | ||
30 | public void testConcurrencyFailure() throws Exception { | ||
31 | mockMvc.perform(get("/api/exception-translator-test/concurrency-failure")) | ||
32 | .andExpect(status().isConflict()) | ||
33 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
34 | .andExpect(jsonPath("$.message").value(ErrorConstants.ERR_CONCURRENCY_FAILURE)); | ||
35 | } | ||
36 | |||
37 | @Test | ||
38 | public void testMethodArgumentNotValid() throws Exception { | ||
39 | mockMvc.perform(post("/api/exception-translator-test/method-argument").content("{}").contentType(MediaType.APPLICATION_JSON)) | ||
40 | .andExpect(status().isBadRequest()) | ||
41 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
42 | .andExpect(jsonPath("$.message").value(ErrorConstants.ERR_VALIDATION)) | ||
43 | .andExpect(jsonPath("$.fieldErrors.[0].objectName").value("test")) | ||
44 | .andExpect(jsonPath("$.fieldErrors.[0].field").value("test")) | ||
45 | .andExpect(jsonPath("$.fieldErrors.[0].message").value("NotNull")); | ||
46 | } | ||
47 | |||
48 | @Test | ||
49 | public void testMissingServletRequestPartException() throws Exception { | ||
50 | mockMvc.perform(get("/api/exception-translator-test/missing-servlet-request-part")) | ||
51 | .andExpect(status().isBadRequest()) | ||
52 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
53 | .andExpect(jsonPath("$.message").value("error.http.400")); | ||
54 | } | ||
55 | |||
56 | @Test | ||
57 | public void testMissingServletRequestParameterException() throws Exception { | ||
58 | mockMvc.perform(get("/api/exception-translator-test/missing-servlet-request-parameter")) | ||
59 | .andExpect(status().isBadRequest()) | ||
60 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
61 | .andExpect(jsonPath("$.message").value("error.http.400")); | ||
62 | } | ||
63 | |||
64 | @Test | ||
65 | public void testAccessDenied() throws Exception { | ||
66 | mockMvc.perform(get("/api/exception-translator-test/access-denied")) | ||
67 | .andExpect(status().isForbidden()) | ||
68 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
69 | .andExpect(jsonPath("$.message").value("error.http.403")) | ||
70 | .andExpect(jsonPath("$.detail").value("test access denied!")); | ||
71 | } | ||
72 | |||
73 | @Test | ||
74 | public void testUnauthorized() throws Exception { | ||
75 | mockMvc.perform(get("/api/exception-translator-test/unauthorized")) | ||
76 | .andExpect(status().isUnauthorized()) | ||
77 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
78 | .andExpect(jsonPath("$.message").value("error.http.401")) | ||
79 | .andExpect(jsonPath("$.path").value("/api/exception-translator-test/unauthorized")) | ||
80 | .andExpect(jsonPath("$.detail").value("test authentication failed!")); | ||
81 | } | ||
82 | |||
83 | @Test | ||
84 | public void testMethodNotSupported() throws Exception { | ||
85 | mockMvc.perform(post("/api/exception-translator-test/access-denied")) | ||
86 | .andExpect(status().isMethodNotAllowed()) | ||
87 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
88 | .andExpect(jsonPath("$.message").value("error.http.405")) | ||
89 | .andExpect(jsonPath("$.detail").value("Request method 'POST' not supported")); | ||
90 | } | ||
91 | |||
92 | @Test | ||
93 | public void testExceptionWithResponseStatus() throws Exception { | ||
94 | mockMvc.perform(get("/api/exception-translator-test/response-status")) | ||
95 | .andExpect(status().isBadRequest()) | ||
96 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
97 | .andExpect(jsonPath("$.message").value("error.http.400")) | ||
98 | .andExpect(jsonPath("$.title").value("test response status")); | ||
99 | } | ||
100 | |||
101 | @Test | ||
102 | public void testInternalServerError() throws Exception { | ||
103 | mockMvc.perform(get("/api/exception-translator-test/internal-server-error")) | ||
104 | .andExpect(status().isInternalServerError()) | ||
105 | .andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON)) | ||
106 | .andExpect(jsonPath("$.message").value("error.http.500")) | ||
107 | .andExpect(jsonPath("$.title").value("Internal Server Error")); | ||
108 | } | ||
109 | |||
110 | } |
File src/test/java/hu/dns/honlap/web/rest/errors/ExceptionTranslatorTestController.java added (mode: 100644) (index 0000000..5331e52) | |||
1 | package hu.dns.honlap.web.rest.errors; | ||
2 | |||
3 | import org.springframework.dao.ConcurrencyFailureException; | ||
4 | import org.springframework.http.HttpStatus; | ||
5 | import org.springframework.security.access.AccessDeniedException; | ||
6 | import org.springframework.security.authentication.BadCredentialsException; | ||
7 | import org.springframework.web.bind.annotation.*; | ||
8 | |||
9 | import javax.validation.Valid; | ||
10 | import javax.validation.constraints.NotNull; | ||
11 | |||
12 | @RestController | ||
13 | @RequestMapping("/api/exception-translator-test") | ||
14 | public class ExceptionTranslatorTestController { | ||
15 | |||
16 | @GetMapping("/concurrency-failure") | ||
17 | public void concurrencyFailure() { | ||
18 | throw new ConcurrencyFailureException("test concurrency failure"); | ||
19 | } | ||
20 | |||
21 | @PostMapping("/method-argument") | ||
22 | public void methodArgument(@Valid @RequestBody TestDTO testDTO) { | ||
23 | } | ||
24 | |||
25 | @GetMapping("/missing-servlet-request-part") | ||
26 | public void missingServletRequestPartException(@RequestPart String part) { | ||
27 | } | ||
28 | |||
29 | @GetMapping("/missing-servlet-request-parameter") | ||
30 | public void missingServletRequestParameterException(@RequestParam String param) { | ||
31 | } | ||
32 | |||
33 | @GetMapping("/access-denied") | ||
34 | public void accessdenied() { | ||
35 | throw new AccessDeniedException("test access denied!"); | ||
36 | } | ||
37 | |||
38 | @GetMapping("/unauthorized") | ||
39 | public void unauthorized() { | ||
40 | throw new BadCredentialsException("test authentication failed!"); | ||
41 | } | ||
42 | |||
43 | @GetMapping("/response-status") | ||
44 | public void exceptionWithResponseStatus() { | ||
45 | throw new TestResponseStatusException(); | ||
46 | } | ||
47 | |||
48 | @GetMapping("/internal-server-error") | ||
49 | public void internalServerError() { | ||
50 | throw new RuntimeException(); | ||
51 | } | ||
52 | |||
53 | public static class TestDTO { | ||
54 | |||
55 | @NotNull | ||
56 | private String test; | ||
57 | |||
58 | public String getTest() { | ||
59 | return test; | ||
60 | } | ||
61 | |||
62 | public void setTest(String test) { | ||
63 | this.test = test; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | @ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "test response status") | ||
68 | @SuppressWarnings("serial") | ||
69 | public static class TestResponseStatusException extends RuntimeException { | ||
70 | } | ||
71 | |||
72 | } |
File src/test/javascript/e2e/account/account.spec.ts added (mode: 100644) (index 0000000..a16236b) | |||
1 | import { browser, element, by, ExpectedConditions as ec } from 'protractor'; | ||
2 | |||
3 | import { NavBarPage, SignInPage, PasswordPage, SettingsPage } from '../page-objects/jhi-page-objects'; | ||
4 | |||
5 | const expect = chai.expect; | ||
6 | |||
7 | describe('account', () => { | ||
8 | let navBarPage: NavBarPage; | ||
9 | let signInPage: SignInPage; | ||
10 | let passwordPage: PasswordPage; | ||
11 | let settingsPage: SettingsPage; | ||
12 | |||
13 | before(async () => { | ||
14 | await browser.get('/'); | ||
15 | navBarPage = new NavBarPage(true); | ||
16 | }); | ||
17 | |||
18 | it('should fail to login with bad password', async () => { | ||
19 | const expect1 = 'home.title'; | ||
20 | const value1 = await element(by.css('h1')).getAttribute('jhiTranslate'); | ||
21 | expect(value1).to.eq(expect1); | ||
22 | signInPage = await navBarPage.getSignInPage(); | ||
23 | await signInPage.autoSignInUsing('admin', 'foo'); | ||
24 | |||
25 | const expect2 = 'login.messages.error.authentication'; | ||
26 | const value2 = await element(by.css('.alert-danger')).getAttribute('jhiTranslate'); | ||
27 | expect(value2).to.eq(expect2); | ||
28 | }); | ||
29 | |||
30 | it('should login successfully with admin account', async () => { | ||
31 | await browser.get('/'); | ||
32 | signInPage = await navBarPage.getSignInPage(); | ||
33 | |||
34 | const expect1 = 'global.form.username.label'; | ||
35 | const value1 = await element(by.className('username-label')).getAttribute('jhiTranslate'); | ||
36 | expect(value1).to.eq(expect1); | ||
37 | await signInPage.autoSignInUsing('admin', 'admin'); | ||
38 | |||
39 | const expect2 = 'home.logged.message'; | ||
40 | await browser.wait(ec.visibilityOf(element(by.id('home-logged-message')))); | ||
41 | const value2 = await element(by.id('home-logged-message')).getAttribute('jhiTranslate'); | ||
42 | expect(value2).to.eq(expect2); | ||
43 | }); | ||
44 | |||
45 | it('should be able to update settings', async () => { | ||
46 | settingsPage = await navBarPage.getSettingsPage(); | ||
47 | |||
48 | const expect1 = 'settings.title'; | ||
49 | const value1 = await settingsPage.getTitle(); | ||
50 | expect(value1).to.eq(expect1); | ||
51 | await settingsPage.save(); | ||
52 | |||
53 | const expect2 = 'settings.messages.success'; | ||
54 | const alert = element(by.css('.alert-success')); | ||
55 | const value2 = await alert.getAttribute('jhiTranslate'); | ||
56 | expect(value2).to.eq(expect2); | ||
57 | }); | ||
58 | |||
59 | it('should fail to update password when using incorrect current password', async () => { | ||
60 | passwordPage = await navBarPage.getPasswordPage(); | ||
61 | |||
62 | expect(await passwordPage.getTitle()).to.eq('password.title'); | ||
63 | |||
64 | await passwordPage.setCurrentPassword('wrong_current_password'); | ||
65 | await passwordPage.setPassword('new_password'); | ||
66 | await passwordPage.setConfirmPassword('new_password'); | ||
67 | await passwordPage.save(); | ||
68 | |||
69 | const expect2 = 'password.messages.error'; | ||
70 | const alert = element(by.css('.alert-danger')); | ||
71 | const value2 = await alert.getAttribute('jhiTranslate'); | ||
72 | expect(value2).to.eq(expect2); | ||
73 | settingsPage = await navBarPage.getSettingsPage(); | ||
74 | }); | ||
75 | |||
76 | it('should be able to update password', async () => { | ||
77 | passwordPage = await navBarPage.getPasswordPage(); | ||
78 | |||
79 | expect(await passwordPage.getTitle()).to.eq('password.title'); | ||
80 | |||
81 | await passwordPage.setCurrentPassword('admin'); | ||
82 | await passwordPage.setPassword('newpassword'); | ||
83 | await passwordPage.setConfirmPassword('newpassword'); | ||
84 | await passwordPage.save(); | ||
85 | |||
86 | const successMsg = 'password.messages.success'; | ||
87 | const alert = element(by.css('.alert-success')); | ||
88 | const alertValue = await alert.getAttribute('jhiTranslate'); | ||
89 | expect(alertValue).to.eq(successMsg); | ||
90 | await navBarPage.autoSignOut(); | ||
91 | await navBarPage.goToSignInPage(); | ||
92 | await signInPage.autoSignInUsing('admin', 'newpassword'); | ||
93 | |||
94 | // change back to default | ||
95 | await navBarPage.goToPasswordMenu(); | ||
96 | await passwordPage.setCurrentPassword('newpassword'); | ||
97 | await passwordPage.setPassword('admin'); | ||
98 | await passwordPage.setConfirmPassword('admin'); | ||
99 | await passwordPage.save(); | ||
100 | |||
101 | // wait for success message | ||
102 | const alertValue2 = await alert.getAttribute('jhiTranslate'); | ||
103 | expect(alertValue2).to.eq(successMsg); | ||
104 | }); | ||
105 | |||
106 | it('should navigate to 404 not found error page on non existing route and show user own navbar if valid authentication exists', async () => { | ||
107 | // don't sign out and refresh page with non existing route | ||
108 | await browser.get('/this-is-link-to-non-existing-page'); | ||
109 | |||
110 | // should navigate to 404 not found page | ||
111 | const url = await browser.getCurrentUrl(); | ||
112 | expect(url).to.endWith('404'); | ||
113 | |||
114 | // as user is admin then should show admin menu to user | ||
115 | await navBarPage.clickOnAdminMenu(); | ||
116 | }); | ||
117 | |||
118 | after(async () => { | ||
119 | await navBarPage.autoSignOut(); | ||
120 | }); | ||
121 | }); |
File src/test/javascript/e2e/admin/administration.spec.ts added (mode: 100644) (index 0000000..5a65663) | |||
1 | import { browser, element, by, ExpectedConditions as ec } from 'protractor'; | ||
2 | |||
3 | import { NavBarPage, SignInPage } from '../page-objects/jhi-page-objects'; | ||
4 | |||
5 | const expect = chai.expect; | ||
6 | |||
7 | describe('administration', () => { | ||
8 | let navBarPage: NavBarPage; | ||
9 | let signInPage: SignInPage; | ||
10 | |||
11 | before(async () => { | ||
12 | await browser.get('/'); | ||
13 | navBarPage = new NavBarPage(true); | ||
14 | signInPage = await navBarPage.getSignInPage(); | ||
15 | await signInPage.autoSignInUsing('admin', 'admin'); | ||
16 | await browser.wait(ec.visibilityOf(navBarPage.adminMenu), 5000); | ||
17 | }); | ||
18 | |||
19 | beforeEach(async () => { | ||
20 | await navBarPage.clickOnAdminMenu(); | ||
21 | }); | ||
22 | |||
23 | it('should load user management', async () => { | ||
24 | await navBarPage.clickOnAdmin('user-management'); | ||
25 | const expect1 = 'userManagement.home.title'; | ||
26 | const value1 = await element(by.id('user-management-page-heading')).getAttribute('jhiTranslate'); | ||
27 | expect(value1).to.eq(expect1); | ||
28 | }); | ||
29 | |||
30 | it('should load metrics', async () => { | ||
31 | await navBarPage.clickOnAdmin('metrics'); | ||
32 | const expect1 = 'metrics.title'; | ||
33 | const value1 = await element(by.id('metrics-page-heading')).getAttribute('jhiTranslate'); | ||
34 | expect(value1).to.eq(expect1); | ||
35 | }); | ||
36 | |||
37 | it('should load health', async () => { | ||
38 | await navBarPage.clickOnAdmin('health'); | ||
39 | const expect1 = 'health.title'; | ||
40 | const value1 = await element(by.id('health-page-heading')).getAttribute('jhiTranslate'); | ||
41 | expect(value1).to.eq(expect1); | ||
42 | }); | ||
43 | |||
44 | it('should load configuration', async () => { | ||
45 | await navBarPage.clickOnAdmin('configuration'); | ||
46 | await browser.sleep(500); | ||
47 | const expect1 = 'configuration.title'; | ||
48 | const value1 = await element(by.id('configuration-page-heading')).getAttribute('jhiTranslate'); | ||
49 | expect(value1).to.eq(expect1); | ||
50 | }); | ||
51 | |||
52 | it('should load audits', async () => { | ||
53 | await navBarPage.clickOnAdmin('audits'); | ||
54 | await browser.sleep(500); | ||
55 | const expect1 = 'audits.title'; | ||
56 | const value1 = await element(by.id('audits-page-heading')).getAttribute('jhiTranslate'); | ||
57 | expect(value1).to.eq(expect1); | ||
58 | }); | ||
59 | |||
60 | it('should load logs', async () => { | ||
61 | await navBarPage.clickOnAdmin('logs'); | ||
62 | await browser.sleep(500); | ||
63 | const expect1 = 'logs.title'; | ||
64 | const value1 = await element(by.id('logs-page-heading')).getAttribute('jhiTranslate'); | ||
65 | expect(value1).to.eq(expect1); | ||
66 | }); | ||
67 | |||
68 | after(async () => { | ||
69 | await navBarPage.autoSignOut(); | ||
70 | }); | ||
71 | }); |
File src/test/javascript/e2e/entities/piece-of-news/piece-of-news.page-object.ts added (mode: 100644) (index 0000000..3695094) | |||
1 | import { element, by, ElementFinder } from 'protractor'; | ||
2 | |||
3 | export class PieceOfNewsComponentsPage { | ||
4 | createButton = element(by.id('jh-create-entity')); | ||
5 | deleteButtons = element.all(by.css('auth-piece-of-news div table .btn-danger')); | ||
6 | title = element.all(by.css('auth-piece-of-news div h2#page-heading span')).first(); | ||
7 | noResult = element(by.id('no-result')); | ||
8 | entities = element(by.id('entities')); | ||
9 | |||
10 | async clickOnCreateButton(): Promise<void> { | ||
11 | await this.createButton.click(); | ||
12 | } | ||
13 | |||
14 | async clickOnLastDeleteButton(): Promise<void> { | ||
15 | await this.deleteButtons.last().click(); | ||
16 | } | ||
17 | |||
18 | async countDeleteButtons(): Promise<number> { | ||
19 | return this.deleteButtons.count(); | ||
20 | } | ||
21 | |||
22 | async getTitle(): Promise<string> { | ||
23 | return this.title.getAttribute('jhiTranslate'); | ||
24 | } | ||
25 | } | ||
26 | |||
27 | export class PieceOfNewsUpdatePage { | ||
28 | pageTitle = element(by.id('auth-piece-of-news-heading')); | ||
29 | saveButton = element(by.id('save-entity')); | ||
30 | cancelButton = element(by.id('cancel-save')); | ||
31 | |||
32 | appIdInput = element(by.id('field_appId')); | ||
33 | newsDateInput = element(by.id('field_newsDate')); | ||
34 | headlineInput = element(by.id('field_headline')); | ||
35 | contentInput = element(by.id('field_content')); | ||
36 | linkInput = element(by.id('field_link')); | ||
37 | publishDateInput = element(by.id('field_publishDate')); | ||
38 | createdByInput = element(by.id('field_createdBy')); | ||
39 | createdDateInput = element(by.id('field_createdDate')); | ||
40 | lastModifiedByInput = element(by.id('field_lastModifiedBy')); | ||
41 | lastModifiedDateInput = element(by.id('field_lastModifiedDate')); | ||
42 | |||
43 | async getPageTitle(): Promise<string> { | ||
44 | return this.pageTitle.getAttribute('jhiTranslate'); | ||
45 | } | ||
46 | |||
47 | async setAppIdInput(appId: string): Promise<void> { | ||
48 | await this.appIdInput.sendKeys(appId); | ||
49 | } | ||
50 | |||
51 | async getAppIdInput(): Promise<string> { | ||
52 | return await this.appIdInput.getAttribute('value'); | ||
53 | } | ||
54 | |||
55 | async setNewsDateInput(newsDate: string): Promise<void> { | ||
56 | await this.newsDateInput.sendKeys(newsDate); | ||
57 | } | ||
58 | |||
59 | async getNewsDateInput(): Promise<string> { | ||
60 | return await this.newsDateInput.getAttribute('value'); | ||
61 | } | ||
62 | |||
63 | async setHeadlineInput(headline: string): Promise<void> { | ||
64 | await this.headlineInput.sendKeys(headline); | ||
65 | } | ||
66 | |||
67 | async getHeadlineInput(): Promise<string> { | ||
68 | return await this.headlineInput.getAttribute('value'); | ||
69 | } | ||
70 | |||
71 | async setContentInput(content: string): Promise<void> { | ||
72 | await this.contentInput.sendKeys(content); | ||
73 | } | ||
74 | |||
75 | async getContentInput(): Promise<string> { | ||
76 | return await this.contentInput.getAttribute('value'); | ||
77 | } | ||
78 | |||
79 | async setLinkInput(link: string): Promise<void> { | ||
80 | await this.linkInput.sendKeys(link); | ||
81 | } | ||
82 | |||
83 | async getLinkInput(): Promise<string> { | ||
84 | return await this.linkInput.getAttribute('value'); | ||
85 | } | ||
86 | |||
87 | async setPublishDateInput(publishDate: string): Promise<void> { | ||
88 | await this.publishDateInput.sendKeys(publishDate); | ||
89 | } | ||
90 | |||
91 | async getPublishDateInput(): Promise<string> { | ||
92 | return await this.publishDateInput.getAttribute('value'); | ||
93 | } | ||
94 | |||
95 | async setCreatedByInput(createdBy: string): Promise<void> { | ||
96 | await this.createdByInput.sendKeys(createdBy); | ||
97 | } | ||
98 | |||
99 | async getCreatedByInput(): Promise<string> { | ||
100 | return await this.createdByInput.getAttribute('value'); | ||
101 | } | ||
102 | |||
103 | async setCreatedDateInput(createdDate: string): Promise<void> { | ||
104 | await this.createdDateInput.sendKeys(createdDate); | ||
105 | } | ||
106 | |||
107 | async getCreatedDateInput(): Promise<string> { | ||
108 | return await this.createdDateInput.getAttribute('value'); | ||
109 | } | ||
110 | |||
111 | async setLastModifiedByInput(lastModifiedBy: string): Promise<void> { | ||
112 | await this.lastModifiedByInput.sendKeys(lastModifiedBy); | ||
113 | } | ||
114 | |||
115 | async getLastModifiedByInput(): Promise<string> { | ||
116 | return await this.lastModifiedByInput.getAttribute('value'); | ||
117 | } | ||
118 | |||
119 | async setLastModifiedDateInput(lastModifiedDate: string): Promise<void> { | ||
120 | await this.lastModifiedDateInput.sendKeys(lastModifiedDate); | ||
121 | } | ||
122 | |||
123 | async getLastModifiedDateInput(): Promise<string> { | ||
124 | return await this.lastModifiedDateInput.getAttribute('value'); | ||
125 | } | ||
126 | |||
127 | async save(): Promise<void> { | ||
128 | await this.saveButton.click(); | ||
129 | } | ||
130 | |||
131 | async cancel(): Promise<void> { | ||
132 | await this.cancelButton.click(); | ||
133 | } | ||
134 | |||
135 | getSaveButton(): ElementFinder { | ||
136 | return this.saveButton; | ||
137 | } | ||
138 | } | ||
139 | |||
140 | export class PieceOfNewsDeleteDialog { | ||
141 | private dialogTitle = element(by.id('auth-delete-pieceOfNews-heading')); | ||
142 | private confirmButton = element(by.id('auth-confirm-delete-pieceOfNews')); | ||
143 | |||
144 | async getDialogTitle(): Promise<string> { | ||
145 | return this.dialogTitle.getAttribute('jhiTranslate'); | ||
146 | } | ||
147 | |||
148 | async clickOnConfirmButton(): Promise<void> { | ||
149 | await this.confirmButton.click(); | ||
150 | } | ||
151 | } |
File src/test/javascript/e2e/entities/piece-of-news/piece-of-news.spec.ts added (mode: 100644) (index 0000000..81f32d7) | |||
1 | import { browser, ExpectedConditions as ec, protractor, promise } from 'protractor'; | ||
2 | import { NavBarPage, SignInPage } from '../../page-objects/jhi-page-objects'; | ||
3 | |||
4 | import { PieceOfNewsComponentsPage, PieceOfNewsDeleteDialog, PieceOfNewsUpdatePage } from './piece-of-news.page-object'; | ||
5 | |||
6 | const expect = chai.expect; | ||
7 | |||
8 | describe('PieceOfNews e2e test', () => { | ||
9 | let navBarPage: NavBarPage; | ||
10 | let signInPage: SignInPage; | ||
11 | let pieceOfNewsComponentsPage: PieceOfNewsComponentsPage; | ||
12 | let pieceOfNewsUpdatePage: PieceOfNewsUpdatePage; | ||
13 | let pieceOfNewsDeleteDialog: PieceOfNewsDeleteDialog; | ||
14 | |||
15 | before(async () => { | ||
16 | await browser.get('/'); | ||
17 | navBarPage = new NavBarPage(); | ||
18 | signInPage = await navBarPage.getSignInPage(); | ||
19 | await signInPage.autoSignInUsing('admin', 'admin'); | ||
20 | await browser.wait(ec.visibilityOf(navBarPage.entityMenu), 5000); | ||
21 | }); | ||
22 | |||
23 | it('should load PieceOfNews', async () => { | ||
24 | await navBarPage.goToEntity('piece-of-news'); | ||
25 | pieceOfNewsComponentsPage = new PieceOfNewsComponentsPage(); | ||
26 | await browser.wait(ec.visibilityOf(pieceOfNewsComponentsPage.title), 5000); | ||
27 | expect(await pieceOfNewsComponentsPage.getTitle()).to.eq('honlapApp.pieceOfNews.home.title'); | ||
28 | await browser.wait( | ||
29 | ec.or(ec.visibilityOf(pieceOfNewsComponentsPage.entities), ec.visibilityOf(pieceOfNewsComponentsPage.noResult)), | ||
30 | 1000 | ||
31 | ); | ||
32 | }); | ||
33 | |||
34 | it('should load create PieceOfNews page', async () => { | ||
35 | await pieceOfNewsComponentsPage.clickOnCreateButton(); | ||
36 | pieceOfNewsUpdatePage = new PieceOfNewsUpdatePage(); | ||
37 | expect(await pieceOfNewsUpdatePage.getPageTitle()).to.eq('honlapApp.pieceOfNews.home.createOrEditLabel'); | ||
38 | await pieceOfNewsUpdatePage.cancel(); | ||
39 | }); | ||
40 | |||
41 | it('should create and save PieceOfNews', async () => { | ||
42 | const nbButtonsBeforeCreate = await pieceOfNewsComponentsPage.countDeleteButtons(); | ||
43 | |||
44 | await pieceOfNewsComponentsPage.clickOnCreateButton(); | ||
45 | |||
46 | await promise.all([ | ||
47 | pieceOfNewsUpdatePage.setAppIdInput('5'), | ||
48 | pieceOfNewsUpdatePage.setNewsDateInput('01/01/2001' + protractor.Key.TAB + '02:30AM'), | ||
49 | pieceOfNewsUpdatePage.setHeadlineInput('headline'), | ||
50 | pieceOfNewsUpdatePage.setContentInput('content'), | ||
51 | pieceOfNewsUpdatePage.setLinkInput('link'), | ||
52 | pieceOfNewsUpdatePage.setPublishDateInput('01/01/2001' + protractor.Key.TAB + '02:30AM'), | ||
53 | pieceOfNewsUpdatePage.setCreatedByInput('createdBy'), | ||
54 | pieceOfNewsUpdatePage.setCreatedDateInput('01/01/2001' + protractor.Key.TAB + '02:30AM'), | ||
55 | pieceOfNewsUpdatePage.setLastModifiedByInput('lastModifiedBy'), | ||
56 | pieceOfNewsUpdatePage.setLastModifiedDateInput('01/01/2001' + protractor.Key.TAB + '02:30AM') | ||
57 | ]); | ||
58 | |||
59 | expect(await pieceOfNewsUpdatePage.getAppIdInput()).to.eq('5', 'Expected appId value to be equals to 5'); | ||
60 | expect(await pieceOfNewsUpdatePage.getNewsDateInput()).to.contain( | ||
61 | '2001-01-01T02:30', | ||
62 | 'Expected newsDate value to be equals to 2000-12-31' | ||
63 | ); | ||
64 | expect(await pieceOfNewsUpdatePage.getHeadlineInput()).to.eq('headline', 'Expected Headline value to be equals to headline'); | ||
65 | expect(await pieceOfNewsUpdatePage.getContentInput()).to.eq('content', 'Expected Content value to be equals to content'); | ||
66 | expect(await pieceOfNewsUpdatePage.getLinkInput()).to.eq('link', 'Expected Link value to be equals to link'); | ||
67 | expect(await pieceOfNewsUpdatePage.getPublishDateInput()).to.contain( | ||
68 | '2001-01-01T02:30', | ||
69 | 'Expected publishDate value to be equals to 2000-12-31' | ||
70 | ); | ||
71 | expect(await pieceOfNewsUpdatePage.getCreatedByInput()).to.eq('createdBy', 'Expected CreatedBy value to be equals to createdBy'); | ||
72 | expect(await pieceOfNewsUpdatePage.getCreatedDateInput()).to.contain( | ||
73 | '2001-01-01T02:30', | ||
74 | 'Expected createdDate value to be equals to 2000-12-31' | ||
75 | ); | ||
76 | expect(await pieceOfNewsUpdatePage.getLastModifiedByInput()).to.eq( | ||
77 | 'lastModifiedBy', | ||
78 | 'Expected LastModifiedBy value to be equals to lastModifiedBy' | ||
79 | ); | ||
80 | expect(await pieceOfNewsUpdatePage.getLastModifiedDateInput()).to.contain( | ||
81 | '2001-01-01T02:30', | ||
82 | 'Expected lastModifiedDate value to be equals to 2000-12-31' | ||
83 | ); | ||
84 | |||
85 | await pieceOfNewsUpdatePage.save(); | ||
86 | expect(await pieceOfNewsUpdatePage.getSaveButton().isPresent(), 'Expected save button disappear').to.be.false; | ||
87 | |||
88 | expect(await pieceOfNewsComponentsPage.countDeleteButtons()).to.eq(nbButtonsBeforeCreate + 1, 'Expected one more entry in the table'); | ||
89 | }); | ||
90 | |||
91 | it('should delete last PieceOfNews', async () => { | ||
92 | const nbButtonsBeforeDelete = await pieceOfNewsComponentsPage.countDeleteButtons(); | ||
93 | await pieceOfNewsComponentsPage.clickOnLastDeleteButton(); | ||
94 | |||
95 | pieceOfNewsDeleteDialog = new PieceOfNewsDeleteDialog(); | ||
96 | expect(await pieceOfNewsDeleteDialog.getDialogTitle()).to.eq('honlapApp.pieceOfNews.delete.question'); | ||
97 | await pieceOfNewsDeleteDialog.clickOnConfirmButton(); | ||
98 | |||
99 | expect(await pieceOfNewsComponentsPage.countDeleteButtons()).to.eq(nbButtonsBeforeDelete - 1); | ||
100 | }); | ||
101 | |||
102 | after(async () => { | ||
103 | await navBarPage.autoSignOut(); | ||
104 | }); | ||
105 | }); |
File src/test/javascript/e2e/page-objects/jhi-page-objects.ts added (mode: 100644) (index 0000000..cbfa50c) | |||
1 | import { element, by, ElementFinder } from 'protractor'; | ||
2 | |||
3 | /* eslint @typescript-eslint/no-use-before-define: 0 */ | ||
4 | export class NavBarPage { | ||
5 | entityMenu = element(by.id('entity-menu')); | ||
6 | accountMenu = element(by.id('account-menu')); | ||
7 | adminMenu!: ElementFinder; | ||
8 | signIn = element(by.id('login')); | ||
9 | register = element(by.css('[routerLink="account/register"]')); | ||
10 | signOut = element(by.id('logout')); | ||
11 | passwordMenu = element(by.css('[routerLink="account/password"]')); | ||
12 | settingsMenu = element(by.css('[routerLink="account/settings"]')); | ||
13 | |||
14 | constructor(asAdmin?: Boolean) { | ||
15 | if (asAdmin) { | ||
16 | this.adminMenu = element(by.id('admin-menu')); | ||
17 | } | ||
18 | } | ||
19 | |||
20 | async clickOnEntityMenu(): Promise<void> { | ||
21 | await this.entityMenu.click(); | ||
22 | } | ||
23 | |||
24 | async clickOnAccountMenu(): Promise<void> { | ||
25 | await this.accountMenu.click(); | ||
26 | } | ||
27 | |||
28 | async clickOnAdminMenu(): Promise<void> { | ||
29 | await this.adminMenu.click(); | ||
30 | } | ||
31 | |||
32 | async clickOnSignIn(): Promise<void> { | ||
33 | await this.signIn.click(); | ||
34 | } | ||
35 | |||
36 | async clickOnRegister(): Promise<void> { | ||
37 | await this.signIn.click(); | ||
38 | } | ||
39 | |||
40 | async clickOnSignOut(): Promise<void> { | ||
41 | await this.signOut.click(); | ||
42 | } | ||
43 | |||
44 | async clickOnPasswordMenu(): Promise<void> { | ||
45 | await this.passwordMenu.click(); | ||
46 | } | ||
47 | |||
48 | async clickOnSettingsMenu(): Promise<void> { | ||
49 | await this.settingsMenu.click(); | ||
50 | } | ||
51 | |||
52 | async clickOnEntity(entityName: string): Promise<void> { | ||
53 | await element(by.css('[routerLink="' + entityName + '"]')).click(); | ||
54 | } | ||
55 | |||
56 | async clickOnAdmin(entityName: string): Promise<void> { | ||
57 | await element(by.css('[routerLink="admin/' + entityName + '"]')).click(); | ||
58 | } | ||
59 | |||
60 | async getSignInPage(): Promise<SignInPage> { | ||
61 | await this.clickOnAccountMenu(); | ||
62 | await this.clickOnSignIn(); | ||
63 | return new SignInPage(); | ||
64 | } | ||
65 | |||
66 | async getPasswordPage(): Promise<PasswordPage> { | ||
67 | await this.clickOnAccountMenu(); | ||
68 | await this.clickOnPasswordMenu(); | ||
69 | return new PasswordPage(); | ||
70 | } | ||
71 | |||
72 | async getSettingsPage(): Promise<SettingsPage> { | ||
73 | await this.clickOnAccountMenu(); | ||
74 | await this.clickOnSettingsMenu(); | ||
75 | return new SettingsPage(); | ||
76 | } | ||
77 | |||
78 | async goToEntity(entityName: string): Promise<void> { | ||
79 | await this.clickOnEntityMenu(); | ||
80 | await this.clickOnEntity(entityName); | ||
81 | } | ||
82 | |||
83 | async goToSignInPage(): Promise<void> { | ||
84 | await this.clickOnAccountMenu(); | ||
85 | await this.clickOnSignIn(); | ||
86 | } | ||
87 | |||
88 | async goToPasswordMenu(): Promise<void> { | ||
89 | await this.clickOnAccountMenu(); | ||
90 | await this.clickOnPasswordMenu(); | ||
91 | } | ||
92 | |||
93 | async autoSignOut(): Promise<void> { | ||
94 | await this.clickOnAccountMenu(); | ||
95 | await this.clickOnSignOut(); | ||
96 | } | ||
97 | } | ||
98 | |||
99 | export class SignInPage { | ||
100 | username = element(by.id('username')); | ||
101 | password = element(by.id('password')); | ||
102 | loginButton = element(by.css('button[type=submit]')); | ||
103 | |||
104 | async setUserName(username: string): Promise<void> { | ||
105 | await this.username.sendKeys(username); | ||
106 | } | ||
107 | |||
108 | async getUserName(): Promise<string> { | ||
109 | return this.username.getAttribute('value'); | ||
110 | } | ||
111 | |||
112 | async clearUserName(): Promise<void> { | ||
113 | await this.username.clear(); | ||
114 | } | ||
115 | |||
116 | async setPassword(password: string): Promise<void> { | ||
117 | await this.password.sendKeys(password); | ||
118 | } | ||
119 | |||
120 | async getPassword(): Promise<string> { | ||
121 | return this.password.getAttribute('value'); | ||
122 | } | ||
123 | |||
124 | async clearPassword(): Promise<void> { | ||
125 | await this.password.clear(); | ||
126 | } | ||
127 | |||
128 | async autoSignInUsing(username: string, password: string): Promise<void> { | ||
129 | await this.setUserName(username); | ||
130 | await this.setPassword(password); | ||
131 | await this.login(); | ||
132 | } | ||
133 | |||
134 | async login(): Promise<void> { | ||
135 | await this.loginButton.click(); | ||
136 | } | ||
137 | } | ||
138 | |||
139 | export class PasswordPage { | ||
140 | currentPassword = element(by.id('currentPassword')); | ||
141 | password = element(by.id('newPassword')); | ||
142 | confirmPassword = element(by.id('confirmPassword')); | ||
143 | saveButton = element(by.css('button[type=submit]')); | ||
144 | title = element.all(by.css('h2')).first(); | ||
145 | |||
146 | async setCurrentPassword(password: string): Promise<void> { | ||
147 | await this.currentPassword.sendKeys(password); | ||
148 | } | ||
149 | |||
150 | async setPassword(password: string): Promise<void> { | ||
151 | await this.password.sendKeys(password); | ||
152 | } | ||
153 | |||
154 | async getPassword(): Promise<string> { | ||
155 | return this.password.getAttribute('value'); | ||
156 | } | ||
157 | |||
158 | async clearPassword(): Promise<void> { | ||
159 | await this.password.clear(); | ||
160 | } | ||
161 | |||
162 | async setConfirmPassword(confirmPassword: string): Promise<void> { | ||
163 | await this.confirmPassword.sendKeys(confirmPassword); | ||
164 | } | ||
165 | |||
166 | async getConfirmPassword(): Promise<string> { | ||
167 | return this.confirmPassword.getAttribute('value'); | ||
168 | } | ||
169 | |||
170 | async clearConfirmPassword(): Promise<void> { | ||
171 | await this.confirmPassword.clear(); | ||
172 | } | ||
173 | |||
174 | async getTitle(): Promise<string> { | ||
175 | return this.title.getAttribute('jhiTranslate'); | ||
176 | } | ||
177 | |||
178 | async save(): Promise<void> { | ||
179 | await this.saveButton.click(); | ||
180 | } | ||
181 | } | ||
182 | |||
183 | export class SettingsPage { | ||
184 | firstName = element(by.id('firstName')); | ||
185 | lastName = element(by.id('lastName')); | ||
186 | email = element(by.id('email')); | ||
187 | saveButton = element(by.css('button[type=submit]')); | ||
188 | title = element.all(by.css('h2')).first(); | ||
189 | |||
190 | async setFirstName(firstName: string): Promise<void> { | ||
191 | await this.firstName.sendKeys(firstName); | ||
192 | } | ||
193 | |||
194 | async getFirstName(): Promise<string> { | ||
195 | return this.firstName.getAttribute('value'); | ||
196 | } | ||
197 | |||
198 | async clearFirstName(): Promise<void> { | ||
199 | await this.firstName.clear(); | ||
200 | } | ||
201 | |||
202 | async setLastName(lastName: string): Promise<void> { | ||
203 | await this.lastName.sendKeys(lastName); | ||
204 | } | ||
205 | |||
206 | async getLastName(): Promise<string> { | ||
207 | return this.lastName.getAttribute('value'); | ||
208 | } | ||
209 | |||
210 | async clearLastName(): Promise<void> { | ||
211 | await this.lastName.clear(); | ||
212 | } | ||
213 | |||
214 | async setEmail(email: string): Promise<void> { | ||
215 | await this.email.sendKeys(email); | ||
216 | } | ||
217 | |||
218 | async getEmail(): Promise<string> { | ||
219 | return this.email.getAttribute('value'); | ||
220 | } | ||
221 | |||
222 | async clearEmail(): Promise<void> { | ||
223 | await this.email.clear(); | ||
224 | } | ||
225 | |||
226 | async getTitle(): Promise<string> { | ||
227 | return this.title.getAttribute('jhiTranslate'); | ||
228 | } | ||
229 | |||
230 | async save(): Promise<void> { | ||
231 | await this.saveButton.click(); | ||
232 | } | ||
233 | } |
File src/test/javascript/jest-global-mocks.ts added (mode: 100644) (index 0000000..a802d1b) | |||
1 | Object.defineProperty(window, 'getComputedStyle', { | ||
2 | value: () => ['-webkit-appearance'] | ||
3 | }); |
File src/test/javascript/jest.conf.js added (mode: 100644) (index 0000000..91d9d5f) | |||
1 | const tsconfig = require('../../../tsconfig.json'); | ||
2 | |||
3 | module.exports = { | ||
4 | preset: 'jest-preset-angular', | ||
5 | setupFiles: ['jest-date-mock'], | ||
6 | setupFilesAfterEnv: ['<rootDir>/src/test/javascript/jest.ts'], | ||
7 | cacheDirectory: '<rootDir>/target/jest-cache', | ||
8 | coverageDirectory: '<rootDir>/target/test-results/', | ||
9 | globals: { | ||
10 | 'ts-jest': { | ||
11 | stringifyContentPathRegex: '\\.html$', | ||
12 | tsConfig: '<rootDir>/tsconfig.json', | ||
13 | astTransformers: ['jest-preset-angular/build/InlineFilesTransformer', 'jest-preset-angular/build/StripStylesTransformer'] | ||
14 | } | ||
15 | }, | ||
16 | coveragePathIgnorePatterns: [ | ||
17 | '<rootDir>/src/test/javascript' | ||
18 | ], | ||
19 | moduleNameMapper: mapTypescriptAliasToJestAlias(), | ||
20 | reporters: [ | ||
21 | 'default', | ||
22 | [ 'jest-junit', { outputDirectory: './target/test-results/', outputName: 'TESTS-results-jest.xml' } ] | ||
23 | ], | ||
24 | testResultsProcessor: 'jest-sonar-reporter', | ||
25 | transformIgnorePatterns: ['node_modules/'], | ||
26 | testMatch: ['<rootDir>/src/test/javascript/spec/**/@(*.)@(spec.ts)'], | ||
27 | rootDir: '../../../', | ||
28 | testURL: 'http://localhost/' | ||
29 | }; | ||
30 | |||
31 | function mapTypescriptAliasToJestAlias(alias = {}) { | ||
32 | const jestAliases = { ...alias }; | ||
33 | if (!tsconfig.compilerOptions.paths) { | ||
34 | return jestAliases; | ||
35 | } | ||
36 | Object.entries(tsconfig.compilerOptions.paths) | ||
37 | .filter(([key, value]) => { | ||
38 | // use Typescript alias in Jest only if this has value | ||
39 | if (value.length) { | ||
40 | return true; | ||
41 | } | ||
42 | return false; | ||
43 | }) | ||
44 | .map(([key, value]) => { | ||
45 | // if Typescript alias ends with /* then in Jest: | ||
46 | // - alias key must end with /(.*) | ||
47 | // - alias value must end with /$1 | ||
48 | const regexToReplace = /(.*)\/\*$/; | ||
49 | const aliasKey = key.replace(regexToReplace, '$1/(.*)'); | ||
50 | const aliasValue = value[0].replace(regexToReplace, '$1/$$1'); | ||
51 | return [aliasKey, `<rootDir>/${aliasValue}`]; | ||
52 | }) | ||
53 | .reduce((aliases, [key, value]) => { | ||
54 | aliases[key] = value; | ||
55 | return aliases; | ||
56 | }, jestAliases); | ||
57 | return jestAliases; | ||
58 | } |
File src/test/javascript/jest.ts added (mode: 100644) (index 0000000..904329f) | |||
1 | import 'jest-preset-angular'; | ||
2 | import './jest-global-mocks'; |
File src/test/javascript/protractor.conf.js added (mode: 100644) (index 0000000..faed3b3) | |||
1 | exports.config = { | ||
2 | allScriptsTimeout: 20000, | ||
3 | |||
4 | specs: [ | ||
5 | './e2e/account/**/*.spec.ts', | ||
6 | './e2e/admin/**/*.spec.ts', | ||
7 | './e2e/entities/**/*.spec.ts', | ||
8 | /* jhipster-needle-add-protractor-tests - JHipster will add protractors tests here */ | ||
9 | ], | ||
10 | |||
11 | capabilities: { | ||
12 | browserName: 'chrome', | ||
13 | chromeOptions: { | ||
14 | args: process.env.JHI_E2E_HEADLESS | ||
15 | ? [ "--headless", "--disable-gpu", "--window-size=800,600" ] | ||
16 | : [ "--disable-gpu", "--window-size=800,600" ] | ||
17 | } | ||
18 | }, | ||
19 | |||
20 | directConnect: true, | ||
21 | |||
22 | baseUrl: 'http://localhost:8080/', | ||
23 | |||
24 | framework: 'mocha', | ||
25 | |||
26 | SELENIUM_PROMISE_MANAGER: false, | ||
27 | |||
28 | mochaOpts: { | ||
29 | reporter: 'spec', | ||
30 | slow: 3000, | ||
31 | ui: 'bdd', | ||
32 | timeout: 720000 | ||
33 | }, | ||
34 | |||
35 | beforeLaunch: function() { | ||
36 | require('ts-node').register({ | ||
37 | project: 'tsconfig.e2e.json' | ||
38 | }); | ||
39 | }, | ||
40 | |||
41 | onPrepare: function() { | ||
42 | browser.driver.manage().window().setSize(1280, 1024); | ||
43 | // Disable animations | ||
44 | // @ts-ignore | ||
45 | browser.executeScript('document.body.className += " notransition";'); | ||
46 | const chai = require('chai'); | ||
47 | const chaiAsPromised = require('chai-as-promised'); | ||
48 | chai.use(chaiAsPromised); | ||
49 | const chaiString = require('chai-string'); | ||
50 | chai.use(chaiString); | ||
51 | // @ts-ignore | ||
52 | global.chai = chai; | ||
53 | }, | ||
54 | |||
55 | useAllAngular2AppRoots: true | ||
56 | }; |
File src/test/javascript/spec/app/account/activate/activate.component.spec.ts added (mode: 100644) (index 0000000..82c5195) | |||
1 | import { TestBed, async, tick, fakeAsync, inject } from '@angular/core/testing'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | import { of, throwError } from 'rxjs'; | ||
4 | |||
5 | import { HonlapTestModule } from '../../../test.module'; | ||
6 | import { MockActivatedRoute } from '../../../helpers/mock-route.service'; | ||
7 | import { ActivateService } from 'app/account/activate/activate.service'; | ||
8 | import { ActivateComponent } from 'app/account/activate/activate.component'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('ActivateComponent', () => { | ||
12 | let comp: ActivateComponent; | ||
13 | |||
14 | beforeEach(async(() => { | ||
15 | TestBed.configureTestingModule({ | ||
16 | imports: [HonlapTestModule], | ||
17 | declarations: [ActivateComponent], | ||
18 | providers: [ | ||
19 | { | ||
20 | provide: ActivatedRoute, | ||
21 | useValue: new MockActivatedRoute({ key: 'ABC123' }) | ||
22 | } | ||
23 | ] | ||
24 | }) | ||
25 | .overrideTemplate(ActivateComponent, '') | ||
26 | .compileComponents(); | ||
27 | })); | ||
28 | |||
29 | beforeEach(() => { | ||
30 | const fixture = TestBed.createComponent(ActivateComponent); | ||
31 | comp = fixture.componentInstance; | ||
32 | }); | ||
33 | |||
34 | it('calls activate.get with the key from params', inject( | ||
35 | [ActivateService], | ||
36 | fakeAsync((service: ActivateService) => { | ||
37 | spyOn(service, 'get').and.returnValue(of()); | ||
38 | |||
39 | comp.ngOnInit(); | ||
40 | tick(); | ||
41 | |||
42 | expect(service.get).toHaveBeenCalledWith('ABC123'); | ||
43 | }) | ||
44 | )); | ||
45 | |||
46 | it('should set set success to true upon successful activation', inject( | ||
47 | [ActivateService], | ||
48 | fakeAsync((service: ActivateService) => { | ||
49 | spyOn(service, 'get').and.returnValue(of({})); | ||
50 | |||
51 | comp.ngOnInit(); | ||
52 | tick(); | ||
53 | |||
54 | expect(comp.error).toBe(false); | ||
55 | expect(comp.success).toBe(true); | ||
56 | }) | ||
57 | )); | ||
58 | |||
59 | it('should set set error to true upon activation failure', inject( | ||
60 | [ActivateService], | ||
61 | fakeAsync((service: ActivateService) => { | ||
62 | spyOn(service, 'get').and.returnValue(throwError('ERROR')); | ||
63 | |||
64 | comp.ngOnInit(); | ||
65 | tick(); | ||
66 | |||
67 | expect(comp.error).toBe(true); | ||
68 | expect(comp.success).toBe(false); | ||
69 | }) | ||
70 | )); | ||
71 | }); | ||
72 | }); |
File src/test/javascript/spec/app/account/password-reset/finish/password-reset-finish.component.spec.ts added (mode: 100644) (index 0000000..2185aaf) | |||
1 | import { ElementRef } from '@angular/core'; | ||
2 | import { ComponentFixture, TestBed, inject, tick, fakeAsync } from '@angular/core/testing'; | ||
3 | import { FormBuilder } from '@angular/forms'; | ||
4 | import { ActivatedRoute } from '@angular/router'; | ||
5 | import { of, throwError } from 'rxjs'; | ||
6 | |||
7 | import { HonlapTestModule } from '../../../../test.module'; | ||
8 | import { PasswordResetFinishComponent } from 'app/account/password-reset/finish/password-reset-finish.component'; | ||
9 | import { PasswordResetFinishService } from 'app/account/password-reset/finish/password-reset-finish.service'; | ||
10 | import { MockActivatedRoute } from '../../../../helpers/mock-route.service'; | ||
11 | |||
12 | describe('Component Tests', () => { | ||
13 | describe('PasswordResetFinishComponent', () => { | ||
14 | let fixture: ComponentFixture<PasswordResetFinishComponent>; | ||
15 | let comp: PasswordResetFinishComponent; | ||
16 | |||
17 | beforeEach(() => { | ||
18 | fixture = TestBed.configureTestingModule({ | ||
19 | imports: [HonlapTestModule], | ||
20 | declarations: [PasswordResetFinishComponent], | ||
21 | providers: [ | ||
22 | FormBuilder, | ||
23 | { | ||
24 | provide: ActivatedRoute, | ||
25 | useValue: new MockActivatedRoute({ key: 'XYZPDQ' }) | ||
26 | } | ||
27 | ] | ||
28 | }) | ||
29 | .overrideTemplate(PasswordResetFinishComponent, '') | ||
30 | .createComponent(PasswordResetFinishComponent); | ||
31 | }); | ||
32 | |||
33 | beforeEach(() => { | ||
34 | fixture = TestBed.createComponent(PasswordResetFinishComponent); | ||
35 | comp = fixture.componentInstance; | ||
36 | comp.ngOnInit(); | ||
37 | }); | ||
38 | |||
39 | it('should define its initial state', () => { | ||
40 | expect(comp.initialized).toBe(true); | ||
41 | expect(comp.key).toEqual('XYZPDQ'); | ||
42 | }); | ||
43 | |||
44 | it('sets focus after the view has been initialized', () => { | ||
45 | const node = { | ||
46 | focus(): void {} | ||
47 | }; | ||
48 | comp.newPassword = new ElementRef(node); | ||
49 | spyOn(node, 'focus'); | ||
50 | |||
51 | comp.ngAfterViewInit(); | ||
52 | |||
53 | expect(node.focus).toHaveBeenCalled(); | ||
54 | }); | ||
55 | |||
56 | it('should ensure the two passwords entered match', () => { | ||
57 | comp.passwordForm.patchValue({ | ||
58 | newPassword: 'password', | ||
59 | confirmPassword: 'non-matching' | ||
60 | }); | ||
61 | |||
62 | comp.finishReset(); | ||
63 | |||
64 | expect(comp.doNotMatch).toBe(true); | ||
65 | }); | ||
66 | |||
67 | it('should update success to true after resetting password', inject( | ||
68 | [PasswordResetFinishService], | ||
69 | fakeAsync((service: PasswordResetFinishService) => { | ||
70 | spyOn(service, 'save').and.returnValue(of({})); | ||
71 | comp.passwordForm.patchValue({ | ||
72 | newPassword: 'password', | ||
73 | confirmPassword: 'password' | ||
74 | }); | ||
75 | |||
76 | comp.finishReset(); | ||
77 | tick(); | ||
78 | |||
79 | expect(service.save).toHaveBeenCalledWith('XYZPDQ', 'password'); | ||
80 | expect(comp.success).toBe(true); | ||
81 | }) | ||
82 | )); | ||
83 | |||
84 | it('should notify of generic error', inject( | ||
85 | [PasswordResetFinishService], | ||
86 | fakeAsync((service: PasswordResetFinishService) => { | ||
87 | spyOn(service, 'save').and.returnValue(throwError('ERROR')); | ||
88 | comp.passwordForm.patchValue({ | ||
89 | newPassword: 'password', | ||
90 | confirmPassword: 'password' | ||
91 | }); | ||
92 | |||
93 | comp.finishReset(); | ||
94 | tick(); | ||
95 | |||
96 | expect(service.save).toHaveBeenCalledWith('XYZPDQ', 'password'); | ||
97 | expect(comp.success).toBe(false); | ||
98 | expect(comp.error).toBe(true); | ||
99 | }) | ||
100 | )); | ||
101 | }); | ||
102 | }); |
File src/test/javascript/spec/app/account/password-reset/init/password-reset-init.component.spec.ts added (mode: 100644) (index 0000000..5d281b5) | |||
1 | import { ElementRef } from '@angular/core'; | ||
2 | import { ComponentFixture, TestBed, inject } from '@angular/core/testing'; | ||
3 | import { FormBuilder } from '@angular/forms'; | ||
4 | import { of, throwError } from 'rxjs'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../../test.module'; | ||
7 | import { PasswordResetInitComponent } from 'app/account/password-reset/init/password-reset-init.component'; | ||
8 | import { PasswordResetInitService } from 'app/account/password-reset/init/password-reset-init.service'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('PasswordResetInitComponent', () => { | ||
12 | let fixture: ComponentFixture<PasswordResetInitComponent>; | ||
13 | let comp: PasswordResetInitComponent; | ||
14 | |||
15 | beforeEach(() => { | ||
16 | fixture = TestBed.configureTestingModule({ | ||
17 | imports: [HonlapTestModule], | ||
18 | declarations: [PasswordResetInitComponent], | ||
19 | providers: [FormBuilder] | ||
20 | }) | ||
21 | .overrideTemplate(PasswordResetInitComponent, '') | ||
22 | .createComponent(PasswordResetInitComponent); | ||
23 | comp = fixture.componentInstance; | ||
24 | }); | ||
25 | |||
26 | it('sets focus after the view has been initialized', () => { | ||
27 | const node = { | ||
28 | focus(): void {} | ||
29 | }; | ||
30 | comp.email = new ElementRef(node); | ||
31 | spyOn(node, 'focus'); | ||
32 | |||
33 | comp.ngAfterViewInit(); | ||
34 | |||
35 | expect(node.focus).toHaveBeenCalled(); | ||
36 | }); | ||
37 | |||
38 | it('notifies of success upon successful requestReset', inject([PasswordResetInitService], (service: PasswordResetInitService) => { | ||
39 | spyOn(service, 'save').and.returnValue(of({})); | ||
40 | comp.resetRequestForm.patchValue({ | ||
41 | email: 'user@domain.com' | ||
42 | }); | ||
43 | |||
44 | comp.requestReset(); | ||
45 | |||
46 | expect(service.save).toHaveBeenCalledWith('user@domain.com'); | ||
47 | expect(comp.success).toBe(true); | ||
48 | })); | ||
49 | |||
50 | it('no notification of success upon error response', inject([PasswordResetInitService], (service: PasswordResetInitService) => { | ||
51 | spyOn(service, 'save').and.returnValue( | ||
52 | throwError({ | ||
53 | status: 503, | ||
54 | data: 'something else' | ||
55 | }) | ||
56 | ); | ||
57 | comp.resetRequestForm.patchValue({ | ||
58 | email: 'user@domain.com' | ||
59 | }); | ||
60 | comp.requestReset(); | ||
61 | |||
62 | expect(service.save).toHaveBeenCalledWith('user@domain.com'); | ||
63 | expect(comp.success).toBe(false); | ||
64 | })); | ||
65 | }); | ||
66 | }); |
File src/test/javascript/spec/app/account/password/password-strength-bar.component.spec.ts added (mode: 100644) (index 0000000..ff1297e) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | |||
3 | import { PasswordStrengthBarComponent } from 'app/account/password/password-strength-bar.component'; | ||
4 | |||
5 | describe('Component Tests', () => { | ||
6 | describe('PasswordStrengthBarComponent', () => { | ||
7 | let comp: PasswordStrengthBarComponent; | ||
8 | let fixture: ComponentFixture<PasswordStrengthBarComponent>; | ||
9 | |||
10 | beforeEach(async(() => { | ||
11 | TestBed.configureTestingModule({ | ||
12 | declarations: [PasswordStrengthBarComponent] | ||
13 | }) | ||
14 | .overrideTemplate(PasswordStrengthBarComponent, '') | ||
15 | .compileComponents(); | ||
16 | })); | ||
17 | |||
18 | beforeEach(() => { | ||
19 | fixture = TestBed.createComponent(PasswordStrengthBarComponent); | ||
20 | comp = fixture.componentInstance; | ||
21 | }); | ||
22 | |||
23 | describe('PasswordStrengthBarComponents', () => { | ||
24 | it('should initialize with default values', () => { | ||
25 | expect(comp.measureStrength('')).toBe(0); | ||
26 | expect(comp.colors).toEqual(['#F00', '#F90', '#FF0', '#9F0', '#0F0']); | ||
27 | expect(comp.getColor(0).idx).toBe(1); | ||
28 | expect(comp.getColor(0).color).toBe(comp.colors[0]); | ||
29 | }); | ||
30 | |||
31 | it('should increase strength upon password value change', () => { | ||
32 | expect(comp.measureStrength('')).toBe(0); | ||
33 | expect(comp.measureStrength('aa')).toBeGreaterThanOrEqual(comp.measureStrength('')); | ||
34 | expect(comp.measureStrength('aa^6')).toBeGreaterThanOrEqual(comp.measureStrength('aa')); | ||
35 | expect(comp.measureStrength('Aa090(**)')).toBeGreaterThanOrEqual(comp.measureStrength('aa^6')); | ||
36 | expect(comp.measureStrength('Aa090(**)+-07365')).toBeGreaterThanOrEqual(comp.measureStrength('Aa090(**)')); | ||
37 | }); | ||
38 | |||
39 | it('should change the color based on strength', () => { | ||
40 | expect(comp.getColor(0).color).toBe(comp.colors[0]); | ||
41 | expect(comp.getColor(11).color).toBe(comp.colors[1]); | ||
42 | expect(comp.getColor(22).color).toBe(comp.colors[2]); | ||
43 | expect(comp.getColor(33).color).toBe(comp.colors[3]); | ||
44 | expect(comp.getColor(44).color).toBe(comp.colors[4]); | ||
45 | }); | ||
46 | }); | ||
47 | }); | ||
48 | }); |
File src/test/javascript/spec/app/account/password/password.component.spec.ts added (mode: 100644) (index 0000000..385f8eb) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { HttpResponse } from '@angular/common/http'; | ||
3 | import { FormBuilder } from '@angular/forms'; | ||
4 | import { of, throwError } from 'rxjs'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { PasswordComponent } from 'app/account/password/password.component'; | ||
8 | import { PasswordService } from 'app/account/password/password.service'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('PasswordComponent', () => { | ||
12 | let comp: PasswordComponent; | ||
13 | let fixture: ComponentFixture<PasswordComponent>; | ||
14 | let service: PasswordService; | ||
15 | |||
16 | beforeEach(async(() => { | ||
17 | TestBed.configureTestingModule({ | ||
18 | imports: [HonlapTestModule], | ||
19 | declarations: [PasswordComponent], | ||
20 | providers: [FormBuilder] | ||
21 | }) | ||
22 | .overrideTemplate(PasswordComponent, '') | ||
23 | .compileComponents(); | ||
24 | })); | ||
25 | |||
26 | beforeEach(() => { | ||
27 | fixture = TestBed.createComponent(PasswordComponent); | ||
28 | comp = fixture.componentInstance; | ||
29 | service = fixture.debugElement.injector.get(PasswordService); | ||
30 | }); | ||
31 | |||
32 | it('should show error if passwords do not match', () => { | ||
33 | // GIVEN | ||
34 | comp.passwordForm.patchValue({ | ||
35 | newPassword: 'password1', | ||
36 | confirmPassword: 'password2' | ||
37 | }); | ||
38 | // WHEN | ||
39 | comp.changePassword(); | ||
40 | // THEN | ||
41 | expect(comp.doNotMatch).toBe(true); | ||
42 | expect(comp.error).toBe(false); | ||
43 | expect(comp.success).toBe(false); | ||
44 | }); | ||
45 | |||
46 | it('should call Auth.changePassword when passwords match', () => { | ||
47 | // GIVEN | ||
48 | const passwordValues = { | ||
49 | currentPassword: 'oldPassword', | ||
50 | newPassword: 'myPassword' | ||
51 | }; | ||
52 | |||
53 | spyOn(service, 'save').and.returnValue(of(new HttpResponse({ body: true }))); | ||
54 | |||
55 | comp.passwordForm.patchValue({ | ||
56 | currentPassword: passwordValues.currentPassword, | ||
57 | newPassword: passwordValues.newPassword, | ||
58 | confirmPassword: passwordValues.newPassword | ||
59 | }); | ||
60 | |||
61 | // WHEN | ||
62 | comp.changePassword(); | ||
63 | |||
64 | // THEN | ||
65 | expect(service.save).toHaveBeenCalledWith(passwordValues.newPassword, passwordValues.currentPassword); | ||
66 | }); | ||
67 | |||
68 | it('should set success to true upon success', () => { | ||
69 | // GIVEN | ||
70 | spyOn(service, 'save').and.returnValue(of(new HttpResponse({ body: true }))); | ||
71 | comp.passwordForm.patchValue({ | ||
72 | newPassword: 'myPassword', | ||
73 | confirmPassword: 'myPassword' | ||
74 | }); | ||
75 | |||
76 | // WHEN | ||
77 | comp.changePassword(); | ||
78 | |||
79 | // THEN | ||
80 | expect(comp.doNotMatch).toBe(false); | ||
81 | expect(comp.error).toBe(false); | ||
82 | expect(comp.success).toBe(true); | ||
83 | }); | ||
84 | |||
85 | it('should notify of error if change password fails', () => { | ||
86 | // GIVEN | ||
87 | spyOn(service, 'save').and.returnValue(throwError('ERROR')); | ||
88 | comp.passwordForm.patchValue({ | ||
89 | newPassword: 'myPassword', | ||
90 | confirmPassword: 'myPassword' | ||
91 | }); | ||
92 | |||
93 | // WHEN | ||
94 | comp.changePassword(); | ||
95 | |||
96 | // THEN | ||
97 | expect(comp.doNotMatch).toBe(false); | ||
98 | expect(comp.success).toBe(false); | ||
99 | expect(comp.error).toBe(true); | ||
100 | }); | ||
101 | }); | ||
102 | }); |
File src/test/javascript/spec/app/account/register/register.component.spec.ts added (mode: 100644) (index 0000000..65b06e5) | |||
1 | import { ComponentFixture, TestBed, async, inject, tick, fakeAsync } from '@angular/core/testing'; | ||
2 | import { FormBuilder } from '@angular/forms'; | ||
3 | import { of, throwError } from 'rxjs'; | ||
4 | import { JhiLanguageService } from 'ng-jhipster'; | ||
5 | |||
6 | import { MockLanguageService } from '../../../helpers/mock-language.service'; | ||
7 | import { HonlapTestModule } from '../../../test.module'; | ||
8 | import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/shared/constants/error.constants'; | ||
9 | import { RegisterService } from 'app/account/register/register.service'; | ||
10 | import { RegisterComponent } from 'app/account/register/register.component'; | ||
11 | |||
12 | describe('Component Tests', () => { | ||
13 | describe('RegisterComponent', () => { | ||
14 | let fixture: ComponentFixture<RegisterComponent>; | ||
15 | let comp: RegisterComponent; | ||
16 | |||
17 | beforeEach(async(() => { | ||
18 | TestBed.configureTestingModule({ | ||
19 | imports: [HonlapTestModule], | ||
20 | declarations: [RegisterComponent], | ||
21 | providers: [FormBuilder] | ||
22 | }) | ||
23 | .overrideTemplate(RegisterComponent, '') | ||
24 | .compileComponents(); | ||
25 | })); | ||
26 | |||
27 | beforeEach(() => { | ||
28 | fixture = TestBed.createComponent(RegisterComponent); | ||
29 | comp = fixture.componentInstance; | ||
30 | }); | ||
31 | |||
32 | it('should ensure the two passwords entered match', () => { | ||
33 | comp.registerForm.patchValue({ | ||
34 | password: 'password', | ||
35 | confirmPassword: 'non-matching' | ||
36 | }); | ||
37 | |||
38 | comp.register(); | ||
39 | |||
40 | expect(comp.doNotMatch).toBe(true); | ||
41 | }); | ||
42 | |||
43 | it('should update success to true after creating an account', inject( | ||
44 | [RegisterService, JhiLanguageService], | ||
45 | fakeAsync((service: RegisterService, mockTranslate: MockLanguageService) => { | ||
46 | spyOn(service, 'save').and.returnValue(of({})); | ||
47 | comp.registerForm.patchValue({ | ||
48 | password: 'password', | ||
49 | confirmPassword: 'password' | ||
50 | }); | ||
51 | |||
52 | comp.register(); | ||
53 | tick(); | ||
54 | |||
55 | expect(service.save).toHaveBeenCalledWith({ | ||
56 | email: '', | ||
57 | password: 'password', | ||
58 | login: '', | ||
59 | langKey: 'hu' | ||
60 | }); | ||
61 | expect(comp.success).toBe(true); | ||
62 | expect(mockTranslate.getCurrentLanguageSpy).toHaveBeenCalled(); | ||
63 | expect(comp.errorUserExists).toBe(false); | ||
64 | expect(comp.errorEmailExists).toBe(false); | ||
65 | expect(comp.error).toBe(false); | ||
66 | }) | ||
67 | )); | ||
68 | |||
69 | it('should notify of user existence upon 400/login already in use', inject( | ||
70 | [RegisterService], | ||
71 | fakeAsync((service: RegisterService) => { | ||
72 | spyOn(service, 'save').and.returnValue( | ||
73 | throwError({ | ||
74 | status: 400, | ||
75 | error: { type: LOGIN_ALREADY_USED_TYPE } | ||
76 | }) | ||
77 | ); | ||
78 | comp.registerForm.patchValue({ | ||
79 | password: 'password', | ||
80 | confirmPassword: 'password' | ||
81 | }); | ||
82 | |||
83 | comp.register(); | ||
84 | tick(); | ||
85 | |||
86 | expect(comp.errorUserExists).toBe(true); | ||
87 | expect(comp.errorEmailExists).toBe(false); | ||
88 | expect(comp.error).toBe(false); | ||
89 | }) | ||
90 | )); | ||
91 | |||
92 | it('should notify of email existence upon 400/email address already in use', inject( | ||
93 | [RegisterService], | ||
94 | fakeAsync((service: RegisterService) => { | ||
95 | spyOn(service, 'save').and.returnValue( | ||
96 | throwError({ | ||
97 | status: 400, | ||
98 | error: { type: EMAIL_ALREADY_USED_TYPE } | ||
99 | }) | ||
100 | ); | ||
101 | comp.registerForm.patchValue({ | ||
102 | password: 'password', | ||
103 | confirmPassword: 'password' | ||
104 | }); | ||
105 | |||
106 | comp.register(); | ||
107 | tick(); | ||
108 | |||
109 | expect(comp.errorEmailExists).toBe(true); | ||
110 | expect(comp.errorUserExists).toBe(false); | ||
111 | expect(comp.error).toBe(false); | ||
112 | }) | ||
113 | )); | ||
114 | |||
115 | it('should notify of generic error', inject( | ||
116 | [RegisterService], | ||
117 | fakeAsync((service: RegisterService) => { | ||
118 | spyOn(service, 'save').and.returnValue( | ||
119 | throwError({ | ||
120 | status: 503 | ||
121 | }) | ||
122 | ); | ||
123 | comp.registerForm.patchValue({ | ||
124 | password: 'password', | ||
125 | confirmPassword: 'password' | ||
126 | }); | ||
127 | |||
128 | comp.register(); | ||
129 | tick(); | ||
130 | |||
131 | expect(comp.errorUserExists).toBe(false); | ||
132 | expect(comp.errorEmailExists).toBe(false); | ||
133 | expect(comp.error).toBe(true); | ||
134 | }) | ||
135 | )); | ||
136 | }); | ||
137 | }); |
File src/test/javascript/spec/app/account/settings/settings.component.spec.ts added (mode: 100644) (index 0000000..bd2f61d) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { FormBuilder } from '@angular/forms'; | ||
3 | import { throwError, of } from 'rxjs'; | ||
4 | |||
5 | import { HonlapTestModule } from '../../../test.module'; | ||
6 | import { AccountService } from 'app/core/auth/account.service'; | ||
7 | import { Account } from 'app/core/user/account.model'; | ||
8 | import { SettingsComponent } from 'app/account/settings/settings.component'; | ||
9 | import { MockAccountService } from '../../../helpers/mock-account.service'; | ||
10 | |||
11 | describe('Component Tests', () => { | ||
12 | describe('SettingsComponent', () => { | ||
13 | let comp: SettingsComponent; | ||
14 | let fixture: ComponentFixture<SettingsComponent>; | ||
15 | let mockAuth: MockAccountService; | ||
16 | const accountValues: Account = { | ||
17 | firstName: 'John', | ||
18 | lastName: 'Doe', | ||
19 | activated: true, | ||
20 | email: 'john.doe@mail.com', | ||
21 | langKey: 'hu', | ||
22 | login: 'john', | ||
23 | authorities: [], | ||
24 | imageUrl: '' | ||
25 | }; | ||
26 | |||
27 | beforeEach(async(() => { | ||
28 | TestBed.configureTestingModule({ | ||
29 | imports: [HonlapTestModule], | ||
30 | declarations: [SettingsComponent], | ||
31 | providers: [FormBuilder] | ||
32 | }) | ||
33 | .overrideTemplate(SettingsComponent, '') | ||
34 | .compileComponents(); | ||
35 | })); | ||
36 | |||
37 | beforeEach(() => { | ||
38 | fixture = TestBed.createComponent(SettingsComponent); | ||
39 | comp = fixture.componentInstance; | ||
40 | mockAuth = TestBed.get(AccountService); | ||
41 | mockAuth.setIdentityResponse(accountValues); | ||
42 | }); | ||
43 | |||
44 | it('should send the current identity upon save', () => { | ||
45 | // GIVEN | ||
46 | mockAuth.saveSpy.and.returnValue(of({})); | ||
47 | const settingsFormValues = { | ||
48 | firstName: 'John', | ||
49 | lastName: 'Doe', | ||
50 | email: 'john.doe@mail.com', | ||
51 | langKey: 'hu' | ||
52 | }; | ||
53 | |||
54 | // WHEN | ||
55 | comp.ngOnInit(); | ||
56 | comp.save(); | ||
57 | |||
58 | // THEN | ||
59 | expect(mockAuth.identitySpy).toHaveBeenCalled(); | ||
60 | expect(mockAuth.saveSpy).toHaveBeenCalledWith(accountValues); | ||
61 | expect(mockAuth.authenticateSpy).toHaveBeenCalledWith(accountValues); | ||
62 | expect(comp.settingsForm.value).toEqual(settingsFormValues); | ||
63 | }); | ||
64 | |||
65 | it('should notify of success upon successful save', () => { | ||
66 | // GIVEN | ||
67 | mockAuth.saveSpy.and.returnValue(of({})); | ||
68 | |||
69 | // WHEN | ||
70 | comp.ngOnInit(); | ||
71 | comp.save(); | ||
72 | |||
73 | // THEN | ||
74 | expect(comp.success).toBe(true); | ||
75 | }); | ||
76 | |||
77 | it('should notify of error upon failed save', () => { | ||
78 | // GIVEN | ||
79 | mockAuth.saveSpy.and.returnValue(throwError('ERROR')); | ||
80 | |||
81 | // WHEN | ||
82 | comp.ngOnInit(); | ||
83 | comp.save(); | ||
84 | |||
85 | // THEN | ||
86 | expect(comp.success).toBe(false); | ||
87 | }); | ||
88 | }); | ||
89 | }); |
File src/test/javascript/spec/app/admin/audits/audits.component.spec.ts added (mode: 100644) (index 0000000..8ebf759) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; | ||
3 | import { of } from 'rxjs'; | ||
4 | import { advanceTo } from 'jest-date-mock'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { AuditsComponent } from 'app/admin/audits/audits.component'; | ||
8 | import { AuditsService } from 'app/admin/audits/audits.service'; | ||
9 | import { Audit } from 'app/admin/audits/audit.model'; | ||
10 | import { ITEMS_PER_PAGE } from 'app/shared/constants/pagination.constants'; | ||
11 | |||
12 | function build2DigitsDatePart(datePart: number): string { | ||
13 | return `0${datePart}`.slice(-2); | ||
14 | } | ||
15 | |||
16 | function getDate(isToday = true): string { | ||
17 | let date: Date = new Date(); | ||
18 | if (isToday) { | ||
19 | // Today + 1 day - needed if the current day must be included | ||
20 | date.setDate(date.getDate() + 1); | ||
21 | } else { | ||
22 | // get last month | ||
23 | if (date.getMonth() === 0) { | ||
24 | date = new Date(date.getFullYear() - 1, 11, date.getDate()); | ||
25 | } else { | ||
26 | date = new Date(date.getFullYear(), date.getMonth() - 1, date.getDate()); | ||
27 | } | ||
28 | } | ||
29 | const monthString = build2DigitsDatePart(date.getMonth() + 1); | ||
30 | const dateString = build2DigitsDatePart(date.getDate()); | ||
31 | return `${date.getFullYear()}-${monthString}-${dateString}`; | ||
32 | } | ||
33 | |||
34 | describe('Component Tests', () => { | ||
35 | describe('AuditsComponent', () => { | ||
36 | let comp: AuditsComponent; | ||
37 | let fixture: ComponentFixture<AuditsComponent>; | ||
38 | let service: AuditsService; | ||
39 | |||
40 | beforeEach(async(() => { | ||
41 | TestBed.configureTestingModule({ | ||
42 | imports: [HonlapTestModule], | ||
43 | declarations: [AuditsComponent], | ||
44 | providers: [AuditsService] | ||
45 | }) | ||
46 | .overrideTemplate(AuditsComponent, '') | ||
47 | .compileComponents(); | ||
48 | })); | ||
49 | |||
50 | beforeEach(() => { | ||
51 | fixture = TestBed.createComponent(AuditsComponent); | ||
52 | comp = fixture.componentInstance; | ||
53 | service = fixture.debugElement.injector.get(AuditsService); | ||
54 | }); | ||
55 | |||
56 | describe('today function', () => { | ||
57 | it('should set toDate to current date', () => { | ||
58 | comp.ngOnInit(); | ||
59 | expect(comp.toDate).toBe(getDate()); | ||
60 | }); | ||
61 | |||
62 | it('if current day is last day of month then should set toDate to first day of next month', () => { | ||
63 | advanceTo(new Date(2019, 0, 31, 0, 0, 0)); | ||
64 | comp.ngOnInit(); | ||
65 | expect(comp.toDate).toBe('2019-02-01'); | ||
66 | }); | ||
67 | |||
68 | it('if current day is not last day of month then should set toDate to next day of current month', () => { | ||
69 | advanceTo(new Date(2019, 0, 27, 0, 0, 0)); | ||
70 | comp.ngOnInit(); | ||
71 | expect(comp.toDate).toBe('2019-01-28'); | ||
72 | }); | ||
73 | }); | ||
74 | |||
75 | describe('previousMonth function', () => { | ||
76 | it('should set fromDate to previous month', () => { | ||
77 | comp.ngOnInit(); | ||
78 | expect(comp.fromDate).toBe(getDate(false)); | ||
79 | }); | ||
80 | |||
81 | it('if current month is January then should set fromDate to previous year last month', () => { | ||
82 | advanceTo(new Date(2019, 0, 20, 0, 0, 0)); | ||
83 | comp.ngOnInit(); | ||
84 | expect(comp.fromDate).toBe('2018-12-20'); | ||
85 | }); | ||
86 | |||
87 | it('if current month is not January then should set fromDate to current year previous month', () => { | ||
88 | advanceTo(new Date(2019, 1, 20, 0, 0, 0)); | ||
89 | comp.ngOnInit(); | ||
90 | expect(comp.fromDate).toBe('2019-01-20'); | ||
91 | }); | ||
92 | }); | ||
93 | |||
94 | describe('By default, on init', () => { | ||
95 | it('should set all default values correctly', () => { | ||
96 | fixture.detectChanges(); | ||
97 | expect(comp.toDate).toBe(getDate()); | ||
98 | expect(comp.fromDate).toBe(getDate(false)); | ||
99 | expect(comp.itemsPerPage).toBe(ITEMS_PER_PAGE); | ||
100 | expect(comp.page).toBe(10); | ||
101 | expect(comp.ascending).toBe(false); | ||
102 | expect(comp.predicate).toBe('id'); | ||
103 | }); | ||
104 | }); | ||
105 | |||
106 | describe('OnInit', () => { | ||
107 | it('Should call load all on init', () => { | ||
108 | // GIVEN | ||
109 | const headers = new HttpHeaders().append('X-Total-Count', '1'); | ||
110 | const audit = new Audit({ remoteAddress: '127.0.0.1', sessionId: '123' }, 'user', '20140101', 'AUTHENTICATION_SUCCESS'); | ||
111 | spyOn(service, 'query').and.returnValue( | ||
112 | of( | ||
113 | new HttpResponse({ | ||
114 | body: [audit], | ||
115 | headers | ||
116 | }) | ||
117 | ) | ||
118 | ); | ||
119 | |||
120 | // WHEN | ||
121 | comp.ngOnInit(); | ||
122 | |||
123 | // THEN | ||
124 | expect(service.query).toHaveBeenCalled(); | ||
125 | expect(comp.audits && comp.audits[0]).toEqual(jasmine.objectContaining(audit)); | ||
126 | expect(comp.totalItems).toBe(1); | ||
127 | }); | ||
128 | }); | ||
129 | |||
130 | describe('Create sort object', () => { | ||
131 | beforeEach(() => { | ||
132 | comp.toDate = getDate(); | ||
133 | comp.fromDate = getDate(false); | ||
134 | spyOn(service, 'query').and.returnValue(of(new HttpResponse({ body: null }))); | ||
135 | }); | ||
136 | |||
137 | it('Should sort only by id asc', () => { | ||
138 | // GIVEN | ||
139 | comp.predicate = 'id'; | ||
140 | comp.ascending = false; | ||
141 | |||
142 | // WHEN | ||
143 | comp.transition(); | ||
144 | |||
145 | // THEN | ||
146 | expect(service.query).toBeCalledWith( | ||
147 | expect.objectContaining({ | ||
148 | sort: ['id,desc'] | ||
149 | }) | ||
150 | ); | ||
151 | }); | ||
152 | |||
153 | it('Should sort by timestamp asc then by id', () => { | ||
154 | // GIVEN | ||
155 | comp.predicate = 'timestamp'; | ||
156 | comp.ascending = true; | ||
157 | |||
158 | // WHEN | ||
159 | comp.transition(); | ||
160 | |||
161 | // THEN | ||
162 | expect(service.query).toBeCalledWith( | ||
163 | expect.objectContaining({ | ||
164 | sort: ['timestamp,asc', 'id'] | ||
165 | }) | ||
166 | ); | ||
167 | }); | ||
168 | }); | ||
169 | |||
170 | describe('loadPage', () => { | ||
171 | beforeEach(() => { | ||
172 | comp.toDate = getDate(); | ||
173 | comp.fromDate = getDate(false); | ||
174 | comp.previousPage = 1; | ||
175 | spyOn(comp, 'transition'); | ||
176 | }); | ||
177 | |||
178 | it('Should not reload page already shown', () => { | ||
179 | // WHEN | ||
180 | comp.loadPage(1); | ||
181 | |||
182 | // THEN | ||
183 | expect(comp.transition).not.toBeCalled(); | ||
184 | }); | ||
185 | |||
186 | it('Should load new page', () => { | ||
187 | // WHEN | ||
188 | comp.loadPage(2); | ||
189 | |||
190 | // THEN | ||
191 | expect(comp.previousPage).toBe(2); | ||
192 | expect(comp.transition).toBeCalled(); | ||
193 | }); | ||
194 | }); | ||
195 | |||
196 | describe('transition', () => { | ||
197 | beforeEach(() => { | ||
198 | spyOn(service, 'query').and.returnValue(of(new HttpResponse({ body: null }))); | ||
199 | }); | ||
200 | |||
201 | it('Should not query data if fromDate and toDate are empty', () => { | ||
202 | // WHEN | ||
203 | comp.transition(); | ||
204 | |||
205 | // THEN | ||
206 | expect(comp.canLoad()).toBe(false); | ||
207 | expect(service.query).not.toBeCalled(); | ||
208 | }); | ||
209 | |||
210 | it('Should query data if fromDate and toDate are not empty', () => { | ||
211 | // GIVEN | ||
212 | comp.toDate = getDate(); | ||
213 | comp.fromDate = getDate(false); | ||
214 | |||
215 | // WHEN | ||
216 | comp.transition(); | ||
217 | |||
218 | // THEN | ||
219 | expect(comp.canLoad()).toBe(true); | ||
220 | expect(service.query).toBeCalled(); | ||
221 | }); | ||
222 | }); | ||
223 | }); | ||
224 | }); |
File src/test/javascript/spec/app/admin/audits/audits.service.spec.ts added (mode: 100644) (index 0000000..d5073e2) | |||
1 | import { TestBed } from '@angular/core/testing'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | import { HttpResponse, HttpErrorResponse } from '@angular/common/http'; | ||
4 | |||
5 | import { AuditsService, AuditsQuery } from 'app/admin/audits/audits.service'; | ||
6 | import { Audit } from 'app/admin/audits/audit.model'; | ||
7 | import { SERVER_API_URL } from 'app/app.constants'; | ||
8 | |||
9 | describe('Service Tests', () => { | ||
10 | describe('Audits Service', () => { | ||
11 | let service: AuditsService; | ||
12 | let httpMock: HttpTestingController; | ||
13 | const fakeRequest: AuditsQuery = { page: 0, size: 0, sort: [], fromDate: '', toDate: '' }; | ||
14 | |||
15 | beforeEach(() => { | ||
16 | TestBed.configureTestingModule({ | ||
17 | imports: [HttpClientTestingModule] | ||
18 | }); | ||
19 | |||
20 | service = TestBed.get(AuditsService); | ||
21 | httpMock = TestBed.get(HttpTestingController); | ||
22 | }); | ||
23 | |||
24 | afterEach(() => { | ||
25 | httpMock.verify(); | ||
26 | }); | ||
27 | |||
28 | describe('Service methods', () => { | ||
29 | it('should call correct URL', () => { | ||
30 | service.query(fakeRequest).subscribe(); | ||
31 | |||
32 | const req = httpMock.expectOne({ method: 'GET' }); | ||
33 | const resourceUrl = SERVER_API_URL + 'management/audits'; | ||
34 | expect(req.request.url).toEqual(resourceUrl); | ||
35 | }); | ||
36 | |||
37 | it('should return Audits', () => { | ||
38 | let expectedResult: HttpResponse<Audit[]> = new HttpResponse({ body: [] }); | ||
39 | const audit = new Audit({ remoteAddress: '127.0.0.1', sessionId: '123' }, 'user', '20140101', 'AUTHENTICATION_SUCCESS'); | ||
40 | |||
41 | service.query(fakeRequest).subscribe(received => { | ||
42 | expectedResult = received; | ||
43 | }); | ||
44 | |||
45 | const req = httpMock.expectOne({ method: 'GET' }); | ||
46 | req.flush([audit]); | ||
47 | let audits: Audit[] = []; | ||
48 | if (expectedResult.body !== null) { | ||
49 | audits = expectedResult.body; | ||
50 | } | ||
51 | expect(audits.length).toBe(1); | ||
52 | expect(audits[0]).toEqual(audit); | ||
53 | }); | ||
54 | |||
55 | it('should propagate not found response', () => { | ||
56 | let expectedResult = 0; | ||
57 | service.query(fakeRequest).subscribe(null, (error: HttpErrorResponse) => { | ||
58 | expectedResult = error.status; | ||
59 | }); | ||
60 | |||
61 | const req = httpMock.expectOne({ method: 'GET' }); | ||
62 | req.flush('Invalid request parameters', { | ||
63 | status: 404, | ||
64 | statusText: 'Bad Request' | ||
65 | }); | ||
66 | expect(expectedResult).toEqual(404); | ||
67 | }); | ||
68 | }); | ||
69 | }); | ||
70 | }); |
File src/test/javascript/spec/app/admin/configuration/configuration.component.spec.ts added (mode: 100644) (index 0000000..ed4eb8e) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { of } from 'rxjs'; | ||
3 | |||
4 | import { HonlapTestModule } from '../../../test.module'; | ||
5 | import { ConfigurationComponent } from 'app/admin/configuration/configuration.component'; | ||
6 | import { ConfigurationService, Bean, PropertySource } from 'app/admin/configuration/configuration.service'; | ||
7 | |||
8 | describe('Component Tests', () => { | ||
9 | describe('ConfigurationComponent', () => { | ||
10 | let comp: ConfigurationComponent; | ||
11 | let fixture: ComponentFixture<ConfigurationComponent>; | ||
12 | let service: ConfigurationService; | ||
13 | |||
14 | beforeEach(async(() => { | ||
15 | TestBed.configureTestingModule({ | ||
16 | imports: [HonlapTestModule], | ||
17 | declarations: [ConfigurationComponent], | ||
18 | providers: [ConfigurationService] | ||
19 | }) | ||
20 | .overrideTemplate(ConfigurationComponent, '') | ||
21 | .compileComponents(); | ||
22 | })); | ||
23 | |||
24 | beforeEach(() => { | ||
25 | fixture = TestBed.createComponent(ConfigurationComponent); | ||
26 | comp = fixture.componentInstance; | ||
27 | service = fixture.debugElement.injector.get(ConfigurationService); | ||
28 | }); | ||
29 | |||
30 | describe('OnInit', () => { | ||
31 | it('Should call load all on init', () => { | ||
32 | // GIVEN | ||
33 | const beans: Bean[] = [ | ||
34 | { | ||
35 | prefix: 'jhipster', | ||
36 | properties: { | ||
37 | clientApp: { | ||
38 | name: 'jhipsterApp' | ||
39 | } | ||
40 | } | ||
41 | } | ||
42 | ]; | ||
43 | const propertySources: PropertySource[] = [ | ||
44 | { | ||
45 | name: 'server.ports', | ||
46 | properties: { | ||
47 | 'local.server.port': { | ||
48 | value: '8080' | ||
49 | } | ||
50 | } | ||
51 | } | ||
52 | ]; | ||
53 | spyOn(service, 'getBeans').and.returnValue(of(beans)); | ||
54 | spyOn(service, 'getPropertySources').and.returnValue(of(propertySources)); | ||
55 | |||
56 | // WHEN | ||
57 | comp.ngOnInit(); | ||
58 | |||
59 | // THEN | ||
60 | expect(service.getBeans).toHaveBeenCalled(); | ||
61 | expect(service.getPropertySources).toHaveBeenCalled(); | ||
62 | expect(comp.allBeans).toEqual(beans); | ||
63 | expect(comp.beans).toEqual(beans); | ||
64 | expect(comp.propertySources).toEqual(propertySources); | ||
65 | }); | ||
66 | }); | ||
67 | }); | ||
68 | }); |
File src/test/javascript/spec/app/admin/configuration/configuration.service.spec.ts added (mode: 100644) (index 0000000..2715a8f) | |||
1 | import { TestBed } from '@angular/core/testing'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | |||
4 | import { ConfigurationService, ConfigProps, Env, Bean, PropertySource } from 'app/admin/configuration/configuration.service'; | ||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | describe('Service Tests', () => { | ||
8 | describe('Logs Service', () => { | ||
9 | let service: ConfigurationService; | ||
10 | let httpMock: HttpTestingController; | ||
11 | let expectedResult: Bean[] | PropertySource[] | null; | ||
12 | |||
13 | beforeEach(() => { | ||
14 | TestBed.configureTestingModule({ | ||
15 | imports: [HttpClientTestingModule] | ||
16 | }); | ||
17 | |||
18 | expectedResult = null; | ||
19 | service = TestBed.get(ConfigurationService); | ||
20 | httpMock = TestBed.get(HttpTestingController); | ||
21 | }); | ||
22 | |||
23 | afterEach(() => { | ||
24 | httpMock.verify(); | ||
25 | }); | ||
26 | |||
27 | describe('Service methods', () => { | ||
28 | it('should call correct URL', () => { | ||
29 | service.getBeans().subscribe(); | ||
30 | |||
31 | const req = httpMock.expectOne({ method: 'GET' }); | ||
32 | const resourceUrl = SERVER_API_URL + 'management/configprops'; | ||
33 | expect(req.request.url).toEqual(resourceUrl); | ||
34 | }); | ||
35 | |||
36 | it('should get the config', () => { | ||
37 | const bean: Bean = { | ||
38 | prefix: 'jhipster', | ||
39 | properties: { | ||
40 | clientApp: { | ||
41 | name: 'jhipsterApp' | ||
42 | } | ||
43 | } | ||
44 | }; | ||
45 | const configProps: ConfigProps = { | ||
46 | contexts: { | ||
47 | jhipster: { | ||
48 | beans: { | ||
49 | 'io.github.jhipster.config.JHipsterProperties': bean | ||
50 | } | ||
51 | } | ||
52 | } | ||
53 | }; | ||
54 | service.getBeans().subscribe(received => (expectedResult = received)); | ||
55 | |||
56 | const req = httpMock.expectOne({ method: 'GET' }); | ||
57 | req.flush(configProps); | ||
58 | expect(expectedResult).toEqual([bean]); | ||
59 | }); | ||
60 | |||
61 | it('should get the env', () => { | ||
62 | const propertySources: PropertySource[] = [ | ||
63 | { | ||
64 | name: 'server.ports', | ||
65 | properties: { | ||
66 | 'local.server.port': { | ||
67 | value: '8080' | ||
68 | } | ||
69 | } | ||
70 | } | ||
71 | ]; | ||
72 | const env: Env = { propertySources }; | ||
73 | service.getPropertySources().subscribe(received => (expectedResult = received)); | ||
74 | |||
75 | const req = httpMock.expectOne({ method: 'GET' }); | ||
76 | req.flush(env); | ||
77 | expect(expectedResult).toEqual(propertySources); | ||
78 | }); | ||
79 | }); | ||
80 | }); | ||
81 | }); |
File src/test/javascript/spec/app/admin/health/health.component.spec.ts added (mode: 100644) (index 0000000..2131dba) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { of, throwError } from 'rxjs'; | ||
4 | |||
5 | import { HonlapTestModule } from '../../../test.module'; | ||
6 | import { HealthComponent } from 'app/admin/health/health.component'; | ||
7 | import { HealthService, Health } from 'app/admin/health/health.service'; | ||
8 | |||
9 | describe('Component Tests', () => { | ||
10 | describe('HealthComponent', () => { | ||
11 | let comp: HealthComponent; | ||
12 | let fixture: ComponentFixture<HealthComponent>; | ||
13 | let service: HealthService; | ||
14 | |||
15 | beforeEach(async(() => { | ||
16 | TestBed.configureTestingModule({ | ||
17 | imports: [HonlapTestModule], | ||
18 | declarations: [HealthComponent] | ||
19 | }) | ||
20 | .overrideTemplate(HealthComponent, '') | ||
21 | .compileComponents(); | ||
22 | })); | ||
23 | |||
24 | beforeEach(() => { | ||
25 | fixture = TestBed.createComponent(HealthComponent); | ||
26 | comp = fixture.componentInstance; | ||
27 | service = fixture.debugElement.injector.get(HealthService); | ||
28 | }); | ||
29 | |||
30 | describe('getBadgeClass', () => { | ||
31 | it('should get badge class', () => { | ||
32 | const upBadgeClass = comp.getBadgeClass('UP'); | ||
33 | const downBadgeClass = comp.getBadgeClass('DOWN'); | ||
34 | expect(upBadgeClass).toEqual('badge-success'); | ||
35 | expect(downBadgeClass).toEqual('badge-danger'); | ||
36 | }); | ||
37 | }); | ||
38 | |||
39 | describe('refresh', () => { | ||
40 | it('should call refresh on init', () => { | ||
41 | // GIVEN | ||
42 | const health: Health = { status: 'UP', components: { mail: { status: 'UP', details: 'mailDetails' } } }; | ||
43 | spyOn(service, 'checkHealth').and.returnValue(of(health)); | ||
44 | |||
45 | // WHEN | ||
46 | comp.ngOnInit(); | ||
47 | |||
48 | // THEN | ||
49 | expect(service.checkHealth).toHaveBeenCalled(); | ||
50 | expect(comp.health).toEqual(health); | ||
51 | }); | ||
52 | |||
53 | it('should handle a 503 on refreshing health data', () => { | ||
54 | // GIVEN | ||
55 | const health: Health = { status: 'DOWN', components: { mail: { status: 'DOWN', details: 'mailDetails' } } }; | ||
56 | spyOn(service, 'checkHealth').and.returnValue(throwError(new HttpErrorResponse({ status: 503, error: health }))); | ||
57 | |||
58 | // WHEN | ||
59 | comp.refresh(); | ||
60 | |||
61 | // THEN | ||
62 | expect(service.checkHealth).toHaveBeenCalled(); | ||
63 | expect(comp.health).toEqual(health); | ||
64 | }); | ||
65 | }); | ||
66 | }); | ||
67 | }); |
File src/test/javascript/spec/app/admin/logs/logs.component.spec.ts added (mode: 100644) (index 0000000..ccb0ed7) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { of } from 'rxjs'; | ||
3 | |||
4 | import { HonlapTestModule } from '../../../test.module'; | ||
5 | import { LogsComponent } from 'app/admin/logs/logs.component'; | ||
6 | import { LogsService } from 'app/admin/logs/logs.service'; | ||
7 | import { Log } from 'app/admin/logs/log.model'; | ||
8 | |||
9 | describe('Component Tests', () => { | ||
10 | describe('LogsComponent', () => { | ||
11 | let comp: LogsComponent; | ||
12 | let fixture: ComponentFixture<LogsComponent>; | ||
13 | let service: LogsService; | ||
14 | |||
15 | beforeEach(async(() => { | ||
16 | TestBed.configureTestingModule({ | ||
17 | imports: [HonlapTestModule], | ||
18 | declarations: [LogsComponent], | ||
19 | providers: [LogsService] | ||
20 | }) | ||
21 | .overrideTemplate(LogsComponent, '') | ||
22 | .compileComponents(); | ||
23 | })); | ||
24 | |||
25 | beforeEach(() => { | ||
26 | fixture = TestBed.createComponent(LogsComponent); | ||
27 | comp = fixture.componentInstance; | ||
28 | service = fixture.debugElement.injector.get(LogsService); | ||
29 | }); | ||
30 | |||
31 | describe('OnInit', () => { | ||
32 | it('should set all default values correctly', () => { | ||
33 | expect(comp.filter).toBe(''); | ||
34 | expect(comp.orderProp).toBe('name'); | ||
35 | expect(comp.reverse).toBe(false); | ||
36 | }); | ||
37 | |||
38 | it('Should call load all on init', () => { | ||
39 | // GIVEN | ||
40 | const log = new Log('main', 'WARN'); | ||
41 | spyOn(service, 'findAll').and.returnValue( | ||
42 | of({ | ||
43 | loggers: { | ||
44 | main: { | ||
45 | effectiveLevel: 'WARN' | ||
46 | } | ||
47 | } | ||
48 | }) | ||
49 | ); | ||
50 | |||
51 | // WHEN | ||
52 | comp.ngOnInit(); | ||
53 | |||
54 | // THEN | ||
55 | expect(service.findAll).toHaveBeenCalled(); | ||
56 | expect(comp.loggers && comp.loggers[0]).toEqual(jasmine.objectContaining(log)); | ||
57 | }); | ||
58 | }); | ||
59 | |||
60 | describe('change log level', () => { | ||
61 | it('should change log level correctly', () => { | ||
62 | // GIVEN | ||
63 | const log = new Log('main', 'ERROR'); | ||
64 | spyOn(service, 'changeLevel').and.returnValue(of({})); | ||
65 | spyOn(service, 'findAll').and.returnValue( | ||
66 | of({ | ||
67 | loggers: { | ||
68 | main: { | ||
69 | effectiveLevel: 'ERROR' | ||
70 | } | ||
71 | } | ||
72 | }) | ||
73 | ); | ||
74 | |||
75 | // WHEN | ||
76 | comp.changeLevel('main', 'ERROR'); | ||
77 | |||
78 | // THEN | ||
79 | expect(service.changeLevel).toHaveBeenCalled(); | ||
80 | expect(service.findAll).toHaveBeenCalled(); | ||
81 | expect(comp.loggers && comp.loggers[0]).toEqual(jasmine.objectContaining(log)); | ||
82 | }); | ||
83 | }); | ||
84 | }); | ||
85 | }); |
File src/test/javascript/spec/app/admin/logs/logs.service.spec.ts added (mode: 100644) (index 0000000..bccec0d) | |||
1 | import { TestBed } from '@angular/core/testing'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | |||
4 | import { LogsService } from 'app/admin/logs/logs.service'; | ||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | describe('Service Tests', () => { | ||
8 | describe('Logs Service', () => { | ||
9 | let service: LogsService; | ||
10 | let httpMock: HttpTestingController; | ||
11 | |||
12 | beforeEach(() => { | ||
13 | TestBed.configureTestingModule({ | ||
14 | imports: [HttpClientTestingModule] | ||
15 | }); | ||
16 | |||
17 | service = TestBed.get(LogsService); | ||
18 | httpMock = TestBed.get(HttpTestingController); | ||
19 | }); | ||
20 | |||
21 | afterEach(() => { | ||
22 | httpMock.verify(); | ||
23 | }); | ||
24 | |||
25 | describe('Service methods', () => { | ||
26 | it('should call correct URL', () => { | ||
27 | service.findAll().subscribe(); | ||
28 | |||
29 | const req = httpMock.expectOne({ method: 'GET' }); | ||
30 | const resourceUrl = SERVER_API_URL + 'management/loggers'; | ||
31 | expect(req.request.url).toEqual(resourceUrl); | ||
32 | }); | ||
33 | |||
34 | it('should change log level', () => { | ||
35 | service.changeLevel('main', 'ERROR').subscribe(); | ||
36 | |||
37 | const req = httpMock.expectOne({ method: 'POST' }); | ||
38 | const resourceUrl = SERVER_API_URL + 'management/loggers/main'; | ||
39 | expect(req.request.url).toEqual(resourceUrl); | ||
40 | expect(req.request.body).toEqual({ configuredLevel: 'ERROR' }); | ||
41 | }); | ||
42 | }); | ||
43 | }); | ||
44 | }); |
File src/test/javascript/spec/app/admin/metrics/metrics.component.spec.ts added (mode: 100644) (index 0000000..c17b8f7) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { of } from 'rxjs'; | ||
3 | |||
4 | import { HonlapTestModule } from '../../../test.module'; | ||
5 | import { MetricsComponent } from 'app/admin/metrics/metrics.component'; | ||
6 | import { MetricsService } from 'app/admin/metrics/metrics.service'; | ||
7 | |||
8 | describe('Component Tests', () => { | ||
9 | describe('MetricsComponent', () => { | ||
10 | let comp: MetricsComponent; | ||
11 | let fixture: ComponentFixture<MetricsComponent>; | ||
12 | let service: MetricsService; | ||
13 | |||
14 | beforeEach(async(() => { | ||
15 | TestBed.configureTestingModule({ | ||
16 | imports: [HonlapTestModule], | ||
17 | declarations: [MetricsComponent] | ||
18 | }) | ||
19 | .overrideTemplate(MetricsComponent, '') | ||
20 | .compileComponents(); | ||
21 | })); | ||
22 | |||
23 | beforeEach(() => { | ||
24 | fixture = TestBed.createComponent(MetricsComponent); | ||
25 | comp = fixture.componentInstance; | ||
26 | service = fixture.debugElement.injector.get(MetricsService); | ||
27 | }); | ||
28 | |||
29 | describe('refresh', () => { | ||
30 | it('should call refresh on init', () => { | ||
31 | // GIVEN | ||
32 | const response = { | ||
33 | timers: { | ||
34 | service: 'test', | ||
35 | unrelatedKey: 'test' | ||
36 | }, | ||
37 | gauges: { | ||
38 | 'jcache.statistics': { | ||
39 | value: 2 | ||
40 | }, | ||
41 | unrelatedKey: 'test' | ||
42 | } | ||
43 | }; | ||
44 | spyOn(service, 'getMetrics').and.returnValue(of(response)); | ||
45 | |||
46 | // WHEN | ||
47 | comp.ngOnInit(); | ||
48 | |||
49 | // THEN | ||
50 | expect(service.getMetrics).toHaveBeenCalled(); | ||
51 | }); | ||
52 | }); | ||
53 | }); | ||
54 | }); |
File src/test/javascript/spec/app/admin/metrics/metrics.service.spec.ts added (mode: 100644) (index 0000000..c86b4af) | |||
1 | import { TestBed } from '@angular/core/testing'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | |||
4 | import { MetricsService, Metrics, ThreadDump } from 'app/admin/metrics/metrics.service'; | ||
5 | import { SERVER_API_URL } from 'app/app.constants'; | ||
6 | |||
7 | describe('Service Tests', () => { | ||
8 | describe('Logs Service', () => { | ||
9 | let service: MetricsService; | ||
10 | let httpMock: HttpTestingController; | ||
11 | |||
12 | beforeEach(() => { | ||
13 | TestBed.configureTestingModule({ | ||
14 | imports: [HttpClientTestingModule] | ||
15 | }); | ||
16 | service = TestBed.get(MetricsService); | ||
17 | httpMock = TestBed.get(HttpTestingController); | ||
18 | }); | ||
19 | |||
20 | afterEach(() => { | ||
21 | httpMock.verify(); | ||
22 | }); | ||
23 | |||
24 | describe('Service methods', () => { | ||
25 | it('should call correct URL', () => { | ||
26 | service.getMetrics().subscribe(); | ||
27 | |||
28 | const req = httpMock.expectOne({ method: 'GET' }); | ||
29 | const resourceUrl = SERVER_API_URL + 'management/jhimetrics'; | ||
30 | expect(req.request.url).toEqual(resourceUrl); | ||
31 | }); | ||
32 | |||
33 | it('should return Metrics', () => { | ||
34 | let expectedResult: Metrics | null = null; | ||
35 | const metrics: Metrics = { | ||
36 | jvm: {}, | ||
37 | 'http.server.requests': {}, | ||
38 | cache: {}, | ||
39 | services: {}, | ||
40 | databases: {}, | ||
41 | garbageCollector: {}, | ||
42 | processMetrics: {} | ||
43 | }; | ||
44 | |||
45 | service.getMetrics().subscribe(received => { | ||
46 | expectedResult = received; | ||
47 | }); | ||
48 | |||
49 | const req = httpMock.expectOne({ method: 'GET' }); | ||
50 | req.flush(metrics); | ||
51 | expect(expectedResult).toEqual(metrics); | ||
52 | }); | ||
53 | |||
54 | it('should return Thread Dump', () => { | ||
55 | let expectedResult: ThreadDump | null = null; | ||
56 | const dump: ThreadDump = { threads: [{ name: 'test1', threadState: 'RUNNABLE' }] }; | ||
57 | |||
58 | service.threadDump().subscribe(received => { | ||
59 | expectedResult = received; | ||
60 | }); | ||
61 | |||
62 | const req = httpMock.expectOne({ method: 'GET' }); | ||
63 | req.flush(dump); | ||
64 | expect(expectedResult).toEqual(dump); | ||
65 | }); | ||
66 | }); | ||
67 | }); | ||
68 | }); |
File src/test/javascript/spec/app/admin/user-management/user-management-delete-dialog.component.spec.ts added (mode: 100644) (index 0000000..1f04e99) | |||
1 | import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | import { of } from 'rxjs'; | ||
4 | import { JhiEventManager } from 'ng-jhipster'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { MockEventManager } from '../../../helpers/mock-event-manager.service'; | ||
8 | import { MockActiveModal } from '../../../helpers/mock-active-modal.service'; | ||
9 | import { UserManagementDeleteDialogComponent } from 'app/admin/user-management/user-management-delete-dialog.component'; | ||
10 | import { UserService } from 'app/core/user/user.service'; | ||
11 | |||
12 | describe('Component Tests', () => { | ||
13 | describe('User Management Delete Component', () => { | ||
14 | let comp: UserManagementDeleteDialogComponent; | ||
15 | let fixture: ComponentFixture<UserManagementDeleteDialogComponent>; | ||
16 | let service: UserService; | ||
17 | let mockEventManager: MockEventManager; | ||
18 | let mockActiveModal: MockActiveModal; | ||
19 | |||
20 | beforeEach(async(() => { | ||
21 | TestBed.configureTestingModule({ | ||
22 | imports: [HonlapTestModule], | ||
23 | declarations: [UserManagementDeleteDialogComponent] | ||
24 | }) | ||
25 | .overrideTemplate(UserManagementDeleteDialogComponent, '') | ||
26 | .compileComponents(); | ||
27 | })); | ||
28 | |||
29 | beforeEach(() => { | ||
30 | fixture = TestBed.createComponent(UserManagementDeleteDialogComponent); | ||
31 | comp = fixture.componentInstance; | ||
32 | service = fixture.debugElement.injector.get(UserService); | ||
33 | mockEventManager = TestBed.get(JhiEventManager); | ||
34 | mockActiveModal = TestBed.get(NgbActiveModal); | ||
35 | }); | ||
36 | |||
37 | describe('confirmDelete', () => { | ||
38 | it('Should call delete service on confirmDelete', inject( | ||
39 | [], | ||
40 | fakeAsync(() => { | ||
41 | // GIVEN | ||
42 | spyOn(service, 'delete').and.returnValue(of({})); | ||
43 | |||
44 | // WHEN | ||
45 | comp.confirmDelete('user'); | ||
46 | tick(); | ||
47 | |||
48 | // THEN | ||
49 | expect(service.delete).toHaveBeenCalledWith('user'); | ||
50 | expect(mockActiveModal.closeSpy).toHaveBeenCalled(); | ||
51 | expect(mockEventManager.broadcastSpy).toHaveBeenCalled(); | ||
52 | }) | ||
53 | )); | ||
54 | }); | ||
55 | }); | ||
56 | }); |
File src/test/javascript/spec/app/admin/user-management/user-management-detail.component.spec.ts added (mode: 100644) (index 0000000..55b3a53) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | import { of } from 'rxjs'; | ||
4 | |||
5 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { UserManagementDetailComponent } from 'app/admin/user-management/user-management-detail.component'; | ||
8 | import { User } from 'app/core/user/user.model'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('User Management Detail Component', () => { | ||
12 | let comp: UserManagementDetailComponent; | ||
13 | let fixture: ComponentFixture<UserManagementDetailComponent>; | ||
14 | const route: ActivatedRoute = ({ | ||
15 | data: of({ user: new User(1, 'user', 'first', 'last', 'first@last.com', true, 'en', [Authority.USER], 'admin') }) | ||
16 | } as any) as ActivatedRoute; | ||
17 | |||
18 | beforeEach(async(() => { | ||
19 | TestBed.configureTestingModule({ | ||
20 | imports: [HonlapTestModule], | ||
21 | declarations: [UserManagementDetailComponent], | ||
22 | providers: [ | ||
23 | { | ||
24 | provide: ActivatedRoute, | ||
25 | useValue: route | ||
26 | } | ||
27 | ] | ||
28 | }) | ||
29 | .overrideTemplate(UserManagementDetailComponent, '') | ||
30 | .compileComponents(); | ||
31 | })); | ||
32 | |||
33 | beforeEach(() => { | ||
34 | fixture = TestBed.createComponent(UserManagementDetailComponent); | ||
35 | comp = fixture.componentInstance; | ||
36 | }); | ||
37 | |||
38 | describe('OnInit', () => { | ||
39 | it('Should call load all on init', () => { | ||
40 | // GIVEN | ||
41 | |||
42 | // WHEN | ||
43 | comp.ngOnInit(); | ||
44 | |||
45 | // THEN | ||
46 | expect(comp.user).toEqual( | ||
47 | jasmine.objectContaining({ | ||
48 | id: 1, | ||
49 | login: 'user', | ||
50 | firstName: 'first', | ||
51 | lastName: 'last', | ||
52 | email: 'first@last.com', | ||
53 | activated: true, | ||
54 | langKey: 'en', | ||
55 | authorities: [Authority.USER], | ||
56 | createdBy: 'admin' | ||
57 | }) | ||
58 | ); | ||
59 | }); | ||
60 | }); | ||
61 | }); | ||
62 | }); |
File src/test/javascript/spec/app/admin/user-management/user-management-update.component.spec.ts added (mode: 100644) (index 0000000..84520c1) | |||
1 | import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { HttpResponse } from '@angular/common/http'; | ||
3 | import { FormBuilder } from '@angular/forms'; | ||
4 | import { ActivatedRoute } from '@angular/router'; | ||
5 | import { of } from 'rxjs'; | ||
6 | |||
7 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
8 | import { HonlapTestModule } from '../../../test.module'; | ||
9 | import { UserManagementUpdateComponent } from 'app/admin/user-management/user-management-update.component'; | ||
10 | import { UserService } from 'app/core/user/user.service'; | ||
11 | import { User } from 'app/core/user/user.model'; | ||
12 | |||
13 | describe('Component Tests', () => { | ||
14 | describe('User Management Update Component', () => { | ||
15 | let comp: UserManagementUpdateComponent; | ||
16 | let fixture: ComponentFixture<UserManagementUpdateComponent>; | ||
17 | let service: UserService; | ||
18 | const route: ActivatedRoute = ({ | ||
19 | data: of({ user: new User(1, 'user', 'first', 'last', 'first@last.com', true, 'en', [Authority.USER], 'admin') }) | ||
20 | } as any) as ActivatedRoute; | ||
21 | |||
22 | beforeEach(async(() => { | ||
23 | TestBed.configureTestingModule({ | ||
24 | imports: [HonlapTestModule], | ||
25 | declarations: [UserManagementUpdateComponent], | ||
26 | providers: [ | ||
27 | FormBuilder, | ||
28 | { | ||
29 | provide: ActivatedRoute, | ||
30 | useValue: route | ||
31 | } | ||
32 | ] | ||
33 | }) | ||
34 | .overrideTemplate(UserManagementUpdateComponent, '') | ||
35 | .compileComponents(); | ||
36 | })); | ||
37 | |||
38 | beforeEach(() => { | ||
39 | fixture = TestBed.createComponent(UserManagementUpdateComponent); | ||
40 | comp = fixture.componentInstance; | ||
41 | service = fixture.debugElement.injector.get(UserService); | ||
42 | }); | ||
43 | |||
44 | describe('OnInit', () => { | ||
45 | it('Should load authorities and language on init', inject( | ||
46 | [], | ||
47 | fakeAsync(() => { | ||
48 | // GIVEN | ||
49 | spyOn(service, 'authorities').and.returnValue(of(['USER'])); | ||
50 | |||
51 | // WHEN | ||
52 | comp.ngOnInit(); | ||
53 | |||
54 | // THEN | ||
55 | expect(service.authorities).toHaveBeenCalled(); | ||
56 | expect(comp.authorities).toEqual(['USER']); | ||
57 | }) | ||
58 | )); | ||
59 | }); | ||
60 | |||
61 | describe('save', () => { | ||
62 | it('Should call update service on save for existing user', inject( | ||
63 | [], | ||
64 | fakeAsync(() => { | ||
65 | // GIVEN | ||
66 | const entity = new User(123); | ||
67 | spyOn(service, 'update').and.returnValue( | ||
68 | of( | ||
69 | new HttpResponse({ | ||
70 | body: entity | ||
71 | }) | ||
72 | ) | ||
73 | ); | ||
74 | comp.user = entity; | ||
75 | comp.editForm.patchValue({ id: entity.id }); | ||
76 | // WHEN | ||
77 | comp.save(); | ||
78 | tick(); // simulate async | ||
79 | |||
80 | // THEN | ||
81 | expect(service.update).toHaveBeenCalledWith(entity); | ||
82 | expect(comp.isSaving).toEqual(false); | ||
83 | }) | ||
84 | )); | ||
85 | |||
86 | it('Should call create service on save for new user', inject( | ||
87 | [], | ||
88 | fakeAsync(() => { | ||
89 | // GIVEN | ||
90 | const entity = new User(); | ||
91 | spyOn(service, 'create').and.returnValue(of(new HttpResponse({ body: entity }))); | ||
92 | comp.user = entity; | ||
93 | // WHEN | ||
94 | comp.save(); | ||
95 | tick(); // simulate async | ||
96 | |||
97 | // THEN | ||
98 | expect(service.create).toHaveBeenCalledWith(entity); | ||
99 | expect(comp.isSaving).toEqual(false); | ||
100 | }) | ||
101 | )); | ||
102 | }); | ||
103 | }); | ||
104 | }); |
File src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts added (mode: 100644) (index 0000000..76eb140) | |||
1 | import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; | ||
3 | import { of } from 'rxjs'; | ||
4 | |||
5 | import { HonlapTestModule } from '../../../test.module'; | ||
6 | import { UserManagementComponent } from 'app/admin/user-management/user-management.component'; | ||
7 | import { UserService } from 'app/core/user/user.service'; | ||
8 | import { User } from 'app/core/user/user.model'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('User Management Component', () => { | ||
12 | let comp: UserManagementComponent; | ||
13 | let fixture: ComponentFixture<UserManagementComponent>; | ||
14 | let service: UserService; | ||
15 | |||
16 | beforeEach(async(() => { | ||
17 | TestBed.configureTestingModule({ | ||
18 | imports: [HonlapTestModule], | ||
19 | declarations: [UserManagementComponent] | ||
20 | }) | ||
21 | .overrideTemplate(UserManagementComponent, '') | ||
22 | .compileComponents(); | ||
23 | })); | ||
24 | |||
25 | beforeEach(() => { | ||
26 | fixture = TestBed.createComponent(UserManagementComponent); | ||
27 | comp = fixture.componentInstance; | ||
28 | service = fixture.debugElement.injector.get(UserService); | ||
29 | }); | ||
30 | |||
31 | describe('OnInit', () => { | ||
32 | it('Should call load all on init', inject( | ||
33 | [], | ||
34 | fakeAsync(() => { | ||
35 | // GIVEN | ||
36 | const headers = new HttpHeaders().append('link', 'link;link'); | ||
37 | spyOn(service, 'query').and.returnValue( | ||
38 | of( | ||
39 | new HttpResponse({ | ||
40 | body: [new User(123)], | ||
41 | headers | ||
42 | }) | ||
43 | ) | ||
44 | ); | ||
45 | |||
46 | // WHEN | ||
47 | comp.ngOnInit(); | ||
48 | tick(); // simulate async | ||
49 | |||
50 | // THEN | ||
51 | expect(service.query).toHaveBeenCalled(); | ||
52 | expect(comp.users && comp.users[0]).toEqual(jasmine.objectContaining({ id: 123 })); | ||
53 | }) | ||
54 | )); | ||
55 | }); | ||
56 | |||
57 | describe('setActive', () => { | ||
58 | it('Should update user and call load all', inject( | ||
59 | [], | ||
60 | fakeAsync(() => { | ||
61 | // GIVEN | ||
62 | const headers = new HttpHeaders().append('link', 'link;link'); | ||
63 | const user = new User(123); | ||
64 | spyOn(service, 'query').and.returnValue( | ||
65 | of( | ||
66 | new HttpResponse({ | ||
67 | body: [user], | ||
68 | headers | ||
69 | }) | ||
70 | ) | ||
71 | ); | ||
72 | spyOn(service, 'update').and.returnValue(of(new HttpResponse({ status: 200 }))); | ||
73 | |||
74 | // WHEN | ||
75 | comp.setActive(user, true); | ||
76 | tick(); // simulate async | ||
77 | |||
78 | // THEN | ||
79 | expect(service.update).toHaveBeenCalledWith({ ...user, activated: true }); | ||
80 | expect(service.query).toHaveBeenCalled(); | ||
81 | expect(comp.users && comp.users[0]).toEqual(jasmine.objectContaining({ id: 123 })); | ||
82 | }) | ||
83 | )); | ||
84 | }); | ||
85 | }); | ||
86 | }); |
File src/test/javascript/spec/app/core/user/account.service.spec.ts added (mode: 100644) (index 0000000..f5e1167) | |||
1 | import { Router } from '@angular/router'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | import { TestBed } from '@angular/core/testing'; | ||
4 | import { JhiDateUtils, JhiLanguageService } from 'ng-jhipster'; | ||
5 | import { NgxWebstorageModule } from 'ngx-webstorage'; | ||
6 | |||
7 | import { SERVER_API_URL } from 'app/app.constants'; | ||
8 | import { AccountService } from 'app/core/auth/account.service'; | ||
9 | import { Account } from 'app/core/user/account.model'; | ||
10 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
11 | import { StateStorageService } from 'app/core/auth/state-storage.service'; | ||
12 | import { MockLanguageService } from '../../../helpers/mock-language.service'; | ||
13 | import { MockRouter } from '../../../helpers/mock-route.service'; | ||
14 | import { MockStateStorageService } from '../../../helpers/mock-state-storage.service'; | ||
15 | |||
16 | function accountWithAuthorities(authorities: string[]): Account { | ||
17 | return { | ||
18 | activated: true, | ||
19 | authorities, | ||
20 | email: '', | ||
21 | firstName: '', | ||
22 | langKey: '', | ||
23 | lastName: '', | ||
24 | login: '', | ||
25 | imageUrl: '' | ||
26 | }; | ||
27 | } | ||
28 | |||
29 | describe('Service Tests', () => { | ||
30 | describe('Account Service', () => { | ||
31 | let service: AccountService; | ||
32 | let httpMock: HttpTestingController; | ||
33 | let storageService: MockStateStorageService; | ||
34 | let router: MockRouter; | ||
35 | |||
36 | beforeEach(() => { | ||
37 | TestBed.configureTestingModule({ | ||
38 | imports: [HttpClientTestingModule, NgxWebstorageModule.forRoot()], | ||
39 | providers: [ | ||
40 | JhiDateUtils, | ||
41 | { | ||
42 | provide: JhiLanguageService, | ||
43 | useClass: MockLanguageService | ||
44 | }, | ||
45 | { | ||
46 | provide: StateStorageService, | ||
47 | useClass: MockStateStorageService | ||
48 | }, | ||
49 | { | ||
50 | provide: Router, | ||
51 | useClass: MockRouter | ||
52 | } | ||
53 | ] | ||
54 | }); | ||
55 | |||
56 | service = TestBed.get(AccountService); | ||
57 | httpMock = TestBed.get(HttpTestingController); | ||
58 | storageService = TestBed.get(StateStorageService); | ||
59 | router = TestBed.get(Router); | ||
60 | }); | ||
61 | |||
62 | afterEach(() => { | ||
63 | httpMock.verify(); | ||
64 | }); | ||
65 | |||
66 | describe('authenticate', () => { | ||
67 | it('authenticationState should emit null if input is null', () => { | ||
68 | // GIVEN | ||
69 | let userIdentity: Account | null = accountWithAuthorities([]); | ||
70 | service.getAuthenticationState().subscribe(account => (userIdentity = account)); | ||
71 | |||
72 | // WHEN | ||
73 | service.authenticate(null); | ||
74 | |||
75 | // THEN | ||
76 | expect(userIdentity).toBeNull(); | ||
77 | expect(service.isAuthenticated()).toBe(false); | ||
78 | }); | ||
79 | |||
80 | it('authenticationState should emit the same account as was in input parameter', () => { | ||
81 | // GIVEN | ||
82 | const expectedResult = accountWithAuthorities([]); | ||
83 | let userIdentity: Account | null = null; | ||
84 | service.getAuthenticationState().subscribe(account => (userIdentity = account)); | ||
85 | |||
86 | // WHEN | ||
87 | service.authenticate(expectedResult); | ||
88 | |||
89 | // THEN | ||
90 | expect(userIdentity).toEqual(expectedResult); | ||
91 | expect(service.isAuthenticated()).toBe(true); | ||
92 | }); | ||
93 | }); | ||
94 | |||
95 | describe('identity', () => { | ||
96 | it('should call /account if user is undefined', () => { | ||
97 | service.identity().subscribe(); | ||
98 | const req = httpMock.expectOne({ method: 'GET' }); | ||
99 | const resourceUrl = SERVER_API_URL + 'api/account'; | ||
100 | |||
101 | expect(req.request.url).toEqual(`${resourceUrl}`); | ||
102 | }); | ||
103 | |||
104 | it('should call /account only once if not logged out after first authentication and should call /account again if user has logged out', () => { | ||
105 | // Given the user is authenticated | ||
106 | service.identity().subscribe(); | ||
107 | httpMock.expectOne({ method: 'GET' }).flush({}); | ||
108 | |||
109 | // When I call | ||
110 | service.identity().subscribe(); | ||
111 | |||
112 | // Then there is no second request | ||
113 | httpMock.expectNone({ method: 'GET' }); | ||
114 | |||
115 | // When I log out | ||
116 | service.authenticate(null); | ||
117 | // and then call | ||
118 | service.identity().subscribe(); | ||
119 | |||
120 | // Then there is a new request | ||
121 | httpMock.expectOne({ method: 'GET' }); | ||
122 | }); | ||
123 | |||
124 | describe('navigateToStoredUrl', () => { | ||
125 | it('should navigate to the previous stored url post successful authentication', () => { | ||
126 | // GIVEN | ||
127 | storageService.setResponse('admin/users?page=0'); | ||
128 | |||
129 | // WHEN | ||
130 | service.identity().subscribe(); | ||
131 | httpMock.expectOne({ method: 'GET' }).flush({}); | ||
132 | |||
133 | // THEN | ||
134 | expect(storageService.getUrlSpy).toHaveBeenCalledTimes(1); | ||
135 | expect(storageService.clearUrlSpy).toHaveBeenCalledTimes(1); | ||
136 | expect(router.navigateByUrlSpy).toHaveBeenCalledWith('admin/users?page=0'); | ||
137 | }); | ||
138 | |||
139 | it('should not navigate to the previous stored url when authentication fails', () => { | ||
140 | // WHEN | ||
141 | service.identity().subscribe(); | ||
142 | httpMock.expectOne({ method: 'GET' }).error(new ErrorEvent('')); | ||
143 | |||
144 | // THEN | ||
145 | expect(storageService.getUrlSpy).not.toHaveBeenCalled(); | ||
146 | expect(storageService.clearUrlSpy).not.toHaveBeenCalled(); | ||
147 | expect(router.navigateByUrlSpy).not.toHaveBeenCalled(); | ||
148 | }); | ||
149 | |||
150 | it('should not navigate to the previous stored url when no such url exists post successful authentication', () => { | ||
151 | // GIVEN | ||
152 | storageService.setResponse(null); | ||
153 | |||
154 | // WHEN | ||
155 | service.identity().subscribe(); | ||
156 | httpMock.expectOne({ method: 'GET' }).flush({}); | ||
157 | |||
158 | // THEN | ||
159 | expect(storageService.getUrlSpy).toHaveBeenCalledTimes(1); | ||
160 | expect(storageService.clearUrlSpy).not.toHaveBeenCalled(); | ||
161 | expect(router.navigateByUrlSpy).not.toHaveBeenCalled(); | ||
162 | }); | ||
163 | }); | ||
164 | }); | ||
165 | |||
166 | describe('hasAnyAuthority', () => { | ||
167 | describe('hasAnyAuthority string parameter', () => { | ||
168 | it('should return false if user is not logged', () => { | ||
169 | const hasAuthority = service.hasAnyAuthority(Authority.USER); | ||
170 | expect(hasAuthority).toBe(false); | ||
171 | }); | ||
172 | |||
173 | it('should return false if user is logged and has not authority', () => { | ||
174 | service.authenticate(accountWithAuthorities([Authority.USER])); | ||
175 | |||
176 | const hasAuthority = service.hasAnyAuthority(Authority.ADMIN); | ||
177 | |||
178 | expect(hasAuthority).toBe(false); | ||
179 | }); | ||
180 | |||
181 | it('should return true if user is logged and has authority', () => { | ||
182 | service.authenticate(accountWithAuthorities([Authority.USER])); | ||
183 | |||
184 | const hasAuthority = service.hasAnyAuthority(Authority.USER); | ||
185 | |||
186 | expect(hasAuthority).toBe(true); | ||
187 | }); | ||
188 | }); | ||
189 | |||
190 | describe('hasAnyAuthority array parameter', () => { | ||
191 | it('should return false if user is not logged', () => { | ||
192 | const hasAuthority = service.hasAnyAuthority([Authority.USER]); | ||
193 | expect(hasAuthority).toBeFalsy(); | ||
194 | }); | ||
195 | |||
196 | it('should return false if user is logged and has not authority', () => { | ||
197 | service.authenticate(accountWithAuthorities([Authority.USER])); | ||
198 | |||
199 | const hasAuthority = service.hasAnyAuthority([Authority.ADMIN]); | ||
200 | |||
201 | expect(hasAuthority).toBe(false); | ||
202 | }); | ||
203 | |||
204 | it('should return true if user is logged and has authority', () => { | ||
205 | service.authenticate(accountWithAuthorities([Authority.USER])); | ||
206 | |||
207 | const hasAuthority = service.hasAnyAuthority([Authority.USER, Authority.ADMIN]); | ||
208 | |||
209 | expect(hasAuthority).toBe(true); | ||
210 | }); | ||
211 | }); | ||
212 | }); | ||
213 | }); | ||
214 | }); |
File src/test/javascript/spec/app/core/user/user.service.spec.ts added (mode: 100644) (index 0000000..2811acb) | |||
1 | import { TestBed } from '@angular/core/testing'; | ||
2 | import { HttpErrorResponse } from '@angular/common/http'; | ||
3 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
4 | import { JhiDateUtils } from 'ng-jhipster'; | ||
5 | |||
6 | import { Authority } from 'app/shared/constants/authority.constants'; | ||
7 | import { UserService } from 'app/core/user/user.service'; | ||
8 | import { User } from 'app/core/user/user.model'; | ||
9 | import { SERVER_API_URL } from 'app/app.constants'; | ||
10 | |||
11 | describe('Service Tests', () => { | ||
12 | describe('User Service', () => { | ||
13 | let service: UserService; | ||
14 | let httpMock: HttpTestingController; | ||
15 | |||
16 | beforeEach(() => { | ||
17 | TestBed.configureTestingModule({ | ||
18 | imports: [HttpClientTestingModule], | ||
19 | providers: [JhiDateUtils] | ||
20 | }); | ||
21 | |||
22 | service = TestBed.get(UserService); | ||
23 | httpMock = TestBed.get(HttpTestingController); | ||
24 | }); | ||
25 | |||
26 | afterEach(() => { | ||
27 | httpMock.verify(); | ||
28 | }); | ||
29 | |||
30 | describe('Service methods', () => { | ||
31 | it('should call correct URL', () => { | ||
32 | service.find('user').subscribe(); | ||
33 | |||
34 | const req = httpMock.expectOne({ method: 'GET' }); | ||
35 | const resourceUrl = SERVER_API_URL + 'api/users'; | ||
36 | expect(req.request.url).toEqual(`${resourceUrl}/user`); | ||
37 | }); | ||
38 | |||
39 | it('should return User', () => { | ||
40 | let expectedResult: string | undefined; | ||
41 | |||
42 | service.find('user').subscribe(received => { | ||
43 | expectedResult = received.login; | ||
44 | }); | ||
45 | |||
46 | const req = httpMock.expectOne({ method: 'GET' }); | ||
47 | req.flush(new User(1, 'user')); | ||
48 | expect(expectedResult).toEqual('user'); | ||
49 | }); | ||
50 | |||
51 | it('should return Authorities', () => { | ||
52 | let expectedResult: string[] = []; | ||
53 | |||
54 | service.authorities().subscribe(authorities => { | ||
55 | expectedResult = authorities; | ||
56 | }); | ||
57 | const req = httpMock.expectOne({ method: 'GET' }); | ||
58 | |||
59 | req.flush([Authority.USER, Authority.ADMIN]); | ||
60 | expect(expectedResult).toEqual([Authority.USER, Authority.ADMIN]); | ||
61 | }); | ||
62 | |||
63 | it('should propagate not found response', () => { | ||
64 | let expectedResult = 0; | ||
65 | |||
66 | service.find('user').subscribe(null, (error: HttpErrorResponse) => { | ||
67 | expectedResult = error.status; | ||
68 | }); | ||
69 | |||
70 | const req = httpMock.expectOne({ method: 'GET' }); | ||
71 | req.flush('Invalid request parameters', { | ||
72 | status: 404, | ||
73 | statusText: 'Bad Request' | ||
74 | }); | ||
75 | expect(expectedResult).toEqual(404); | ||
76 | }); | ||
77 | }); | ||
78 | }); | ||
79 | }); |
File src/test/javascript/spec/app/entities/piece-of-news/piece-of-news-delete-dialog.component.spec.ts added (mode: 100644) (index 0000000..63a0850) | |||
1 | import { ComponentFixture, TestBed, inject, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | import { of } from 'rxjs'; | ||
4 | import { JhiEventManager } from 'ng-jhipster'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { MockEventManager } from '../../../helpers/mock-event-manager.service'; | ||
8 | import { MockActiveModal } from '../../../helpers/mock-active-modal.service'; | ||
9 | import { PieceOfNewsDeleteDialogComponent } from 'app/entities/piece-of-news/piece-of-news-delete-dialog.component'; | ||
10 | import { PieceOfNewsService } from 'app/entities/piece-of-news/piece-of-news.service'; | ||
11 | |||
12 | describe('Component Tests', () => { | ||
13 | describe('PieceOfNews Management Delete Component', () => { | ||
14 | let comp: PieceOfNewsDeleteDialogComponent; | ||
15 | let fixture: ComponentFixture<PieceOfNewsDeleteDialogComponent>; | ||
16 | let service: PieceOfNewsService; | ||
17 | let mockEventManager: MockEventManager; | ||
18 | let mockActiveModal: MockActiveModal; | ||
19 | |||
20 | beforeEach(() => { | ||
21 | TestBed.configureTestingModule({ | ||
22 | imports: [HonlapTestModule], | ||
23 | declarations: [PieceOfNewsDeleteDialogComponent] | ||
24 | }) | ||
25 | .overrideTemplate(PieceOfNewsDeleteDialogComponent, '') | ||
26 | .compileComponents(); | ||
27 | fixture = TestBed.createComponent(PieceOfNewsDeleteDialogComponent); | ||
28 | comp = fixture.componentInstance; | ||
29 | service = fixture.debugElement.injector.get(PieceOfNewsService); | ||
30 | mockEventManager = TestBed.get(JhiEventManager); | ||
31 | mockActiveModal = TestBed.get(NgbActiveModal); | ||
32 | }); | ||
33 | |||
34 | describe('confirmDelete', () => { | ||
35 | it('Should call delete service on confirmDelete', inject( | ||
36 | [], | ||
37 | fakeAsync(() => { | ||
38 | // GIVEN | ||
39 | spyOn(service, 'delete').and.returnValue(of({})); | ||
40 | |||
41 | // WHEN | ||
42 | comp.confirmDelete(123); | ||
43 | tick(); | ||
44 | |||
45 | // THEN | ||
46 | expect(service.delete).toHaveBeenCalledWith(123); | ||
47 | expect(mockActiveModal.closeSpy).toHaveBeenCalled(); | ||
48 | expect(mockEventManager.broadcastSpy).toHaveBeenCalled(); | ||
49 | }) | ||
50 | )); | ||
51 | |||
52 | it('Should not call delete service on clear', () => { | ||
53 | // GIVEN | ||
54 | spyOn(service, 'delete'); | ||
55 | |||
56 | // WHEN | ||
57 | comp.cancel(); | ||
58 | |||
59 | // THEN | ||
60 | expect(service.delete).not.toHaveBeenCalled(); | ||
61 | expect(mockActiveModal.dismissSpy).toHaveBeenCalled(); | ||
62 | }); | ||
63 | }); | ||
64 | }); | ||
65 | }); |
File src/test/javascript/spec/app/entities/piece-of-news/piece-of-news-detail.component.spec.ts added (mode: 100644) (index 0000000..c123358) | |||
1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
2 | import { ActivatedRoute } from '@angular/router'; | ||
3 | import { of } from 'rxjs'; | ||
4 | |||
5 | import { HonlapTestModule } from '../../../test.module'; | ||
6 | import { PieceOfNewsDetailComponent } from 'app/entities/piece-of-news/piece-of-news-detail.component'; | ||
7 | import { PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
8 | |||
9 | describe('Component Tests', () => { | ||
10 | describe('PieceOfNews Management Detail Component', () => { | ||
11 | let comp: PieceOfNewsDetailComponent; | ||
12 | let fixture: ComponentFixture<PieceOfNewsDetailComponent>; | ||
13 | const route = ({ data: of({ pieceOfNews: new PieceOfNews(123) }) } as any) as ActivatedRoute; | ||
14 | |||
15 | beforeEach(() => { | ||
16 | TestBed.configureTestingModule({ | ||
17 | imports: [HonlapTestModule], | ||
18 | declarations: [PieceOfNewsDetailComponent], | ||
19 | providers: [{ provide: ActivatedRoute, useValue: route }] | ||
20 | }) | ||
21 | .overrideTemplate(PieceOfNewsDetailComponent, '') | ||
22 | .compileComponents(); | ||
23 | fixture = TestBed.createComponent(PieceOfNewsDetailComponent); | ||
24 | comp = fixture.componentInstance; | ||
25 | }); | ||
26 | |||
27 | describe('OnInit', () => { | ||
28 | it('Should load pieceOfNews on init', () => { | ||
29 | // WHEN | ||
30 | comp.ngOnInit(); | ||
31 | |||
32 | // THEN | ||
33 | expect(comp.pieceOfNews).toEqual(jasmine.objectContaining({ id: 123 })); | ||
34 | }); | ||
35 | }); | ||
36 | }); | ||
37 | }); |
File src/test/javascript/spec/app/entities/piece-of-news/piece-of-news-update.component.spec.ts added (mode: 100644) (index 0000000..997fc7a) | |||
1 | import { ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { HttpResponse } from '@angular/common/http'; | ||
3 | import { FormBuilder } from '@angular/forms'; | ||
4 | import { of } from 'rxjs'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { PieceOfNewsUpdateComponent } from 'app/entities/piece-of-news/piece-of-news-update.component'; | ||
8 | import { PieceOfNewsService } from 'app/entities/piece-of-news/piece-of-news.service'; | ||
9 | import { PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
10 | |||
11 | describe('Component Tests', () => { | ||
12 | describe('PieceOfNews Management Update Component', () => { | ||
13 | let comp: PieceOfNewsUpdateComponent; | ||
14 | let fixture: ComponentFixture<PieceOfNewsUpdateComponent>; | ||
15 | let service: PieceOfNewsService; | ||
16 | |||
17 | beforeEach(() => { | ||
18 | TestBed.configureTestingModule({ | ||
19 | imports: [HonlapTestModule], | ||
20 | declarations: [PieceOfNewsUpdateComponent], | ||
21 | providers: [FormBuilder] | ||
22 | }) | ||
23 | .overrideTemplate(PieceOfNewsUpdateComponent, '') | ||
24 | .compileComponents(); | ||
25 | |||
26 | fixture = TestBed.createComponent(PieceOfNewsUpdateComponent); | ||
27 | comp = fixture.componentInstance; | ||
28 | service = fixture.debugElement.injector.get(PieceOfNewsService); | ||
29 | }); | ||
30 | |||
31 | describe('save', () => { | ||
32 | it('Should call update service on save for existing entity', fakeAsync(() => { | ||
33 | // GIVEN | ||
34 | const entity = new PieceOfNews(123); | ||
35 | spyOn(service, 'update').and.returnValue(of(new HttpResponse({ body: entity }))); | ||
36 | comp.updateForm(entity); | ||
37 | // WHEN | ||
38 | comp.save(); | ||
39 | tick(); // simulate async | ||
40 | |||
41 | // THEN | ||
42 | expect(service.update).toHaveBeenCalledWith(entity); | ||
43 | expect(comp.isSaving).toEqual(false); | ||
44 | })); | ||
45 | |||
46 | it('Should call create service on save for new entity', fakeAsync(() => { | ||
47 | // GIVEN | ||
48 | const entity = new PieceOfNews(); | ||
49 | spyOn(service, 'create').and.returnValue(of(new HttpResponse({ body: entity }))); | ||
50 | comp.updateForm(entity); | ||
51 | // WHEN | ||
52 | comp.save(); | ||
53 | tick(); // simulate async | ||
54 | |||
55 | // THEN | ||
56 | expect(service.create).toHaveBeenCalledWith(entity); | ||
57 | expect(comp.isSaving).toEqual(false); | ||
58 | })); | ||
59 | }); | ||
60 | }); | ||
61 | }); |
File src/test/javascript/spec/app/entities/piece-of-news/piece-of-news.component.spec.ts added (mode: 100644) (index 0000000..f33ba9c) | |||
1 | import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
2 | import { of } from 'rxjs'; | ||
3 | import { HttpHeaders, HttpResponse } from '@angular/common/http'; | ||
4 | import { ActivatedRoute, Data } from '@angular/router'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { PieceOfNewsComponent } from 'app/entities/piece-of-news/piece-of-news.component'; | ||
8 | import { PieceOfNewsService } from 'app/entities/piece-of-news/piece-of-news.service'; | ||
9 | import { PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
10 | |||
11 | describe('Component Tests', () => { | ||
12 | describe('PieceOfNews Management Component', () => { | ||
13 | let comp: PieceOfNewsComponent; | ||
14 | let fixture: ComponentFixture<PieceOfNewsComponent>; | ||
15 | let service: PieceOfNewsService; | ||
16 | |||
17 | beforeEach(() => { | ||
18 | TestBed.configureTestingModule({ | ||
19 | imports: [HonlapTestModule], | ||
20 | declarations: [PieceOfNewsComponent], | ||
21 | providers: [ | ||
22 | { | ||
23 | provide: ActivatedRoute, | ||
24 | useValue: { | ||
25 | data: { | ||
26 | subscribe: (fn: (value: Data) => void) => | ||
27 | fn({ | ||
28 | pagingParams: { | ||
29 | predicate: 'id', | ||
30 | reverse: false, | ||
31 | page: 0 | ||
32 | } | ||
33 | }) | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | ] | ||
38 | }) | ||
39 | .overrideTemplate(PieceOfNewsComponent, '') | ||
40 | .compileComponents(); | ||
41 | |||
42 | fixture = TestBed.createComponent(PieceOfNewsComponent); | ||
43 | comp = fixture.componentInstance; | ||
44 | service = fixture.debugElement.injector.get(PieceOfNewsService); | ||
45 | }); | ||
46 | |||
47 | it('Should call load all on init', () => { | ||
48 | // GIVEN | ||
49 | const headers = new HttpHeaders().append('link', 'link;link'); | ||
50 | spyOn(service, 'query').and.returnValue( | ||
51 | of( | ||
52 | new HttpResponse({ | ||
53 | body: [new PieceOfNews(123)], | ||
54 | headers | ||
55 | }) | ||
56 | ) | ||
57 | ); | ||
58 | |||
59 | // WHEN | ||
60 | comp.ngOnInit(); | ||
61 | |||
62 | // THEN | ||
63 | expect(service.query).toHaveBeenCalled(); | ||
64 | expect(comp.pieceOfNews && comp.pieceOfNews[0]).toEqual(jasmine.objectContaining({ id: 123 })); | ||
65 | }); | ||
66 | |||
67 | it('should load a page', () => { | ||
68 | // GIVEN | ||
69 | const headers = new HttpHeaders().append('link', 'link;link'); | ||
70 | spyOn(service, 'query').and.returnValue( | ||
71 | of( | ||
72 | new HttpResponse({ | ||
73 | body: [new PieceOfNews(123)], | ||
74 | headers | ||
75 | }) | ||
76 | ) | ||
77 | ); | ||
78 | |||
79 | // WHEN | ||
80 | comp.loadPage(1); | ||
81 | |||
82 | // THEN | ||
83 | expect(service.query).toHaveBeenCalled(); | ||
84 | expect(comp.pieceOfNews && comp.pieceOfNews[0]).toEqual(jasmine.objectContaining({ id: 123 })); | ||
85 | }); | ||
86 | |||
87 | it('should calculate the sort attribute for an id', () => { | ||
88 | // WHEN | ||
89 | comp.ngOnInit(); | ||
90 | const result = comp.sort(); | ||
91 | |||
92 | // THEN | ||
93 | expect(result).toEqual(['id,desc']); | ||
94 | }); | ||
95 | |||
96 | it('should calculate the sort attribute for a non-id attribute', () => { | ||
97 | // INIT | ||
98 | comp.ngOnInit(); | ||
99 | |||
100 | // GIVEN | ||
101 | comp.predicate = 'name'; | ||
102 | |||
103 | // WHEN | ||
104 | const result = comp.sort(); | ||
105 | |||
106 | // THEN | ||
107 | expect(result).toEqual(['name,desc', 'id']); | ||
108 | }); | ||
109 | }); | ||
110 | }); |
File src/test/javascript/spec/app/entities/piece-of-news/piece-of-news.service.spec.ts added (mode: 100644) (index 0000000..544d208) | |||
1 | import { TestBed, getTestBed } from '@angular/core/testing'; | ||
2 | import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing'; | ||
3 | import * as moment from 'moment'; | ||
4 | import { DATE_TIME_FORMAT } from 'app/shared/constants/input.constants'; | ||
5 | import { PieceOfNewsService } from 'app/entities/piece-of-news/piece-of-news.service'; | ||
6 | import { IPieceOfNews, PieceOfNews } from 'app/shared/model/piece-of-news.model'; | ||
7 | |||
8 | describe('Service Tests', () => { | ||
9 | describe('PieceOfNews Service', () => { | ||
10 | let injector: TestBed; | ||
11 | let service: PieceOfNewsService; | ||
12 | let httpMock: HttpTestingController; | ||
13 | let elemDefault: IPieceOfNews; | ||
14 | let expectedResult: IPieceOfNews | IPieceOfNews[] | boolean | null; | ||
15 | let currentDate: moment.Moment; | ||
16 | |||
17 | beforeEach(() => { | ||
18 | TestBed.configureTestingModule({ | ||
19 | imports: [HttpClientTestingModule] | ||
20 | }); | ||
21 | expectedResult = null; | ||
22 | injector = getTestBed(); | ||
23 | service = injector.get(PieceOfNewsService); | ||
24 | httpMock = injector.get(HttpTestingController); | ||
25 | currentDate = moment(); | ||
26 | |||
27 | elemDefault = new PieceOfNews( | ||
28 | 0, | ||
29 | 0, | ||
30 | currentDate, | ||
31 | 'AAAAAAA', | ||
32 | 'AAAAAAA', | ||
33 | 'AAAAAAA', | ||
34 | currentDate, | ||
35 | 'AAAAAAA', | ||
36 | currentDate, | ||
37 | 'AAAAAAA', | ||
38 | currentDate | ||
39 | ); | ||
40 | }); | ||
41 | |||
42 | describe('Service methods', () => { | ||
43 | it('should find an element', () => { | ||
44 | const returnedFromService = Object.assign( | ||
45 | { | ||
46 | newsDate: currentDate.format(DATE_TIME_FORMAT), | ||
47 | publishDate: currentDate.format(DATE_TIME_FORMAT), | ||
48 | createdDate: currentDate.format(DATE_TIME_FORMAT), | ||
49 | lastModifiedDate: currentDate.format(DATE_TIME_FORMAT) | ||
50 | }, | ||
51 | elemDefault | ||
52 | ); | ||
53 | |||
54 | service.find(123).subscribe(resp => (expectedResult = resp.body)); | ||
55 | |||
56 | const req = httpMock.expectOne({ method: 'GET' }); | ||
57 | req.flush(returnedFromService); | ||
58 | expect(expectedResult).toMatchObject(elemDefault); | ||
59 | }); | ||
60 | |||
61 | it('should create a PieceOfNews', () => { | ||
62 | const returnedFromService = Object.assign( | ||
63 | { | ||
64 | id: 0, | ||
65 | newsDate: currentDate.format(DATE_TIME_FORMAT), | ||
66 | publishDate: currentDate.format(DATE_TIME_FORMAT), | ||
67 | createdDate: currentDate.format(DATE_TIME_FORMAT), | ||
68 | lastModifiedDate: currentDate.format(DATE_TIME_FORMAT) | ||
69 | }, | ||
70 | elemDefault | ||
71 | ); | ||
72 | |||
73 | const expected = Object.assign( | ||
74 | { | ||
75 | newsDate: currentDate, | ||
76 | publishDate: currentDate, | ||
77 | createdDate: currentDate, | ||
78 | lastModifiedDate: currentDate | ||
79 | }, | ||
80 | returnedFromService | ||
81 | ); | ||
82 | |||
83 | service.create(new PieceOfNews()).subscribe(resp => (expectedResult = resp.body)); | ||
84 | |||
85 | const req = httpMock.expectOne({ method: 'POST' }); | ||
86 | req.flush(returnedFromService); | ||
87 | expect(expectedResult).toMatchObject(expected); | ||
88 | }); | ||
89 | |||
90 | it('should update a PieceOfNews', () => { | ||
91 | const returnedFromService = Object.assign( | ||
92 | { | ||
93 | appId: 1, | ||
94 | newsDate: currentDate.format(DATE_TIME_FORMAT), | ||
95 | headline: 'BBBBBB', | ||
96 | content: 'BBBBBB', | ||
97 | link: 'BBBBBB', | ||
98 | publishDate: currentDate.format(DATE_TIME_FORMAT), | ||
99 | createdBy: 'BBBBBB', | ||
100 | createdDate: currentDate.format(DATE_TIME_FORMAT), | ||
101 | lastModifiedBy: 'BBBBBB', | ||
102 | lastModifiedDate: currentDate.format(DATE_TIME_FORMAT) | ||
103 | }, | ||
104 | elemDefault | ||
105 | ); | ||
106 | |||
107 | const expected = Object.assign( | ||
108 | { | ||
109 | newsDate: currentDate, | ||
110 | publishDate: currentDate, | ||
111 | createdDate: currentDate, | ||
112 | lastModifiedDate: currentDate | ||
113 | }, | ||
114 | returnedFromService | ||
115 | ); | ||
116 | |||
117 | service.update(expected).subscribe(resp => (expectedResult = resp.body)); | ||
118 | |||
119 | const req = httpMock.expectOne({ method: 'PUT' }); | ||
120 | req.flush(returnedFromService); | ||
121 | expect(expectedResult).toMatchObject(expected); | ||
122 | }); | ||
123 | |||
124 | it('should return a list of PieceOfNews', () => { | ||
125 | const returnedFromService = Object.assign( | ||
126 | { | ||
127 | appId: 1, | ||
128 | newsDate: currentDate.format(DATE_TIME_FORMAT), | ||
129 | headline: 'BBBBBB', | ||
130 | content: 'BBBBBB', | ||
131 | link: 'BBBBBB', | ||
132 | publishDate: currentDate.format(DATE_TIME_FORMAT), | ||
133 | createdBy: 'BBBBBB', | ||
134 | createdDate: currentDate.format(DATE_TIME_FORMAT), | ||
135 | lastModifiedBy: 'BBBBBB', | ||
136 | lastModifiedDate: currentDate.format(DATE_TIME_FORMAT) | ||
137 | }, | ||
138 | elemDefault | ||
139 | ); | ||
140 | |||
141 | const expected = Object.assign( | ||
142 | { | ||
143 | newsDate: currentDate, | ||
144 | publishDate: currentDate, | ||
145 | createdDate: currentDate, | ||
146 | lastModifiedDate: currentDate | ||
147 | }, | ||
148 | returnedFromService | ||
149 | ); | ||
150 | |||
151 | service.query().subscribe(resp => (expectedResult = resp.body)); | ||
152 | |||
153 | const req = httpMock.expectOne({ method: 'GET' }); | ||
154 | req.flush([returnedFromService]); | ||
155 | httpMock.verify(); | ||
156 | expect(expectedResult).toContainEqual(expected); | ||
157 | }); | ||
158 | |||
159 | it('should delete a PieceOfNews', () => { | ||
160 | service.delete(123).subscribe(resp => (expectedResult = resp.ok)); | ||
161 | |||
162 | const req = httpMock.expectOne({ method: 'DELETE' }); | ||
163 | req.flush({ status: 200 }); | ||
164 | expect(expectedResult); | ||
165 | }); | ||
166 | }); | ||
167 | |||
168 | afterEach(() => { | ||
169 | httpMock.verify(); | ||
170 | }); | ||
171 | }); | ||
172 | }); |
File src/test/javascript/spec/app/layouts/main/main.component.spec.ts added (mode: 100644) (index 0000000..1c30205) | |||
1 | import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
2 | import { Router, RouterEvent, NavigationEnd } from '@angular/router'; | ||
3 | import { Title } from '@angular/platform-browser'; | ||
4 | import { Subject, of } from 'rxjs'; | ||
5 | import { TranslateModule, TranslateService, LangChangeEvent } from '@ngx-translate/core'; | ||
6 | |||
7 | import { MainComponent } from 'app/layouts/main/main.component'; | ||
8 | import { HonlapTestModule } from '../../../test.module'; | ||
9 | import { MockRouter } from '../../../helpers/mock-route.service'; | ||
10 | |||
11 | describe('Component Tests', () => { | ||
12 | describe('MainComponent', () => { | ||
13 | let comp: MainComponent; | ||
14 | let fixture: ComponentFixture<MainComponent>; | ||
15 | let router: MockRouter; | ||
16 | const routerEventsSubject = new Subject<RouterEvent>(); | ||
17 | let titleService: Title; | ||
18 | let translateService: TranslateService; | ||
19 | |||
20 | beforeEach(async(() => { | ||
21 | TestBed.configureTestingModule({ | ||
22 | imports: [HonlapTestModule, TranslateModule.forRoot()], | ||
23 | declarations: [MainComponent], | ||
24 | providers: [Title] | ||
25 | }) | ||
26 | .overrideTemplate(MainComponent, '') | ||
27 | .compileComponents(); | ||
28 | })); | ||
29 | |||
30 | beforeEach(() => { | ||
31 | fixture = TestBed.createComponent(MainComponent); | ||
32 | comp = fixture.componentInstance; | ||
33 | router = TestBed.get(Router); | ||
34 | router.setEvents(routerEventsSubject.asObservable()); | ||
35 | titleService = TestBed.get(Title); | ||
36 | translateService = TestBed.get(TranslateService); | ||
37 | }); | ||
38 | |||
39 | describe('page title', () => { | ||
40 | let routerState: any; | ||
41 | const defaultPageTitle = 'global.title'; | ||
42 | const parentRoutePageTitle = 'parentTitle'; | ||
43 | const childRoutePageTitle = 'childTitle'; | ||
44 | const navigationEnd = new NavigationEnd(1, '', ''); | ||
45 | const langChangeEvent: LangChangeEvent = { lang: 'hu', translations: null }; | ||
46 | |||
47 | beforeEach(() => { | ||
48 | routerState = { snapshot: { root: {} } }; | ||
49 | router.setRouterState(routerState); | ||
50 | spyOn(translateService, 'get').and.callFake((key: string) => { | ||
51 | return of(key + ' translated'); | ||
52 | }); | ||
53 | translateService.currentLang = 'hu'; | ||
54 | spyOn(titleService, 'setTitle'); | ||
55 | comp.ngOnInit(); | ||
56 | }); | ||
57 | |||
58 | describe('navigation end', () => { | ||
59 | it('should set page title to default title if pageTitle is missing on routes', () => { | ||
60 | // WHEN | ||
61 | routerEventsSubject.next(navigationEnd); | ||
62 | |||
63 | // THEN | ||
64 | expect(translateService.get).toHaveBeenCalledWith(defaultPageTitle); | ||
65 | expect(titleService.setTitle).toHaveBeenCalledWith(defaultPageTitle + ' translated'); | ||
66 | }); | ||
67 | |||
68 | it('should set page title to root route pageTitle if there is no child routes', () => { | ||
69 | // GIVEN | ||
70 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
71 | |||
72 | // WHEN | ||
73 | routerEventsSubject.next(navigationEnd); | ||
74 | |||
75 | // THEN | ||
76 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
77 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
78 | }); | ||
79 | |||
80 | it('should set page title to child route pageTitle if child routes exist and pageTitle is set for child route', () => { | ||
81 | // GIVEN | ||
82 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
83 | routerState.snapshot.root.firstChild = { data: { pageTitle: childRoutePageTitle } }; | ||
84 | |||
85 | // WHEN | ||
86 | routerEventsSubject.next(navigationEnd); | ||
87 | |||
88 | // THEN | ||
89 | expect(translateService.get).toHaveBeenCalledWith(childRoutePageTitle); | ||
90 | expect(titleService.setTitle).toHaveBeenCalledWith(childRoutePageTitle + ' translated'); | ||
91 | }); | ||
92 | |||
93 | it('should set page title to parent route pageTitle if child routes exists but pageTitle is not set for child route data', () => { | ||
94 | // GIVEN | ||
95 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
96 | routerState.snapshot.root.firstChild = { data: {} }; | ||
97 | |||
98 | // WHEN | ||
99 | routerEventsSubject.next(navigationEnd); | ||
100 | |||
101 | // THEN | ||
102 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
103 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
104 | }); | ||
105 | |||
106 | it('should set page title to parent route pageTitle if child routes exists but data is not set for child route', () => { | ||
107 | // GIVEN | ||
108 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
109 | routerState.snapshot.root.firstChild = {}; | ||
110 | |||
111 | // WHEN | ||
112 | routerEventsSubject.next(navigationEnd); | ||
113 | |||
114 | // THEN | ||
115 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
116 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
117 | }); | ||
118 | }); | ||
119 | |||
120 | describe('language change', () => { | ||
121 | it('should set page title to default title if pageTitle is missing on routes', () => { | ||
122 | // WHEN | ||
123 | translateService.onLangChange.emit(langChangeEvent); | ||
124 | |||
125 | // THEN | ||
126 | expect(translateService.get).toHaveBeenCalledWith(defaultPageTitle); | ||
127 | expect(titleService.setTitle).toHaveBeenCalledWith(defaultPageTitle + ' translated'); | ||
128 | }); | ||
129 | |||
130 | it('should set page title to root route pageTitle if there is no child routes', () => { | ||
131 | // GIVEN | ||
132 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
133 | |||
134 | // WHEN | ||
135 | translateService.onLangChange.emit(langChangeEvent); | ||
136 | |||
137 | // THEN | ||
138 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
139 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
140 | }); | ||
141 | |||
142 | it('should set page title to child route pageTitle if child routes exist and pageTitle is set for child route', () => { | ||
143 | // GIVEN | ||
144 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
145 | routerState.snapshot.root.firstChild = { data: { pageTitle: childRoutePageTitle } }; | ||
146 | |||
147 | // WHEN | ||
148 | translateService.onLangChange.emit(langChangeEvent); | ||
149 | |||
150 | // THEN | ||
151 | expect(translateService.get).toHaveBeenCalledWith(childRoutePageTitle); | ||
152 | expect(titleService.setTitle).toHaveBeenCalledWith(childRoutePageTitle + ' translated'); | ||
153 | }); | ||
154 | |||
155 | it('should set page title to parent route pageTitle if child routes exists but pageTitle is not set for child route data', () => { | ||
156 | // GIVEN | ||
157 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
158 | routerState.snapshot.root.firstChild = { data: {} }; | ||
159 | |||
160 | // WHEN | ||
161 | translateService.onLangChange.emit(langChangeEvent); | ||
162 | |||
163 | // THEN | ||
164 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
165 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
166 | }); | ||
167 | |||
168 | it('should set page title to parent route pageTitle if child routes exists but data is not set for child route', () => { | ||
169 | // GIVEN | ||
170 | routerState.snapshot.root.data = { pageTitle: parentRoutePageTitle }; | ||
171 | routerState.snapshot.root.firstChild = {}; | ||
172 | |||
173 | // WHEN | ||
174 | translateService.onLangChange.emit(langChangeEvent); | ||
175 | |||
176 | // THEN | ||
177 | expect(translateService.get).toHaveBeenCalledWith(parentRoutePageTitle); | ||
178 | expect(titleService.setTitle).toHaveBeenCalledWith(parentRoutePageTitle + ' translated'); | ||
179 | }); | ||
180 | }); | ||
181 | }); | ||
182 | }); | ||
183 | }); |
File src/test/javascript/spec/app/shared/alert/alert-error.component.spec.ts added (mode: 100644) (index 0000000..10ef85f) | |||
1 | import { ComponentFixture, TestBed, async } from '@angular/core/testing'; | ||
2 | import { HttpErrorResponse, HttpHeaders } from '@angular/common/http'; | ||
3 | import { JhiAlertService, JhiEventManager } from 'ng-jhipster'; | ||
4 | import { TranslateModule } from '@ngx-translate/core'; | ||
5 | |||
6 | import { HonlapTestModule } from '../../../test.module'; | ||
7 | import { AlertErrorComponent } from 'app/shared/alert/alert-error.component'; | ||
8 | import { MockAlertService } from '../../../helpers/mock-alert.service'; | ||
9 | |||
10 | describe('Component Tests', () => { | ||
11 | describe('Alert Error Component', () => { | ||
12 | let comp: AlertErrorComponent; | ||
13 | let fixture: ComponentFixture<AlertErrorComponent>; | ||
14 | let eventManager: JhiEventManager; | ||
15 | |||
16 | beforeEach(async(() => { | ||
17 | TestBed.configureTestingModule({ | ||
18 | imports: [HonlapTestModule, TranslateModule.forRoot()], | ||
19 | declarations: [AlertErrorComponent], | ||
20 | providers: [ | ||
21 | JhiEventManager, | ||
22 | { | ||
23 | provide: JhiAlertService, | ||
24 | useClass: MockAlertService | ||
25 | } | ||
26 | ] | ||
27 | }) | ||
28 | .overrideTemplate(AlertErrorComponent, '') | ||
29 | .compileComponents(); | ||
30 | })); | ||
31 | |||
32 | beforeEach(() => { | ||
33 | fixture = TestBed.createComponent(AlertErrorComponent); | ||
34 | comp = fixture.componentInstance; | ||
35 | eventManager = fixture.debugElement.injector.get(JhiEventManager); | ||
36 | }); | ||
37 | |||
38 | describe('Error Handling', () => { | ||
39 | it('Should display an alert on status 0', () => { | ||
40 | // GIVEN | ||
41 | eventManager.broadcast({ name: 'honlapApp.httpError', content: { status: 0 } }); | ||
42 | // THEN | ||
43 | expect(comp.alerts.length).toBe(1); | ||
44 | expect(comp.alerts[0].msg).toBe('error.server.not.reachable'); | ||
45 | }); | ||
46 | |||
47 | it('Should display an alert on status 404', () => { | ||
48 | // GIVEN | ||
49 | eventManager.broadcast({ name: 'honlapApp.httpError', content: { status: 404 } }); | ||
50 | // THEN | ||
51 | expect(comp.alerts.length).toBe(1); | ||
52 | expect(comp.alerts[0].msg).toBe('error.url.not.found'); | ||
53 | }); | ||
54 | |||
55 | it('Should display an alert on generic error', () => { | ||
56 | // GIVEN | ||
57 | eventManager.broadcast({ name: 'honlapApp.httpError', content: { error: { message: 'Error Message' } } }); | ||
58 | eventManager.broadcast({ name: 'honlapApp.httpError', content: { error: 'Second Error Message' } }); | ||
59 | // THEN | ||
60 | expect(comp.alerts.length).toBe(2); | ||
61 | expect(comp.alerts[0].msg).toBe('Error Message'); | ||
62 | expect(comp.alerts[1].msg).toBe('Second Error Message'); | ||
63 | }); | ||
64 | |||
65 | it('Should display an alert on status 400 for generic error', () => { | ||
66 | // GIVEN | ||
67 | const response = new HttpErrorResponse({ | ||
68 | url: 'http://localhost:8080/api/foos', | ||
69 | headers: new HttpHeaders(), | ||
70 | status: 400, | ||
71 | statusText: 'Bad Request', | ||
72 | error: { | ||
73 | type: 'https://www.jhipster.tech/problem/constraint-violation', | ||
74 | title: 'Bad Request', | ||
75 | status: 400, | ||
76 | path: '/api/foos', | ||
77 | message: 'error.validation' | ||
78 | } | ||
79 | }); | ||
80 | eventManager.broadcast({ name: 'honlapApp.httpError', content: response }); | ||
81 | // THEN | ||
82 | expect(comp.alerts.length).toBe(1); | ||
83 | expect(comp.alerts[0].msg).toBe('error.validation'); | ||
84 | }); | ||
85 | |||
86 | it('Should display an alert on status 400 for generic error without message', () => { | ||
87 | // GIVEN | ||
88 | const response = new HttpErrorResponse({ | ||
89 | url: 'http://localhost:8080/api/foos', | ||
90 | headers: new HttpHeaders(), | ||
91 | status: 400, | ||
92 | error: 'Bad Request' | ||
93 | }); | ||
94 | eventManager.broadcast({ name: 'honlapApp.httpError', content: response }); | ||
95 | // THEN | ||
96 | expect(comp.alerts.length).toBe(1); | ||
97 | expect(comp.alerts[0].msg).toBe('Bad Request'); | ||
98 | }); | ||
99 | |||
100 | it('Should display an alert on status 400 for invalid parameters', () => { | ||
101 | // GIVEN | ||
102 | const response = new HttpErrorResponse({ | ||
103 | url: 'http://localhost:8080/api/foos', | ||
104 | headers: new HttpHeaders(), | ||
105 | status: 400, | ||
106 | statusText: 'Bad Request', | ||
107 | error: { | ||
108 | type: 'https://www.jhipster.tech/problem/constraint-violation', | ||
109 | title: 'Method argument not valid', | ||
110 | status: 400, | ||
111 | path: '/api/foos', | ||
112 | message: 'error.validation', | ||
113 | fieldErrors: [{ objectName: 'foo', field: 'minField', message: 'Min' }] | ||
114 | } | ||
115 | }); | ||
116 | eventManager.broadcast({ name: 'honlapApp.httpError', content: response }); | ||
117 | // THEN | ||
118 | expect(comp.alerts.length).toBe(1); | ||
119 | expect(comp.alerts[0].msg).toBe('error.Size'); | ||
120 | }); | ||
121 | |||
122 | it('Should display an alert on status 400 for error headers', () => { | ||
123 | // GIVEN | ||
124 | const response = new HttpErrorResponse({ | ||
125 | url: 'http://localhost:8080/api/foos', | ||
126 | headers: new HttpHeaders().append('app-error', 'Error Message').append('app-params', 'foo'), | ||
127 | status: 400, | ||
128 | statusText: 'Bad Request', | ||
129 | error: { | ||
130 | status: 400, | ||
131 | message: 'error.validation' | ||
132 | } | ||
133 | }); | ||
134 | eventManager.broadcast({ name: 'honlapApp.httpError', content: response }); | ||
135 | // THEN | ||
136 | expect(comp.alerts.length).toBe(1); | ||
137 | expect(comp.alerts[0].msg).toBe('Error Message'); | ||
138 | }); | ||
139 | }); | ||
140 | }); | ||
141 | }); |
File src/test/javascript/spec/app/shared/login/login.component.spec.ts added (mode: 100644) (index 0000000..b5606a6) | |||
1 | import { ComponentFixture, TestBed, async, inject, fakeAsync, tick } from '@angular/core/testing'; | ||
2 | import { FormBuilder } from '@angular/forms'; | ||
3 | import { Router } from '@angular/router'; | ||
4 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
5 | |||
6 | import { LoginService } from 'app/core/login/login.service'; | ||
7 | import { LoginModalComponent } from 'app/shared/login/login.component'; | ||
8 | import { HonlapTestModule } from '../../../test.module'; | ||
9 | import { MockLoginService } from '../../../helpers/mock-login.service'; | ||
10 | import { MockRouter } from '../../../helpers/mock-route.service'; | ||
11 | import { MockActiveModal } from '../../../helpers/mock-active-modal.service'; | ||
12 | |||
13 | describe('Component Tests', () => { | ||
14 | describe('LoginComponent', () => { | ||
15 | let comp: LoginModalComponent; | ||
16 | let fixture: ComponentFixture<LoginModalComponent>; | ||
17 | let mockLoginService: MockLoginService; | ||
18 | let mockRouter: MockRouter; | ||
19 | let mockActiveModal: MockActiveModal; | ||
20 | |||
21 | beforeEach(async(() => { | ||
22 | TestBed.configureTestingModule({ | ||
23 | imports: [HonlapTestModule], | ||
24 | declarations: [LoginModalComponent], | ||
25 | providers: [ | ||
26 | FormBuilder, | ||
27 | { | ||
28 | provide: LoginService, | ||
29 | useClass: MockLoginService | ||
30 | } | ||
31 | ] | ||
32 | }) | ||
33 | .overrideTemplate(LoginModalComponent, '') | ||
34 | .compileComponents(); | ||
35 | })); | ||
36 | |||
37 | beforeEach(() => { | ||
38 | fixture = TestBed.createComponent(LoginModalComponent); | ||
39 | comp = fixture.componentInstance; | ||
40 | mockLoginService = TestBed.get(LoginService); | ||
41 | mockRouter = TestBed.get(Router); | ||
42 | mockActiveModal = TestBed.get(NgbActiveModal); | ||
43 | }); | ||
44 | |||
45 | it('should authenticate the user', inject( | ||
46 | [], | ||
47 | fakeAsync(() => { | ||
48 | // GIVEN | ||
49 | const credentials = { | ||
50 | username: 'admin', | ||
51 | password: 'admin', | ||
52 | rememberMe: true | ||
53 | }; | ||
54 | |||
55 | comp.loginForm.patchValue({ | ||
56 | username: 'admin', | ||
57 | password: 'admin', | ||
58 | rememberMe: true | ||
59 | }); | ||
60 | mockLoginService.setResponse({}); | ||
61 | mockRouter.url = '/admin/metrics'; | ||
62 | |||
63 | // WHEN/ | ||
64 | comp.login(); | ||
65 | tick(); // simulate async | ||
66 | |||
67 | // THEN | ||
68 | expect(comp.authenticationError).toEqual(false); | ||
69 | expect(mockActiveModal.closeSpy).toHaveBeenCalled(); | ||
70 | expect(mockLoginService.loginSpy).toHaveBeenCalledWith(credentials); | ||
71 | }) | ||
72 | )); | ||
73 | |||
74 | it('should empty the credentials upon cancel', () => { | ||
75 | // GIVEN | ||
76 | comp.loginForm.patchValue({ | ||
77 | username: 'admin', | ||
78 | password: 'admin' | ||
79 | }); | ||
80 | |||
81 | const expected = { | ||
82 | username: '', | ||
83 | password: '', | ||
84 | rememberMe: false | ||
85 | }; | ||
86 | |||
87 | // WHEN | ||
88 | comp.cancel(); | ||
89 | |||
90 | // THEN | ||
91 | expect(comp.authenticationError).toEqual(false); | ||
92 | expect(comp.loginForm.get('username')!.value).toEqual(expected.username); | ||
93 | expect(comp.loginForm.get('password')!.value).toEqual(expected.password); | ||
94 | expect(comp.loginForm.get('rememberMe')!.value).toEqual(expected.rememberMe); | ||
95 | expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('cancel'); | ||
96 | }); | ||
97 | |||
98 | it('should redirect user when register', () => { | ||
99 | // WHEN | ||
100 | comp.register(); | ||
101 | |||
102 | // THEN | ||
103 | expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('to state register'); | ||
104 | expect(mockRouter.navigateSpy).toHaveBeenCalledWith(['/account/register']); | ||
105 | }); | ||
106 | |||
107 | it('should redirect user when request password', () => { | ||
108 | // WHEN | ||
109 | comp.requestResetPassword(); | ||
110 | |||
111 | // THEN | ||
112 | expect(mockActiveModal.dismissSpy).toHaveBeenCalledWith('to state requestReset'); | ||
113 | expect(mockRouter.navigateSpy).toHaveBeenCalledWith(['/account/reset', 'request']); | ||
114 | }); | ||
115 | }); | ||
116 | }); |
File src/test/javascript/spec/helpers/mock-account.service.ts added (mode: 100644) (index 0000000..a01ceed) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { of } from 'rxjs'; | ||
3 | |||
4 | import { SpyObject } from './spyobject'; | ||
5 | import { AccountService } from 'app/core/auth/account.service'; | ||
6 | import { Account } from 'app/core/user/account.model'; | ||
7 | |||
8 | export class MockAccountService extends SpyObject { | ||
9 | getSpy: Spy; | ||
10 | saveSpy: Spy; | ||
11 | authenticateSpy: Spy; | ||
12 | identitySpy: Spy; | ||
13 | getAuthenticationStateSpy: Spy; | ||
14 | |||
15 | constructor() { | ||
16 | super(AccountService); | ||
17 | |||
18 | this.getSpy = this.spy('get').andReturn(this); | ||
19 | this.saveSpy = this.spy('save').andReturn(this); | ||
20 | this.authenticateSpy = this.spy('authenticate').andReturn(this); | ||
21 | this.identitySpy = this.spy('identity').andReturn(of(null)); | ||
22 | this.getAuthenticationStateSpy = this.spy('getAuthenticationState').andReturn(of(null)); | ||
23 | } | ||
24 | |||
25 | setIdentityResponse(account: Account | null): void { | ||
26 | this.identitySpy = this.spy('identity').andReturn(of(account)); | ||
27 | this.getAuthenticationStateSpy = this.spy('getAuthenticationState').andReturn(of(account)); | ||
28 | } | ||
29 | } |
File src/test/javascript/spec/helpers/mock-active-modal.service.ts added (mode: 100644) (index 0000000..bd32d74) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'; | ||
3 | |||
4 | import { SpyObject } from './spyobject'; | ||
5 | |||
6 | export class MockActiveModal extends SpyObject { | ||
7 | dismissSpy: Spy; | ||
8 | closeSpy: Spy; | ||
9 | |||
10 | constructor() { | ||
11 | super(NgbActiveModal); | ||
12 | this.dismissSpy = this.spy('dismiss').andReturn(this); | ||
13 | this.closeSpy = this.spy('close').andReturn(this); | ||
14 | } | ||
15 | } |
File src/test/javascript/spec/helpers/mock-alert.service.ts added (mode: 100644) (index 0000000..2bf7724) | |||
1 | import { JhiAlertService, JhiAlert } from 'ng-jhipster'; | ||
2 | |||
3 | import { SpyObject } from './spyobject'; | ||
4 | |||
5 | export class MockAlertService extends SpyObject { | ||
6 | constructor() { | ||
7 | super(JhiAlertService); | ||
8 | } | ||
9 | |||
10 | addAlert(alertOptions: JhiAlert): JhiAlert { | ||
11 | return alertOptions; | ||
12 | } | ||
13 | } |
File src/test/javascript/spec/helpers/mock-event-manager.service.ts added (mode: 100644) (index 0000000..4a8f56a) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { JhiEventManager } from 'ng-jhipster'; | ||
3 | |||
4 | import { SpyObject } from './spyobject'; | ||
5 | |||
6 | export class MockEventManager extends SpyObject { | ||
7 | broadcastSpy: Spy; | ||
8 | |||
9 | constructor() { | ||
10 | super(JhiEventManager); | ||
11 | this.broadcastSpy = this.spy('broadcast').andReturn(this); | ||
12 | } | ||
13 | } |
File src/test/javascript/spec/helpers/mock-language.service.ts added (mode: 100644) (index 0000000..0c53be6) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { JhiLanguageService } from 'ng-jhipster'; | ||
3 | |||
4 | import { SpyObject } from './spyobject'; | ||
5 | |||
6 | export class MockLanguageService extends SpyObject { | ||
7 | getCurrentLanguageSpy: Spy; | ||
8 | |||
9 | constructor() { | ||
10 | super(JhiLanguageService); | ||
11 | |||
12 | this.getCurrentLanguageSpy = this.spy('getCurrentLanguage').andReturn('hu'); | ||
13 | } | ||
14 | } |
File src/test/javascript/spec/helpers/mock-login.service.ts added (mode: 100644) (index 0000000..a75a800) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { of } from 'rxjs'; | ||
3 | |||
4 | import { SpyObject } from './spyobject'; | ||
5 | import { LoginService } from 'app/core/login/login.service'; | ||
6 | |||
7 | export class MockLoginService extends SpyObject { | ||
8 | loginSpy: Spy; | ||
9 | logoutSpy: Spy; | ||
10 | registerSpy: Spy; | ||
11 | requestResetPasswordSpy: Spy; | ||
12 | cancelSpy: Spy; | ||
13 | |||
14 | constructor() { | ||
15 | super(LoginService); | ||
16 | |||
17 | this.loginSpy = this.spy('login').andReturn(of({})); | ||
18 | this.logoutSpy = this.spy('logout').andReturn(this); | ||
19 | this.registerSpy = this.spy('register').andReturn(this); | ||
20 | this.requestResetPasswordSpy = this.spy('requestResetPassword').andReturn(this); | ||
21 | this.cancelSpy = this.spy('cancel').andReturn(this); | ||
22 | } | ||
23 | |||
24 | setResponse(json: any): void { | ||
25 | this.loginSpy = this.spy('login').andReturn(of(json)); | ||
26 | } | ||
27 | } |
File src/test/javascript/spec/helpers/mock-route.service.ts added (mode: 100644) (index 0000000..a2dd6d8) | |||
1 | import Spy = jasmine.Spy; | ||
2 | import { ActivatedRoute, Router, RouterEvent } from '@angular/router'; | ||
3 | import { Observable, of } from 'rxjs'; | ||
4 | |||
5 | import { SpyObject } from './spyobject'; | ||
6 | |||
7 | export class MockActivatedRoute extends ActivatedRoute { | ||
8 | constructor(parameters?: any) { | ||
9 | super(); | ||
10 | this.queryParams = of(parameters); | ||
11 | this.params = of(parameters); | ||
12 | this.data = of({ | ||
13 | ...parameters, | ||
14 | pagingParams: { | ||
15 | page: 10, | ||
16 | ascending: false, | ||
17 | predicate: 'id' | ||
18 | } | ||
19 | }); | ||
20 | } | ||
21 | } | ||
22 | |||
23 | export class MockRouter extends SpyObject { | ||
24 | navigateSpy: Spy; | ||
25 | navigateByUrlSpy: Spy; | ||
26 | events: Observable<RouterEvent> | null = null; | ||
27 | routerState: any; | ||
28 | url = ''; | ||
29 | |||
30 | constructor() { | ||
31 | super(Router); | ||
32 | this.navigateSpy = this.spy('navigate'); | ||
33 | this.navigateByUrlSpy = this.spy('navigateByUrl'); | ||
34 | } | ||
35 | |||
36 | setEvents(events: Observable<RouterEvent>): void { | ||
37 | this.events = events; | ||
38 | } | ||
39 | |||
40 | setRouterState(routerState: any): void { | ||
41 | this.routerState = routerState; | ||
42 | } | ||
43 | } |
File src/test/javascript/spec/helpers/mock-state-storage.service.ts added (mode: 100644) (index 0000000..1a23343) | |||
1 | import Spy = jasmine.Spy; | ||
2 | |||
3 | import { SpyObject } from './spyobject'; | ||
4 | import { StateStorageService } from 'app/core/auth/state-storage.service'; | ||
5 | |||
6 | export class MockStateStorageService extends SpyObject { | ||
7 | getUrlSpy: Spy; | ||
8 | storeUrlSpy: Spy; | ||
9 | clearUrlSpy: Spy; | ||
10 | |||
11 | constructor() { | ||
12 | super(StateStorageService); | ||
13 | this.getUrlSpy = this.spy('getUrl').andReturn(null); | ||
14 | this.storeUrlSpy = this.spy('storeUrl').andReturn(this); | ||
15 | this.clearUrlSpy = this.spy('clearUrl').andReturn(this); | ||
16 | } | ||
17 | |||
18 | setResponse(previousUrl: string | null): void { | ||
19 | this.getUrlSpy = this.spy('getUrl').andReturn(previousUrl); | ||
20 | } | ||
21 | } |
File src/test/javascript/spec/helpers/spyobject.ts added (mode: 100644) (index 0000000..eeb221a) | |||
1 | export interface GuinessCompatibleSpy extends jasmine.Spy { | ||
2 | /** By chaining the spy with and.returnValue, all calls to the function will return a specific | ||
3 | * value. */ | ||
4 | andReturn(val: any): GuinessCompatibleSpy; | ||
5 | /** By chaining the spy with and.callFake, all calls to the spy will delegate to the supplied | ||
6 | * function. */ | ||
7 | andCallFake(fn: Function): GuinessCompatibleSpy; | ||
8 | /** removes all recorded calls */ | ||
9 | reset(): void; | ||
10 | } | ||
11 | |||
12 | export class SpyObject { | ||
13 | constructor(type?: any) { | ||
14 | if (type) { | ||
15 | Object.keys(type.prototype).forEach(prop => { | ||
16 | let m = null; | ||
17 | try { | ||
18 | m = type.prototype[prop]; | ||
19 | } catch (e) { | ||
20 | // As we are creating spys for abstract classes, | ||
21 | // these classes might have getters that throw when they are accessed. | ||
22 | // As we are only auto creating spys for methods, this | ||
23 | // should not matter. | ||
24 | } | ||
25 | if (typeof m === 'function') { | ||
26 | this.spy(prop); | ||
27 | } | ||
28 | }); | ||
29 | } | ||
30 | } | ||
31 | |||
32 | spy(name: string): GuinessCompatibleSpy { | ||
33 | if (!this[name]) { | ||
34 | this[name] = this.createGuinnessCompatibleSpy(name); | ||
35 | } | ||
36 | return this[name]; | ||
37 | } | ||
38 | |||
39 | private createGuinnessCompatibleSpy(name: string): GuinessCompatibleSpy { | ||
40 | const newSpy: GuinessCompatibleSpy = jasmine.createSpy(name) as any; | ||
41 | newSpy.andCallFake = newSpy.and.callFake as any; | ||
42 | newSpy.andReturn = newSpy.and.returnValue as any; | ||
43 | newSpy.reset = newSpy.calls.reset as any; | ||
44 | // revisit return null here (previously needed for rtts_assert). | ||
45 | newSpy.and.returnValue(null); | ||
46 | return newSpy; | ||
47 | } | ||
48 | } |
File src/test/javascript/spec/test.module.ts added (mode: 100644) (index 0000000..601e364) | |||
1 | import { DatePipe } from '@angular/common'; | ||
2 | import { ActivatedRoute, Router } from '@angular/router'; | ||
3 | import { NgModule } from '@angular/core'; | ||
4 | import { HttpClientTestingModule } from '@angular/common/http/testing'; | ||
5 | import { NgbActiveModal, NgbModal } from '@ng-bootstrap/ng-bootstrap'; | ||
6 | import { JhiLanguageService, JhiDataUtils, JhiDateUtils, JhiEventManager, JhiAlertService, JhiParseLinks } from 'ng-jhipster'; | ||
7 | |||
8 | import { MockLanguageService } from './helpers/mock-language.service'; | ||
9 | import { AccountService } from 'app/core/auth/account.service'; | ||
10 | import { LoginModalService } from 'app/core/login/login-modal.service'; | ||
11 | import { MockAccountService } from './helpers/mock-account.service'; | ||
12 | import { MockActivatedRoute, MockRouter } from './helpers/mock-route.service'; | ||
13 | import { MockActiveModal } from './helpers/mock-active-modal.service'; | ||
14 | import { MockEventManager } from './helpers/mock-event-manager.service'; | ||
15 | |||
16 | @NgModule({ | ||
17 | providers: [ | ||
18 | DatePipe, | ||
19 | JhiDataUtils, | ||
20 | JhiDateUtils, | ||
21 | JhiParseLinks, | ||
22 | { | ||
23 | provide: JhiLanguageService, | ||
24 | useClass: MockLanguageService | ||
25 | }, | ||
26 | { | ||
27 | provide: JhiEventManager, | ||
28 | useClass: MockEventManager | ||
29 | }, | ||
30 | { | ||
31 | provide: NgbActiveModal, | ||
32 | useClass: MockActiveModal | ||
33 | }, | ||
34 | { | ||
35 | provide: ActivatedRoute, | ||
36 | useValue: new MockActivatedRoute({ id: 123 }) | ||
37 | }, | ||
38 | { | ||
39 | provide: Router, | ||
40 | useClass: MockRouter | ||
41 | }, | ||
42 | { | ||
43 | provide: AccountService, | ||
44 | useClass: MockAccountService | ||
45 | }, | ||
46 | { | ||
47 | provide: LoginModalService, | ||
48 | useValue: null | ||
49 | }, | ||
50 | { | ||
51 | provide: JhiAlertService, | ||
52 | useValue: null | ||
53 | }, | ||
54 | { | ||
55 | provide: NgbModal, | ||
56 | useValue: null | ||
57 | } | ||
58 | ], | ||
59 | imports: [HttpClientTestingModule] | ||
60 | }) | ||
61 | export class HonlapTestModule {} |
File src/test/resources/config/application.yml added (mode: 100644) (index 0000000..a6606ba) | |||
1 | # =================================================================== | ||
2 | # Spring Boot configuration. | ||
3 | # | ||
4 | # This configuration is used for unit/integration tests. | ||
5 | # | ||
6 | # More information on profiles: https://www.jhipster.tech/profiles/ | ||
7 | # More information on configuration properties: https://www.jhipster.tech/common-application-properties/ | ||
8 | # =================================================================== | ||
9 | |||
10 | # =================================================================== | ||
11 | # Standard Spring Boot properties. | ||
12 | # Full reference is available at: | ||
13 | # http://docs.spring.io/spring-boot/docs/current/reference/html/common-application-properties.html | ||
14 | # =================================================================== | ||
15 | |||
16 | spring: | ||
17 | application: | ||
18 | name: honlap | ||
19 | datasource: | ||
20 | type: com.zaxxer.hikari.HikariDataSource | ||
21 | url: jdbc:h2:mem:honlap;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE | ||
22 | name: | ||
23 | username: | ||
24 | password: | ||
25 | hikari: | ||
26 | auto-commit: false | ||
27 | jackson: | ||
28 | serialization: | ||
29 | write-durations-as-timestamps: false | ||
30 | jpa: | ||
31 | database-platform: io.github.jhipster.domain.util.FixedH2Dialect | ||
32 | open-in-view: false | ||
33 | show-sql: false | ||
34 | hibernate: | ||
35 | ddl-auto: none | ||
36 | naming: | ||
37 | physical-strategy: org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy | ||
38 | implicit-strategy: org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy | ||
39 | properties: | ||
40 | hibernate.id.new_generator_mappings: true | ||
41 | hibernate.connection.provider_disables_autocommit: true | ||
42 | hibernate.cache.use_second_level_cache: false | ||
43 | hibernate.cache.use_query_cache: false | ||
44 | hibernate.generate_statistics: false | ||
45 | hibernate.hbm2ddl.auto: validate | ||
46 | hibernate.jdbc.time_zone: UTC | ||
47 | liquibase: | ||
48 | contexts: test | ||
49 | mail: | ||
50 | host: localhost | ||
51 | main: | ||
52 | allow-bean-definition-overriding: true | ||
53 | messages: | ||
54 | basename: i18n/messages | ||
55 | mvc: | ||
56 | favicon: | ||
57 | enabled: false | ||
58 | task: | ||
59 | execution: | ||
60 | thread-name-prefix: honlap-task- | ||
61 | pool: | ||
62 | core-size: 1 | ||
63 | max-size: 50 | ||
64 | queue-capacity: 10000 | ||
65 | scheduling: | ||
66 | thread-name-prefix: honlap-scheduling- | ||
67 | pool: | ||
68 | size: 1 | ||
69 | thymeleaf: | ||
70 | mode: HTML | ||
71 | |||
72 | server: | ||
73 | port: 10344 | ||
74 | address: localhost | ||
75 | |||
76 | # =================================================================== | ||
77 | # JHipster specific properties | ||
78 | # | ||
79 | # Full reference is available at: https://www.jhipster.tech/common-application-properties/ | ||
80 | # =================================================================== | ||
81 | |||
82 | jhipster: | ||
83 | clientApp: | ||
84 | name: 'honlapApp' | ||
85 | logging: | ||
86 | # To test json console appender | ||
87 | use-json-format: true # By default, logs are in Json format | ||
88 | logstash: | ||
89 | enabled: false | ||
90 | host: localhost | ||
91 | port: 5000 | ||
92 | queue-size: 512 | ||
93 | mail: | ||
94 | from: test@localhost | ||
95 | base-url: http://127.0.0.1:8080 | ||
96 | security: | ||
97 | authentication: | ||
98 | jwt: | ||
99 | # This token must be encoded using Base64 (you can type `echo 'secret-key'|base64` on your command line) | ||
100 | base64-secret: ZmYxOTYwOGZiYTY1OTJiMTQ3MDNhNGJiNTM3ZWMxN2U1ZTVjODdlMDhmZmNkMGRhYTQxY2ZiMGQzM2Q0ZTNmYzc2YjNjMzU5ZmVkZDgzZDc3OTYxZDMzNzdiNzc3MmVkYjA0NDFkOGIxMTI0MjRiNTMzYzRkNzFkMTJiYWE4Y2Y= | ||
101 | # Token is valid 24 hours | ||
102 | token-validity-in-seconds: 86400 | ||
103 | metrics: | ||
104 | logs: # Reports metrics in the logs | ||
105 | enabled: true | ||
106 | report-frequency: 60 # in seconds | ||
107 | |||
108 | # =================================================================== | ||
109 | # Application specific properties | ||
110 | # Add your own application properties here, see the ApplicationProperties class | ||
111 | # to have type-safe configuration, like in the JHipsterProperties above | ||
112 | # | ||
113 | # More documentation is available at: | ||
114 | # https://www.jhipster.tech/common-application-properties/ | ||
115 | # =================================================================== | ||
116 | |||
117 | # application: |
File src/test/resources/i18n/messages_en.properties added (mode: 100644) (index 0000000..334cb4a) | |||
1 | email.test.title=test title | ||
2 | # Value used for English locale unit test in MailServiceIT | ||
3 | # as this file is loaded instead of real file | ||
4 | email.activation.title=honlap account activation |
File src/test/resources/i18n/messages_hu.properties added (mode: 100644) (index 0000000..e971453) | |||
1 | email.test.title=hozzáférés aktiválása. |
File src/test/resources/logback.xml added (mode: 100644) (index 0000000..d0ec607) | |||
1 | <?xml version="1.0" encoding="UTF-8"?> | ||
2 | <!DOCTYPE configuration> | ||
3 | |||
4 | <configuration scan="true"> | ||
5 | <include resource="org/springframework/boot/logging/logback/base.xml"/> | ||
6 | |||
7 | <logger name="hu.dns.honlap" level="INFO"/> | ||
8 | |||
9 | <logger name="io.github.jhipster" level="WARN"/> | ||
10 | |||
11 | <logger name="javax.activation" level="WARN"/> | ||
12 | <logger name="javax.mail" level="WARN"/> | ||
13 | <logger name="javax.xml.bind" level="WARN"/> | ||
14 | <logger name="ch.qos.logback" level="WARN"/> | ||
15 | <logger name="com.ryantenney" level="WARN"/> | ||
16 | <logger name="com.sun" level="WARN"/> | ||
17 | <logger name="com.zaxxer" level="WARN"/> | ||
18 | <logger name="io.undertow" level="WARN"/> | ||
19 | <logger name="io.undertow.websockets.jsr" level="ERROR"/> | ||
20 | <logger name="org.ehcache" level="WARN"/> | ||
21 | <logger name="org.apache" level="WARN"/> | ||
22 | <logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/> | ||
23 | <logger name="org.bson" level="WARN"/> | ||
24 | <logger name="org.hibernate.validator" level="WARN"/> | ||
25 | <logger name="org.hibernate" level="WARN"/> | ||
26 | <logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/> | ||
27 | <logger name="org.postgresql.jdbc" level="WARN"/> | ||
28 | <logger name="org.springframework" level="WARN"/> | ||
29 | <logger name="org.springframework.web" level="WARN"/> | ||
30 | <logger name="org.springframework.security" level="WARN"/> | ||
31 | <logger name="org.springframework.cache" level="WARN"/> | ||
32 | <logger name="org.thymeleaf" level="WARN"/> | ||
33 | <logger name="org.xnio" level="WARN"/> | ||
34 | <logger name="springfox" level="WARN"/> | ||
35 | <logger name="sun.rmi" level="WARN"/> | ||
36 | <logger name="liquibase" level="WARN"/> | ||
37 | <logger name="LiquibaseSchemaResolver" level="INFO"/> | ||
38 | <logger name="sun.rmi.transport" level="WARN"/> | ||
39 | |||
40 | <root> | ||
41 | <level>WARN</level> | ||
42 | <appender-ref ref="CONSOLE"/> | ||
43 | </root> | ||
44 | |||
45 | </configuration> |
File src/test/resources/templates/mail/testEmail.html added (mode: 100644) (index 0000000..a4ca16a) | |||
1 | <html xmlns:th="http://www.thymeleaf.org" th:text="|#{email.test.title}, ${baseUrl}, ${user.login}|"></html> |
File tsconfig.app.json added (mode: 100644) (index 0000000..6aeff43) | |||
1 | { | ||
2 | "extends": "./tsconfig.json", | ||
3 | "files": ["src/main/webapp/app/app.main.ts"] | ||
4 | } |
File tsconfig.e2e.json added (mode: 100644) (index 0000000..2c7b284) | |||
1 | { | ||
2 | "extends": "./tsconfig.json", | ||
3 | "compilerOptions": { | ||
4 | "module": "commonjs" | ||
5 | } | ||
6 | } |
File tsconfig.json added (mode: 100644) (index 0000000..3f31512) | |||
1 | { | ||
2 | "compilerOptions": { | ||
3 | "target": "es6", | ||
4 | "module": "esnext", | ||
5 | "moduleResolution": "node", | ||
6 | "sourceMap": true, | ||
7 | "emitDecoratorMetadata": true, | ||
8 | "experimentalDecorators": true, | ||
9 | "removeComments": false, | ||
10 | "strict": true, | ||
11 | "noImplicitReturns": true, | ||
12 | "noFallthroughCasesInSwitch": true, | ||
13 | "suppressImplicitAnyIndexErrors": true, | ||
14 | "skipLibCheck": true, | ||
15 | "outDir": "target/classes/static/app", | ||
16 | "lib": ["es7", "dom"], | ||
17 | "baseUrl": "./", | ||
18 | "paths": { | ||
19 | "app/*": ["src/main/webapp/app/*"] | ||
20 | }, | ||
21 | "importHelpers": true | ||
22 | }, | ||
23 | "angularCompilerOptions": { | ||
24 | "genDir": "target/classes/aot", | ||
25 | "fullTemplateTypeCheck": true, | ||
26 | "preserveWhitespaces": true | ||
27 | } | ||
28 | } |
File tslint.json added (mode: 100644) (index 0000000..9319baf) | |||
1 | { | ||
2 | "rulesDirectory": ["node_modules/codelyzer"], | ||
3 | "rules": { | ||
4 | "directive-selector": [true, "attribute", "auth", "camelCase"], | ||
5 | "component-selector": [true, "element", "auth", "kebab-case"], | ||
6 | "no-inputs-metadata-property": true, | ||
7 | "no-outputs-metadata-property": true, | ||
8 | "no-host-metadata-property": true, | ||
9 | "no-input-rename": true, | ||
10 | "no-output-rename": true, | ||
11 | "use-lifecycle-interface": true, | ||
12 | "use-pipe-transform-interface": false, | ||
13 | "component-class-suffix": true, | ||
14 | "directive-class-suffix": true, | ||
15 | "typedef": [true, "call-signature"] | ||
16 | } | ||
17 | } |
File webpack/logo-jhipster.png added (mode: 100644) (index 0000000..e301aa9) |
File webpack/utils.js added (mode: 100644) (index 0000000..10aefd4) | |||
1 | const path = require('path'); | ||
2 | |||
3 | const tsconfig = require('../tsconfig.json'); | ||
4 | |||
5 | module.exports = { | ||
6 | root, | ||
7 | mapTypescriptAliasToWebpackAlias | ||
8 | }; | ||
9 | |||
10 | const _root = path.resolve(__dirname, '..'); | ||
11 | |||
12 | function root(args) { | ||
13 | args = Array.prototype.slice.call(arguments, 0); | ||
14 | return path.join.apply(path, [_root].concat(args)); | ||
15 | } | ||
16 | |||
17 | function mapTypescriptAliasToWebpackAlias(alias = {}) { | ||
18 | const webpackAliases = { ...alias }; | ||
19 | if (!tsconfig.compilerOptions.paths) { | ||
20 | return webpackAliases; | ||
21 | } | ||
22 | Object.entries(tsconfig.compilerOptions.paths) | ||
23 | .filter(([key, value]) => { | ||
24 | // use Typescript alias in Webpack only if this has value | ||
25 | return Boolean(value.length); | ||
26 | }) | ||
27 | .map(([key, value]) => { | ||
28 | // if Typescript alias ends with /* then remove this for Webpack | ||
29 | const regexToReplace = /\/\*$/; | ||
30 | const aliasKey = key.replace(regexToReplace, ''); | ||
31 | const aliasValue = value[0].replace(regexToReplace, ''); | ||
32 | return [aliasKey, root(aliasValue)]; | ||
33 | }) | ||
34 | .reduce((aliases, [key, value]) => { | ||
35 | aliases[key] = value; | ||
36 | return aliases; | ||
37 | }, webpackAliases); | ||
38 | return webpackAliases; | ||
39 | } |
File webpack/webpack.common.js added (mode: 100644) (index 0000000..3efcbf3) | |||
1 | const webpack = require('webpack'); | ||
2 | const { BaseHrefWebpackPlugin } = require('base-href-webpack-plugin'); | ||
3 | const CopyWebpackPlugin = require('copy-webpack-plugin'); | ||
4 | const HtmlWebpackPlugin = require('html-webpack-plugin'); | ||
5 | const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin; | ||
6 | const MergeJsonWebpackPlugin = require("merge-jsons-webpack-plugin"); | ||
7 | |||
8 | const utils = require('./utils.js'); | ||
9 | |||
10 | module.exports = (options) => ({ | ||
11 | resolve: { | ||
12 | extensions: ['.ts', '.js'], | ||
13 | modules: ['node_modules'], | ||
14 | mainFields: [ 'es2015', 'browser', 'module', 'main'], | ||
15 | alias: utils.mapTypescriptAliasToWebpackAlias() | ||
16 | }, | ||
17 | stats: { | ||
18 | children: false | ||
19 | }, | ||
20 | module: { | ||
21 | rules: [ | ||
22 | { | ||
23 | test: /(?:\.ngfactory\.js|\.ngstyle\.js|\.ts)$/, | ||
24 | loader: '@ngtools/webpack' | ||
25 | }, | ||
26 | { | ||
27 | test: /\.html$/, | ||
28 | loader: 'html-loader', | ||
29 | options: { | ||
30 | minimize: true, | ||
31 | caseSensitive: true, | ||
32 | removeAttributeQuotes:false, | ||
33 | minifyJS:false, | ||
34 | minifyCSS:false | ||
35 | }, | ||
36 | exclude: /(src\/main\/webapp\/index.html)/ | ||
37 | }, | ||
38 | { | ||
39 | test: /\.(jpe?g|png|gif|svg|woff2?|ttf|eot)$/i, | ||
40 | loader: 'file-loader', | ||
41 | options: { | ||
42 | digest: 'hex', | ||
43 | hash: 'sha512', | ||
44 | // For fixing src attr of image | ||
45 | // See https://github.com/jhipster/generator-jhipster/issues/11209 | ||
46 | name: 'content/[hash].[ext]', | ||
47 | esModule: false | ||
48 | } | ||
49 | }, | ||
50 | { | ||
51 | test: /manifest.webapp$/, | ||
52 | loader: 'file-loader', | ||
53 | options: { | ||
54 | name: 'manifest.webapp' | ||
55 | } | ||
56 | }, | ||
57 | // Ignore warnings about System.import in Angular | ||
58 | { test: /[\/\\]@angular[\/\\].+\.js$/, parser: { system: true } }, | ||
59 | ] | ||
60 | }, | ||
61 | plugins: [ | ||
62 | new webpack.DefinePlugin({ | ||
63 | 'process.env': { | ||
64 | NODE_ENV: `'${options.env}'`, | ||
65 | BUILD_TIMESTAMP: `'${new Date().getTime()}'`, | ||
66 | // APP_VERSION is passed as an environment variable from the Gradle / Maven build tasks. | ||
67 | VERSION: `'${process.env.hasOwnProperty('APP_VERSION') ? process.env.APP_VERSION : 'DEV'}'`, | ||
68 | DEBUG_INFO_ENABLED: options.env === 'development', | ||
69 | // The root URL for API calls, ending with a '/' - for example: `"https://www.jhipster.tech:8081/myservice/"`. | ||
70 | // If this URL is left empty (""), then it will be relative to the current context. | ||
71 | // If you use an API server, in `prod` mode, you will need to enable CORS | ||
72 | // (see the `jhipster.cors` common JHipster property in the `application-*.yml` configurations) | ||
73 | SERVER_API_URL: `''` | ||
74 | } | ||
75 | }), | ||
76 | new CopyWebpackPlugin([ | ||
77 | { from: './node_modules/swagger-ui-dist/*.{js,css,html,png}', to: 'swagger-ui', flatten: true, ignore: ['index.html'] }, | ||
78 | { from: './node_modules/axios/dist/axios.min.js', to: 'swagger-ui' }, | ||
79 | { from: './src/main/webapp/swagger-ui/', to: 'swagger-ui' }, | ||
80 | { from: './src/main/webapp/content/', to: 'content' }, | ||
81 | { from: './src/main/webapp/favicon.ico', to: 'favicon.ico' }, | ||
82 | { from: './src/main/webapp/manifest.webapp', to: 'manifest.webapp' }, | ||
83 | // jhipster-needle-add-assets-to-webpack - JHipster will add/remove third-party resources in this array | ||
84 | { from: './src/main/webapp/robots.txt', to: 'robots.txt' } | ||
85 | ]), | ||
86 | new MergeJsonWebpackPlugin({ | ||
87 | output: { | ||
88 | groupBy: [ | ||
89 | { pattern: "./src/main/webapp/i18n/hu/*.json", fileName: "./i18n/hu.json" }, | ||
90 | { pattern: "./src/main/webapp/i18n/en/*.json", fileName: "./i18n/en.json" } | ||
91 | // jhipster-needle-i18n-language-webpack - JHipster will add/remove languages in this array | ||
92 | ] | ||
93 | } | ||
94 | }), | ||
95 | new HtmlWebpackPlugin({ | ||
96 | template: './src/main/webapp/index.html', | ||
97 | chunks: ['polyfills', 'main', 'global'], | ||
98 | chunksSortMode: 'manual', | ||
99 | inject: 'body' | ||
100 | }), | ||
101 | new BaseHrefWebpackPlugin({ baseHref: '/' }), | ||
102 | new AngularCompilerPlugin({ | ||
103 | mainPath: utils.root('src/main/webapp/app/app.main.ts'), | ||
104 | tsConfigPath: utils.root('tsconfig.app.json'), | ||
105 | sourceMap: true | ||
106 | }) | ||
107 | ] | ||
108 | }); |
File webpack/webpack.dev.js added (mode: 100644) (index 0000000..0fb31af) | |||
1 | const webpack = require('webpack'); | ||
2 | const writeFilePlugin = require('write-file-webpack-plugin'); | ||
3 | const webpackMerge = require('webpack-merge'); | ||
4 | const BrowserSyncPlugin = require('browser-sync-webpack-plugin'); | ||
5 | const FriendlyErrorsWebpackPlugin = require('friendly-errors-webpack-plugin'); | ||
6 | const SimpleProgressWebpackPlugin = require('simple-progress-webpack-plugin'); | ||
7 | const WebpackNotifierPlugin = require('webpack-notifier'); | ||
8 | const path = require('path'); | ||
9 | const sass = require('sass'); | ||
10 | |||
11 | const utils = require('./utils.js'); | ||
12 | const commonConfig = require('./webpack.common.js'); | ||
13 | |||
14 | const ENV = 'development'; | ||
15 | |||
16 | module.exports = (options) => webpackMerge(commonConfig({ env: ENV }), { | ||
17 | devtool: 'eval-source-map', | ||
18 | devServer: { | ||
19 | contentBase: './target/classes/static/', | ||
20 | proxy: [{ | ||
21 | context: [ | ||
22 | '/api', | ||
23 | '/services', | ||
24 | '/management', | ||
25 | '/swagger-resources', | ||
26 | '/v2/api-docs', | ||
27 | '/h2-console', | ||
28 | '/auth' | ||
29 | ], | ||
30 | target: `http${options.tls ? 's' : ''}://localhost:8080`, | ||
31 | secure: false, | ||
32 | changeOrigin: options.tls | ||
33 | }], | ||
34 | stats: options.stats, | ||
35 | watchOptions: { | ||
36 | ignored: /node_modules/ | ||
37 | }, | ||
38 | https: options.tls, | ||
39 | historyApiFallback: true | ||
40 | }, | ||
41 | entry: { | ||
42 | global: './src/main/webapp/content/scss/global.scss', | ||
43 | main: './src/main/webapp/app/app.main' | ||
44 | }, | ||
45 | output: { | ||
46 | path: utils.root('target/classes/static/'), | ||
47 | filename: 'app/[name].bundle.js', | ||
48 | chunkFilename: 'app/[id].chunk.js' | ||
49 | }, | ||
50 | module: { | ||
51 | rules: [{ | ||
52 | test: /\.(j|t)s$/, | ||
53 | enforce: 'pre', | ||
54 | loader: 'eslint-loader', | ||
55 | exclude: /node_modules/ | ||
56 | }, | ||
57 | { | ||
58 | test: /\.scss$/, | ||
59 | use: ['to-string-loader', 'css-loader', 'postcss-loader', { | ||
60 | loader: 'sass-loader', | ||
61 | options: { implementation: sass } | ||
62 | }], | ||
63 | exclude: /(vendor\.scss|global\.scss)/ | ||
64 | }, | ||
65 | { | ||
66 | test: /(vendor\.scss|global\.scss)/, | ||
67 | use: ['style-loader', 'css-loader', 'postcss-loader', { | ||
68 | loader: 'sass-loader', | ||
69 | options: { implementation: sass } | ||
70 | }] | ||
71 | }] | ||
72 | }, | ||
73 | stats: process.env.JHI_DISABLE_WEBPACK_LOGS ? 'none' : options.stats, | ||
74 | plugins: [ | ||
75 | process.env.JHI_DISABLE_WEBPACK_LOGS | ||
76 | ? null | ||
77 | : new SimpleProgressWebpackPlugin({ | ||
78 | format: options.stats === 'minimal' ? 'compact' : 'expanded' | ||
79 | }), | ||
80 | new FriendlyErrorsWebpackPlugin(), | ||
81 | new BrowserSyncPlugin({ | ||
82 | https: options.tls, | ||
83 | host: 'localhost', | ||
84 | port: 9000, | ||
85 | proxy: { | ||
86 | target: `http${options.tls ? 's' : ''}://localhost:9060`, | ||
87 | proxyOptions: { | ||
88 | changeOrigin: false //pass the Host header to the backend unchanged https://github.com/Browsersync/browser-sync/issues/430 | ||
89 | } | ||
90 | }, | ||
91 | socket: { | ||
92 | clients: { | ||
93 | heartbeatTimeout: 60000 | ||
94 | } | ||
95 | } | ||
96 | /* | ||
97 | ,ghostMode: { // uncomment this part to disable BrowserSync ghostMode; https://github.com/jhipster/generator-jhipster/issues/11116 | ||
98 | clicks: false, | ||
99 | location: false, | ||
100 | forms: false, | ||
101 | scroll: false | ||
102 | } */ | ||
103 | }, { | ||
104 | reload: false | ||
105 | }), | ||
106 | new webpack.ContextReplacementPlugin( | ||
107 | /angular(\\|\/)core(\\|\/)/, | ||
108 | path.resolve(__dirname, './src/main/webapp/') | ||
109 | ), | ||
110 | new writeFilePlugin(), | ||
111 | new webpack.WatchIgnorePlugin([ | ||
112 | utils.root('src/test'), | ||
113 | ]), | ||
114 | new WebpackNotifierPlugin({ | ||
115 | title: 'JHipster', | ||
116 | contentImage: path.join(__dirname, 'logo-jhipster.png') | ||
117 | }) | ||
118 | ].filter(Boolean), | ||
119 | mode: 'development' | ||
120 | }); |
File webpack/webpack.prod.js added (mode: 100644) (index 0000000..c2d3477) | |||
1 | const webpack = require('webpack'); | ||
2 | const webpackMerge = require('webpack-merge'); | ||
3 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); | ||
4 | const OptimizeCSSAssetsPlugin = require("optimize-css-assets-webpack-plugin"); | ||
5 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; | ||
6 | const MomentLocalesPlugin = require('moment-locales-webpack-plugin'); | ||
7 | const TerserPlugin = require('terser-webpack-plugin'); | ||
8 | const WorkboxPlugin = require('workbox-webpack-plugin'); | ||
9 | const path = require('path'); | ||
10 | |||
11 | const utils = require('./utils.js'); | ||
12 | const commonConfig = require('./webpack.common.js'); | ||
13 | |||
14 | const ENV = 'production'; | ||
15 | const sass = require('sass'); | ||
16 | |||
17 | module.exports = webpackMerge(commonConfig({ env: ENV }), { | ||
18 | // Enable source maps. Please note that this will slow down the build. | ||
19 | // You have to enable it in Terser config below and in tsconfig.json as well | ||
20 | // devtool: 'source-map', | ||
21 | entry: { | ||
22 | global: './src/main/webapp/content/scss/global.scss', | ||
23 | main: './src/main/webapp/app/app.main' | ||
24 | }, | ||
25 | output: { | ||
26 | path: utils.root('target/classes/static/'), | ||
27 | filename: 'app/[name].[hash].bundle.js', | ||
28 | chunkFilename: 'app/[id].[hash].chunk.js' | ||
29 | }, | ||
30 | module: { | ||
31 | rules: [ | ||
32 | { | ||
33 | test: /\.scss$/, | ||
34 | use: ['to-string-loader', 'css-loader', 'postcss-loader', { | ||
35 | loader: 'sass-loader', | ||
36 | options: { implementation: sass } | ||
37 | }], | ||
38 | exclude: /(vendor\.scss|global\.scss)/ | ||
39 | }, | ||
40 | { | ||
41 | test: /(vendor\.scss|global\.scss)/, | ||
42 | use: [ | ||
43 | { | ||
44 | loader: MiniCssExtractPlugin.loader, | ||
45 | options: { | ||
46 | publicPath: '../' | ||
47 | } | ||
48 | }, | ||
49 | 'css-loader', | ||
50 | 'postcss-loader', | ||
51 | { | ||
52 | loader: 'sass-loader', | ||
53 | options: { implementation: sass } | ||
54 | } | ||
55 | ] | ||
56 | }, | ||
57 | { | ||
58 | test: /\.css$/, | ||
59 | use: ['to-string-loader', 'css-loader'], | ||
60 | exclude: /(vendor\.css|global\.css)/ | ||
61 | }, | ||
62 | { | ||
63 | test: /(vendor\.css|global\.css)/, | ||
64 | use: [ | ||
65 | { | ||
66 | loader: MiniCssExtractPlugin.loader, | ||
67 | options: { | ||
68 | publicPath: '../' | ||
69 | } | ||
70 | }, | ||
71 | 'css-loader', | ||
72 | 'postcss-loader' | ||
73 | ] | ||
74 | }] | ||
75 | }, | ||
76 | optimization: { | ||
77 | runtimeChunk: false, | ||
78 | minimizer: [ | ||
79 | new TerserPlugin({ | ||
80 | parallel: true, | ||
81 | cache: true, | ||
82 | // sourceMap: true, // Enable source maps. Please note that this will slow down the build | ||
83 | terserOptions: { | ||
84 | ecma: 6, | ||
85 | ie8: false, | ||
86 | toplevel: true, | ||
87 | module: true, | ||
88 | compress: { | ||
89 | dead_code: true, | ||
90 | warnings: false, | ||
91 | properties: true, | ||
92 | drop_debugger: true, | ||
93 | conditionals: true, | ||
94 | booleans: true, | ||
95 | loops: true, | ||
96 | unused: true, | ||
97 | toplevel: true, | ||
98 | if_return: true, | ||
99 | inline: true, | ||
100 | join_vars: true, | ||
101 | ecma: 6, | ||
102 | module: true | ||
103 | }, | ||
104 | output: { | ||
105 | comments: false, | ||
106 | beautify: false, | ||
107 | indent_level: 2, | ||
108 | ecma: 6 | ||
109 | }, | ||
110 | mangle: { | ||
111 | module: true, | ||
112 | toplevel: true | ||
113 | } | ||
114 | } | ||
115 | }), | ||
116 | new OptimizeCSSAssetsPlugin({}) | ||
117 | ] | ||
118 | }, | ||
119 | plugins: [ | ||
120 | new MiniCssExtractPlugin({ | ||
121 | // Options similar to the same options in webpackOptions.output | ||
122 | // both options are optional | ||
123 | filename: 'content/[name].[contenthash].css', | ||
124 | chunkFilename: 'content/[id].css' | ||
125 | }), | ||
126 | new MomentLocalesPlugin({ | ||
127 | localesToKeep: [ | ||
128 | 'hu', | ||
129 | 'en' | ||
130 | // jhipster-needle-i18n-language-moment-webpack - JHipster will add/remove languages in this array | ||
131 | ] | ||
132 | }), | ||
133 | new BundleAnalyzerPlugin({ | ||
134 | analyzerMode: 'static', | ||
135 | openAnalyzer: false, | ||
136 | // Webpack statistics in target folder | ||
137 | reportFilename: '../stats.html' | ||
138 | }), | ||
139 | new webpack.LoaderOptionsPlugin({ | ||
140 | minimize: true, | ||
141 | debug: false | ||
142 | }), | ||
143 | new WorkboxPlugin.GenerateSW({ | ||
144 | clientsClaim: true, | ||
145 | skipWaiting: true, | ||
146 | exclude: [/swagger-ui/] | ||
147 | }) | ||
148 | ], | ||
149 | mode: 'production' | ||
150 | }); |