generator-jhipster 7.2.0 → 7.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. package/cli/environment-builder.js +1 -0
  2. package/cli/import-jdl.js +3 -2
  3. package/cli/jdl.js +1 -0
  4. package/cli/jhipster-command.js +2 -2
  5. package/cli/program.js +32 -29
  6. package/generators/app/index.js +35 -26
  7. package/generators/aws/index.js +8 -8
  8. package/generators/aws/lib/eb.js +1 -1
  9. package/generators/azure-app-service/index.js +16 -9
  10. package/generators/azure-app-service/templates/github/workflows/azure-app-service.yml.ejs +2 -2
  11. package/generators/azure-spring-cloud/index.js +16 -9
  12. package/generators/azure-spring-cloud/templates/github/workflows/azure-spring-cloud.yml.ejs +2 -2
  13. package/generators/bootstrap/index.js +57 -61
  14. package/generators/ci-cd/index.js +11 -8
  15. package/generators/ci-cd/templates/github-actions.yml.ejs +1 -1
  16. package/generators/ci-cd/templates/travis.yml.ejs +9 -4
  17. package/generators/client/__workflow/devserver-angular.json +1 -1
  18. package/generators/client/__workflow/devserver-react.json +1 -1
  19. package/generators/client/__workflow/devserver-vue.json +1 -1
  20. package/generators/client/files-angular.js +6 -0
  21. package/generators/client/files-common.js +6 -2
  22. package/generators/client/files-react.js +13 -2
  23. package/generators/client/files-vue.js +56 -6
  24. package/generators/client/index.js +114 -32
  25. package/generators/client/needle-api/needle-client-angular.js +1 -1
  26. package/generators/client/needle-api/needle-client-vue.js +57 -7
  27. package/generators/client/templates/angular/.eslintrc.json.ejs +1 -0
  28. package/generators/client/templates/angular/package.json +19 -19
  29. package/generators/client/templates/angular/package.json.ejs +2 -1
  30. package/generators/client/templates/angular/src/main/webapp/app/account/activate/activate.component.spec.ts.ejs +52 -54
  31. package/generators/client/templates/angular/src/main/webapp/app/account/activate/activate.service.spec.ts.ejs +65 -0
  32. package/generators/client/templates/angular/src/main/webapp/app/account/password/password-strength-bar/password-strength-bar.component.spec.ts.ejs +35 -37
  33. package/generators/client/templates/angular/src/main/webapp/app/account/password/password.component.spec.ts.ejs +78 -80
  34. package/generators/client/templates/angular/src/main/webapp/app/account/password/password.service.spec.ts.ejs +41 -0
  35. package/generators/client/templates/angular/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.spec.ts.ejs +73 -75
  36. package/generators/client/templates/angular/src/main/webapp/app/account/password-reset/finish/password-reset-finish.service.spec.ts.ejs +62 -0
  37. package/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/password-reset-init.component.spec.ts.ejs +44 -46
  38. package/generators/client/templates/angular/src/main/webapp/app/account/password-reset/init/password-reset-init.service.spec.ts.ejs +61 -0
  39. package/generators/client/templates/angular/src/main/webapp/app/account/register/register.component.spec.ts.ejs +116 -118
  40. package/generators/client/templates/angular/src/main/webapp/app/account/register/register.service.spec.ts.ejs +66 -0
  41. package/generators/client/templates/angular/src/main/webapp/app/account/sessions/sessions.component.spec.ts.ejs +75 -77
  42. package/generators/client/templates/angular/src/main/webapp/app/account/settings/settings.component.spec.ts.ejs +74 -76
  43. package/generators/client/templates/angular/src/main/webapp/app/admin/configuration/configuration.component.spec.ts.ejs +48 -50
  44. package/generators/client/templates/angular/src/main/webapp/app/admin/configuration/configuration.service.spec.ts.ejs +50 -52
  45. package/generators/client/templates/angular/src/main/webapp/app/admin/health/health.component.spec.ts.ejs +45 -47
  46. package/generators/client/templates/angular/src/main/webapp/app/admin/health/health.service.spec.ts.ejs +66 -0
  47. package/generators/client/templates/angular/src/main/webapp/app/admin/health/modal/health-modal.component.spec.ts.ejs +99 -101
  48. package/generators/client/templates/angular/src/main/webapp/app/admin/logs/logs.component.spec.ts.ejs +61 -63
  49. package/generators/client/templates/angular/src/main/webapp/app/admin/logs/logs.service.spec.ts.ejs +19 -21
  50. package/generators/client/templates/angular/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.html.ejs +2 -2
  51. package/generators/client/templates/angular/src/main/webapp/app/admin/metrics/metrics.component.spec.ts.ejs +28 -30
  52. package/generators/client/templates/angular/src/main/webapp/app/admin/metrics/metrics.service.spec.ts.ejs +62 -64
  53. package/generators/client/templates/angular/src/main/webapp/app/admin/user-management/delete/user-management-delete-dialog.component.spec.ts.ejs +35 -37
  54. package/generators/client/templates/angular/src/main/webapp/app/admin/user-management/detail/user-management-detail.component.spec.ts.ejs +40 -42
  55. package/generators/client/templates/angular/src/main/webapp/app/admin/user-management/list/user-management.component.spec.ts.ejs +87 -89
  56. package/generators/client/templates/angular/src/main/webapp/app/admin/user-management/service/user-management.service.spec.ts.ejs +41 -43
  57. package/generators/client/templates/angular/src/main/webapp/app/admin/user-management/update/user-management-update.component.spec.ts.ejs +81 -83
  58. package/generators/client/templates/angular/src/main/webapp/app/app.module.ts.ejs +3 -0
  59. package/generators/client/templates/angular/src/main/webapp/app/core/auth/account.service.spec.ts.ejs +178 -180
  60. package/generators/client/templates/angular/src/main/webapp/app/core/config/application-config.service.ts.ejs +9 -0
  61. package/generators/client/templates/angular/src/main/webapp/app/entities/user/user.service.spec.ts.ejs +87 -89
  62. package/generators/client/templates/angular/src/main/webapp/app/home/home.component.spec.ts.ejs +93 -95
  63. package/generators/client/templates/angular/src/main/webapp/app/layouts/main/main.component.spec.ts.ejs +166 -168
  64. package/generators/client/templates/angular/src/main/webapp/app/layouts/navbar/navbar.component.spec.ts.ejs +66 -68
  65. package/generators/client/templates/angular/src/main/webapp/app/layouts/profiles/page-ribbon.component.spec.ts.ejs +27 -29
  66. package/generators/client/templates/angular/src/main/webapp/app/login/login.component.spec.ts.ejs +112 -114
  67. package/generators/client/templates/angular/src/main/webapp/app/shared/alert/alert-error.component.spec.ts.ejs +132 -134
  68. package/generators/client/templates/angular/src/main/webapp/app/shared/alert/alert.component.spec.ts.ejs +29 -31
  69. package/generators/client/templates/angular/webpack/webpack.custom.js.ejs +2 -3
  70. package/generators/client/templates/common/README.md.jhi.client.ejs +34 -0
  71. package/generators/client/templates/common/package.json +7 -7
  72. package/generators/client/templates/common/webpack/webpack.microfrontend.js.jhi.ejs +56 -0
  73. package/generators/client/templates/react/.eslintrc.json.ejs +1 -0
  74. package/generators/client/templates/react/package.json +57 -56
  75. package/generators/client/templates/react/package.json.ejs +5 -2
  76. package/generators/client/templates/react/src/main/webapp/app/app.scss.ejs +0 -3
  77. package/generators/client/templates/react/src/main/webapp/app/modules/account/password/password.tsx.ejs +2 -2
  78. package/generators/client/templates/react/src/main/webapp/app/modules/administration/configuration/configuration.tsx.ejs +2 -2
  79. package/generators/client/templates/react/src/main/webapp/app/modules/administration/gateway/gateway.tsx.ejs +2 -2
  80. package/generators/client/templates/react/src/main/webapp/app/modules/administration/metrics/metrics.tsx.ejs +6 -6
  81. package/generators/client/templates/react/src/main/webapp/app/modules/administration/user-management/user-management.tsx.ejs +8 -8
  82. package/generators/client/templates/react/src/main/webapp/app/modules/home/home.tsx.ejs +1 -1
  83. package/generators/client/templates/react/src/main/webapp/app/shared/layout/header/header.tsx.ejs +1 -1
  84. package/generators/client/templates/react/src/main/webapp/app/shared/layout/menus/account.tsx.ejs +3 -3
  85. package/generators/client/templates/react/src/main/webapp/app/shared/layout/menus/admin.tsx.ejs +7 -7
  86. package/generators/client/templates/react/src/main/webapp/app/shared/layout/menus/menu-components.tsx.ejs +1 -1
  87. package/generators/client/templates/react/webpack/webpack.dev.js.ejs +17 -1
  88. package/generators/client/templates/react/webpack/webpack.prod.js.ejs +13 -1
  89. package/generators/client/templates/vue/.eslintrc.js.ejs +8 -5
  90. package/generators/client/templates/vue/package.json +40 -49
  91. package/generators/client/templates/vue/package.json.ejs +14 -18
  92. package/generators/client/templates/vue/src/main/webapp/app/account/account.service.ts.ejs +6 -5
  93. package/generators/client/templates/vue/src/main/webapp/app/account/settings/settings.vue.ejs +7 -1
  94. package/generators/client/templates/vue/src/main/webapp/app/admin/configuration/configuration.service.ts.ejs +1 -1
  95. package/generators/client/templates/vue/src/main/webapp/app/admin/configuration/configuration.vue.ejs +1 -1
  96. package/generators/client/templates/vue/src/main/webapp/app/admin/metrics/metrics.component.ts.ejs +1 -1
  97. package/generators/client/templates/vue/src/main/webapp/app/admin/tracker/tracker.service.ts.ejs +5 -4
  98. package/generators/client/templates/vue/src/main/webapp/app/admin/user-management/user-management-edit.component.ts.ejs +9 -0
  99. package/generators/client/templates/vue/src/main/webapp/app/admin/user-management/user-management-view.component.ts.ejs +5 -0
  100. package/generators/client/templates/vue/src/main/webapp/app/admin/user-management/user-management.component.ts.ejs +5 -0
  101. package/generators/client/templates/vue/src/main/webapp/app/constants.ts.ejs +16 -6
  102. package/generators/client/templates/vue/src/main/webapp/app/core/jhi-navbar/jhi-navbar.component.ts.ejs +27 -8
  103. package/generators/client/templates/vue/src/main/webapp/app/core/jhi-navbar/jhi-navbar.vue.ejs +6 -0
  104. package/generators/client/templates/vue/src/main/webapp/app/declarations.d.ts.ejs +41 -0
  105. package/generators/client/templates/vue/src/main/webapp/app/entities/entities-menu.component.ts.ejs +34 -0
  106. package/generators/client/templates/vue/src/main/webapp/app/entities/entities-menu.vue.ejs +13 -0
  107. package/generators/client/templates/vue/src/main/webapp/app/entities/entities.component.ts.ejs +14 -0
  108. package/generators/client/templates/vue/src/main/webapp/app/entities/entities.vue.ejs +5 -0
  109. package/generators/client/templates/vue/{webpack/utils.js.ejs → src/main/webapp/app/index.ts.ejs} +1 -12
  110. package/generators/client/templates/vue/src/main/webapp/app/locale/translation.service.ts.ejs +26 -9
  111. package/generators/client/templates/vue/src/main/webapp/app/main.ts.ejs +23 -11
  112. package/generators/client/templates/vue/src/main/webapp/app/router/admin.ts.ejs +4 -4
  113. package/generators/client/templates/vue/src/main/webapp/app/router/entities.ts.ejs +45 -3
  114. package/generators/client/templates/vue/src/main/webapp/app/router/index.ts.ejs +19 -3
  115. package/generators/client/templates/vue/src/main/webapp/app/shared/alert/alert.service.ts.ejs +61 -0
  116. package/generators/client/templates/vue/src/main/webapp/app/shared/config/axios-interceptor.ts.ejs +0 -2
  117. package/generators/client/templates/vue/src/main/webapp/app/shared/data/data-utils.service.ts.ejs +3 -1
  118. package/generators/client/templates/vue/src/main/webapp/app/shims-vue.d.ts.ejs +17 -3
  119. package/generators/client/templates/vue/src/test/javascript/jest.conf.js.ejs +25 -10
  120. package/generators/client/templates/vue/src/test/javascript/spec/app/account/account.service.spec.ts.ejs +2 -2
  121. package/generators/client/templates/vue/src/test/javascript/spec/app/account/login-form/login-form.component.spec.ts.ejs +2 -2
  122. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/tracker/tracker.component.spec.ts.ejs +12 -12
  123. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/tracker/tracker.service.spec.ts.ejs +2 -1
  124. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/user-management/user-management-edit.component.spec.ts.ejs +5 -1
  125. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/user-management/user-management-view.component.spec.ts.ejs +2 -1
  126. package/generators/client/templates/vue/src/test/javascript/spec/app/admin/user-management/user-management.component.spec.ts.ejs +5 -1
  127. package/generators/client/templates/vue/src/test/javascript/spec/app/core/jhi-navbar/jhi-navbar.component.spec.ts.ejs +10 -4
  128. package/generators/client/templates/vue/src/test/javascript/spec/app/entities/entities-menu.spec.ts.ejs +52 -0
  129. package/generators/client/templates/vue/src/test/javascript/spec/app/microfrontends/entities-menu.component.ts.ejs +4 -0
  130. package/generators/client/templates/vue/src/test/javascript/spec/app/microfrontends/entities-menu.vue.ejs +7 -0
  131. package/generators/client/templates/vue/src/test/javascript/spec/app/microfrontends/entities-router.ts.ejs +1 -0
  132. package/generators/client/templates/vue/src/test/javascript/spec/app/shared/alert/alert.service.spec.ts.ejs +124 -0
  133. package/generators/client/templates/vue/src/test/javascript/spec/app/shared/config/axios-interceptor.spec.ts.ejs +0 -1
  134. package/generators/client/templates/vue/tsconfig.json.ejs +6 -10
  135. package/generators/client/templates/vue/tsconfig.spec.json.ejs +37 -0
  136. package/generators/client/templates/vue/webpack/config.js.ejs +50 -0
  137. package/generators/client/templates/vue/webpack/vue.utils.js.ejs +33 -32
  138. package/generators/client/templates/vue/webpack/webpack.common.js.ejs +152 -126
  139. package/generators/client/templates/vue/webpack/webpack.dev.js.ejs +19 -76
  140. package/generators/client/templates/vue/webpack/webpack.microfrontend.js.jhi.vue.ejs +77 -0
  141. package/generators/client/templates/vue/webpack/webpack.prod.js.ejs +5 -41
  142. package/generators/cloudfoundry/index.js +9 -9
  143. package/generators/common/index.js +12 -10
  144. package/generators/common/templates/.husky/pre-commit +1 -1
  145. package/generators/common/templates/.prettierrc.ejs +1 -1
  146. package/generators/common/templates/README.md.jhi.ejs +21 -0
  147. package/generators/common/templates/package.json +4 -4
  148. package/generators/cypress/index.js +12 -9
  149. package/generators/cypress/templates/cypress.json.ejs +9 -2
  150. package/generators/cypress/templates/src/test/javascript/cypress/plugins/index.ts.ejs +4 -4
  151. package/generators/cypress/templates/src/test/javascript/cypress/support/commands.ts.ejs +30 -2
  152. package/generators/cypress/templates/src/test/javascript/cypress/support/entity.ts.ejs +4 -4
  153. package/generators/cypress/templates/src/test/javascript/cypress/support/index.ts.ejs +1 -1
  154. package/generators/cypress/templates/src/test/javascript/cypress/support/management.ts.ejs +1 -1
  155. package/generators/cypress/templates/src/test/javascript/cypress/support/navbar.ts.ejs +1 -1
  156. package/generators/database-changelog/index.js +33 -22
  157. package/generators/database-changelog-liquibase/index.js +12 -8
  158. package/generators/database-changelog-liquibase/templates/src/main/resources/config/liquibase/changelog/updated_entity_constraints.xml.ejs +1 -1
  159. package/generators/docker-compose/index.js +11 -12
  160. package/generators/docker-compose/templates/realm-config/jhipster-realm.json.ejs +13 -12
  161. package/generators/entities/index.js +35 -26
  162. package/generators/entities-client/index.js +10 -7
  163. package/generators/entity/index.js +49 -29
  164. package/generators/entity-client/files.js +7 -16
  165. package/generators/entity-client/index.js +74 -11
  166. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/delete/entity-management-delete-dialog.component.spec.ts.ejs +42 -44
  167. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/detail/entity-management-detail.component.spec.ts.ejs +58 -60
  168. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/entity-management.module.ts.ejs +1 -1
  169. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/list/entity-management.component.spec.ts.ejs +105 -107
  170. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/list/entity-management.component.ts.ejs +8 -1
  171. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/route/entity-management-routing-resolve.service.spec.ts.ejs +52 -54
  172. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/route/entity-management-routing.module.ts.ejs +1 -1
  173. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/service/entity.service.spec.ts.ejs +173 -175
  174. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/update/entity-management-update.component.html.ejs +2 -4
  175. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/update/entity-management-update.component.spec.ts.ejs +193 -195
  176. package/generators/entity-client/templates/angular/src/main/webapp/app/entities/update/entity-management-update.component.ts.ejs +7 -0
  177. package/generators/entity-client/templates/common/src/test/javascript/cypress/integration/entity/entity.spec.ts.ejs +269 -109
  178. package/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-delete-dialog.tsx.ejs +5 -2
  179. package/generators/entity-client/templates/react/src/main/webapp/app/entities/entity-update.tsx.ejs +17 -14
  180. package/generators/entity-client/templates/react/src/main/webapp/app/entities/entity.tsx.ejs +11 -13
  181. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity-details.component.ts.ejs +5 -0
  182. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity-update.component.ts.ejs +23 -8
  183. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity-update.vue.ejs +6 -9
  184. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity.component.ts.ejs +9 -1
  185. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity.model.ts.ejs +1 -1
  186. package/generators/entity-client/templates/vue/src/main/webapp/app/entities/entity.service.ts.ejs +2 -6
  187. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity-details.component.spec.ts.ejs +2 -1
  188. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity-update.component.spec.ts.ejs +8 -1
  189. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity.component.spec.ts.ejs +8 -2
  190. package/generators/entity-client/templates/vue/src/test/javascript/spec/app/entities/entity.service.spec.ts.ejs +1 -1
  191. package/generators/entity-i18n/index.js +7 -4
  192. package/generators/entity-server/files-couchbase.js +2 -2
  193. package/generators/entity-server/files.js +35 -30
  194. package/generators/entity-server/index.js +12 -8
  195. package/generators/entity-server/templates/couchbase/src/main/java/package/repository/EntityRepository.java.ejs +2 -2
  196. package/generators/entity-server/templates/couchbase/src/main/resources/config/couchmove/changelog/entity.fts.ejs +1 -1
  197. package/generators/entity-server/templates/src/main/java/package/domain/Entity.java.jhi.ejs +6 -2
  198. package/generators/entity-server/templates/src/main/java/package/domain/enumeration/Enum.java.ejs +1 -1
  199. package/generators/entity-server/templates/src/main/java/package/repository/EntityRepository.java.ejs +2 -2
  200. package/generators/entity-server/templates/src/main/java/package/repository/EntityRepositoryInternalImpl_reactive.java.ejs +17 -30
  201. package/generators/entity-server/templates/src/main/java/package/repository/EntityRepository_reactive.java.ejs +5 -5
  202. package/generators/entity-server/templates/src/main/java/package/repository/EntitySqlHelper_reactive.java.ejs +46 -0
  203. package/generators/entity-server/templates/src/main/java/package/repository/rowmapper/EntityRowMapper.java.ejs +3 -3
  204. package/generators/entity-server/templates/src/main/java/package/repository/search/EntitySearchRepository.java.ejs +2 -2
  205. package/generators/entity-server/templates/src/main/java/package/service/EntityQueryService.java.ejs +8 -8
  206. package/generators/entity-server/templates/src/main/java/package/service/EntityService.java.ejs +4 -4
  207. package/generators/entity-server/templates/src/main/java/package/service/criteria/EntityCriteria.java.ejs +4 -4
  208. package/generators/entity-server/templates/src/main/java/package/service/dto/EntityDTO.java.ejs +7 -3
  209. package/generators/entity-server/templates/src/main/java/package/service/impl/EntityServiceImpl.java.ejs +8 -8
  210. package/generators/entity-server/templates/src/main/java/package/service/mapper/BaseEntityMapper.java.ejs +1 -1
  211. package/generators/entity-server/templates/src/main/java/package/service/mapper/EntityMapper.java.ejs +7 -3
  212. package/generators/entity-server/templates/src/main/java/package/web/rest/EntityResource.java.ejs +51 -53
  213. package/generators/entity-server/templates/src/test/java/package/domain/EntityTest.java.ejs +1 -1
  214. package/generators/entity-server/templates/src/test/java/package/repository/search/EntitySearchRepositoryMockConfiguration.java.ejs +1 -1
  215. package/generators/entity-server/templates/src/test/java/package/service/dto/EntityDTOTest.java.ejs +1 -1
  216. package/generators/entity-server/templates/src/test/java/package/service/mapper/EntityMapperTest.java.ejs +1 -1
  217. package/generators/entity-server/templates/src/test/java/package/web/rest/EntityResourceIT.java.ejs +17 -14
  218. package/generators/gae/index.js +10 -10
  219. package/generators/generator-base-blueprint.js +14 -46
  220. package/generators/generator-base-private.js +42 -22
  221. package/generators/generator-base.js +57 -20
  222. package/generators/generator-constants.js +29 -21
  223. package/generators/generator-transforms.js +39 -27
  224. package/generators/heroku/index.js +27 -48
  225. package/generators/init/constants.cjs +1 -1
  226. package/generators/init/templates/.husky/pre-commit +1 -1
  227. package/generators/java/constants.cjs +1 -1
  228. package/generators/kubernetes/files.js +3 -0
  229. package/generators/kubernetes/index.js +10 -10
  230. package/generators/kubernetes/templates/db/couchbase.yml.ejs +1 -1
  231. package/generators/kubernetes/templates/deployment.yml.ejs +8 -3
  232. package/generators/kubernetes/templates/istio/destination-rule.yml.ejs +1 -1
  233. package/generators/kubernetes/templates/istio/gateway/grafana-gateway.yml.ejs +5 -2
  234. package/generators/kubernetes/templates/istio/gateway/jhipster-grafana-gateway.yml.ejs +5 -2
  235. package/generators/kubernetes/templates/istio/gateway/kiali-gateway.yml.ejs +10 -8
  236. package/generators/kubernetes/templates/istio/gateway/zipkin-gateway.yml.ejs +5 -2
  237. package/generators/kubernetes/templates/istio/gateway.yml.ejs +7 -5
  238. package/generators/kubernetes/templates/secret/couchbase-secret.yml.ejs +9 -0
  239. package/generators/kubernetes-base.js +1 -0
  240. package/generators/kubernetes-helm/files.js +3 -8
  241. package/generators/kubernetes-helm/index.js +10 -10
  242. package/generators/kubernetes-helm/templates/README-KUBERNETES-HELM.md.ejs +0 -1
  243. package/generators/kubernetes-helm/templates/app/Chart.yml.ejs +27 -0
  244. package/generators/kubernetes-helm/templates/app/helpers.tpl.ejs +0 -11
  245. package/generators/kubernetes-helm/templates/app/requirements.yml.ejs +7 -2
  246. package/generators/kubernetes-helm/templates/app/values.yml.ejs +68 -5
  247. package/generators/kubernetes-helm/templates/csvc/Chart.yml.ejs +17 -0
  248. package/generators/kubernetes-helm/templates/csvc/requirements.yml.ejs +2 -2
  249. package/generators/kubernetes-knative/index.js +10 -10
  250. package/generators/kubernetes-knative/templates/istio/gateway.yml.ejs +6 -4
  251. package/generators/kubernetes-knative/templates/service.yml.ejs +1 -1
  252. package/generators/languages/index.js +13 -13
  253. package/generators/languages/templates/src/main/webapp/i18n/hr/reset.json.ejs +1 -2
  254. package/generators/languages/templates/src/main/webapp/i18n/vi/login.json +1 -1
  255. package/generators/maven/templates/.mvn/wrapper/maven-wrapper.properties +1 -1
  256. package/generators/openapi-client/index.js +13 -10
  257. package/generators/openshift/index.js +10 -11
  258. package/generators/openshift/templates/deployment.yml.ejs +1 -1
  259. package/generators/page/index.js +12 -10
  260. package/generators/server/__snapshots__/generator.spec.mjs.snap +12 -0
  261. package/generators/server/files-sql.js +52 -0
  262. package/generators/server/files.js +15 -0
  263. package/generators/server/index.js +100 -33
  264. package/generators/server/needle-api/needle-server-cache.js +4 -6
  265. package/generators/server/templates/.mvn/wrapper/maven-wrapper.properties +1 -1
  266. package/generators/server/templates/build.gradle.ejs +17 -1
  267. package/generators/server/templates/gradle.properties.ejs +11 -11
  268. package/generators/server/templates/npmw +1 -1
  269. package/generators/server/templates/npmw.cmd +1 -1
  270. package/generators/server/templates/pom.xml.ejs +128 -9
  271. package/generators/server/templates/settings.gradle.ejs +9 -0
  272. package/generators/server/templates/sql/reactive/src/main/java/package/repository/UserSqlHelper.java.ejs +48 -0
  273. package/generators/server/templates/src/main/docker/app.yml.ejs +2 -1
  274. package/generators/server/templates/src/main/docker/config/realm-config/jhipster-realm.json.ejs +13 -12
  275. package/generators/server/templates/src/main/java/package/aop/logging/LoggingAspect.java.ejs +1 -1
  276. package/generators/server/templates/src/main/java/package/config/DatabaseConfiguration_cassandra.java.ejs +0 -6
  277. package/generators/server/templates/src/main/java/package/config/DatabaseConfiguration_sql.java.ejs +2 -2
  278. package/generators/server/templates/src/main/java/package/config/JacksonConfiguration.java.ejs +1 -1
  279. package/generators/server/templates/src/main/java/package/config/LocaleConfiguration.java.ejs +0 -2
  280. package/generators/server/templates/src/main/java/package/config/SecurityConfiguration.java.ejs +2 -5
  281. package/generators/server/templates/src/main/java/package/config/SecurityConfiguration_reactive.java.ejs +9 -1
  282. package/generators/server/templates/src/main/java/package/config/WebConfigurer.java.ejs +0 -1
  283. package/generators/server/templates/src/main/java/package/management/SecurityMetersService.java.ejs +68 -0
  284. package/generators/server/templates/src/main/java/package/repository/UserRepository.java.ejs +0 -23
  285. package/generators/server/templates/src/main/java/package/security/PersistentTokenRememberMeServices.java.ejs +0 -2
  286. package/generators/server/templates/src/main/java/package/security/jwt/TokenProvider.java.ejs +29 -4
  287. package/generators/server/templates/src/main/java/package/security/oauth2/CustomClaimConverter.java.ejs +21 -9
  288. package/generators/server/templates/src/main/java/package/service/UserService.java.ejs +13 -5
  289. package/generators/server/templates/src/main/resources/config/application-dev.yml.ejs +1 -1
  290. package/generators/server/templates/src/main/resources/config/application-prod.yml.ejs +1 -1
  291. package/generators/server/templates/src/main/resources/config/application.yml.ejs +7 -7
  292. package/generators/server/templates/src/main/resources/static/microservices_index.html.ejs +1 -1
  293. package/generators/server/templates/src/test/java/package/management/SecurityMetersServiceTests.java.ejs +113 -0
  294. package/generators/server/templates/src/test/java/package/security/jwt/JWTFilterTest.java.ejs +6 -1
  295. package/generators/server/templates/src/test/java/package/security/jwt/TokenProviderSecurityMetersTests.java.ejs +198 -0
  296. package/generators/server/templates/src/test/java/package/security/jwt/TokenProviderTest.java.ejs +13 -3
  297. package/generators/server/templates/src/test/java/package/security/oauth2/AuthorizationHeaderUtilTest.java.ejs +16 -2
  298. package/generators/server/templates/src/test/java/package/security/oauth2/CustomClaimConverterIT.java.ejs +63 -0
  299. package/generators/spring-controller/index.js +9 -7
  300. package/generators/spring-service/index.js +10 -7
  301. package/generators/upgrade/index.js +4 -5
  302. package/generators/utils.js +2 -2
  303. package/generators/workspaces/index.js +16 -7
  304. package/jdl/jhipster/default-application-options.js +9 -7
  305. package/package.json +23 -23
  306. package/utils/entity.js +21 -4
  307. package/utils/field.js +12 -2
  308. package/utils/multi-step-transform/index.js +8 -8
  309. package/generators/client/templates/react/.npmrc.ejs +0 -1
  310. package/generators/client/templates/vue/webpack/dev.env.js.ejs +0 -17
  311. package/generators/client/templates/vue/webpack/env.js.ejs +0 -67
  312. package/generators/client/templates/vue/webpack/loader.conf.js.ejs +0 -20
  313. package/generators/client/templates/vue/webpack/prod.env.js.ejs +0 -15
@@ -34,6 +34,7 @@ import org.springframework.web.client.RestTemplate;
34
34
  import org.springframework.web.context.request.RequestContextHolder;
35
35
  import org.springframework.web.context.request.ServletRequestAttributes;
36
36
 
37
+ import java.util.Arrays;
37
38
  import java.util.Collections;
38
39
  import java.util.HashMap;
39
40
  import java.util.List;
@@ -62,7 +63,7 @@ public class CustomClaimConverter implements Converter<Map<String, Object>, Map<
62
63
 
63
64
  public Map<String, Object> convert(Map<String, Object> claims) {
64
65
  Map<String, Object> convertedClaims = this.delegate.convert(claims);
65
- if (RequestContextHolder.getRequestAttributes() != null) {
66
+ if (RequestContextHolder.getRequestAttributes() != null && ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()) != null) {
66
67
  // Retrieve and set the token
67
68
  String token = bearerTokenResolver.resolve(((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest());
68
69
  HttpHeaders headers = new HttpHeaders();
@@ -83,20 +84,31 @@ public class CustomClaimConverter implements Converter<Map<String, Object>, Map<
83
84
  if (user.has("family_name")) {
84
85
  convertedClaims.put("family_name", user.get("family_name").asText());
85
86
  }
87
+ if (user.has("email")) {
88
+ convertedClaims.put("email", user.get("email").asText());
89
+ }
90
+ // Allow full name in a name claim - happens with Auth0
91
+ if (user.has("name")) {
92
+ String[] name = user.get("name").asText().split("\\s+");
93
+ if (name.length > 0) {
94
+ convertedClaims.put("given_name", name[0]);
95
+ convertedClaims.put("family_name",
96
+ String.join(" ", Arrays.copyOfRange(name, 1, name.length)));
97
+ }
98
+ }
86
99
  if (user.has("groups")) {
87
100
  List<String> groups = StreamSupport.stream(user.get("groups").spliterator(), false)
88
101
  .map(JsonNode::asText)
89
102
  .collect(Collectors.toList());
90
103
  convertedClaims.put("groups", groups);
91
104
  }
92
- }
93
-
94
- if (user.has(SecurityUtils.CLAIMS_NAMESPACE + "roles")) {
95
- List<String> roles = StreamSupport
96
- .stream(user.get(SecurityUtils.CLAIMS_NAMESPACE + "roles").spliterator(), false)
97
- .map(JsonNode::asText)
98
- .collect(Collectors.toList());
99
- convertedClaims.put("roles", roles);
105
+ if (user.has(SecurityUtils.CLAIMS_NAMESPACE + "roles")) {
106
+ List<String> roles = StreamSupport
107
+ .stream(user.get(SecurityUtils.CLAIMS_NAMESPACE + "roles").spliterator(), false)
108
+ .map(JsonNode::asText)
109
+ .collect(Collectors.toList());
110
+ convertedClaims.put("roles", roles);
111
+ }
100
112
  }
101
113
  }
102
114
  return convertedClaims;
@@ -1017,15 +1017,20 @@ public class UserService {
1017
1017
  private static <%= databaseTypeNo ? asDto('AdminUser') : asEntity('User') %> getUser(Map<String, Object> details) {
1018
1018
  <%= databaseTypeNo ? asDto('AdminUser') : asEntity('User') %> user = new <%= databaseTypeNo ? asDto('AdminUser') : asEntity('User') %>();
1019
1019
  Boolean activated = Boolean.TRUE;
1020
+ String sub = String.valueOf(details.get("sub"));
1021
+ String username = null;
1022
+ if (details.get("preferred_username") != null) {
1023
+ username = ((String) details.get("preferred_username")).toLowerCase();
1024
+ }
1020
1025
  // handle resource server JWT, where sub claim is email and uid is ID
1021
1026
  if (details.get("uid") != null) {
1022
1027
  user.setId((String) details.get("uid"));
1023
- user.setLogin((String) details.get("sub"));
1028
+ user.setLogin(sub);
1024
1029
  } else {
1025
- user.setId((String) details.get("sub"));
1030
+ user.setId(sub);
1026
1031
  }
1027
- if (details.get("preferred_username") != null) {
1028
- user.setLogin(((String) details.get("preferred_username")).toLowerCase());
1032
+ if (username != null) {
1033
+ user.setLogin(username);
1029
1034
  } else if (user.getLogin() == null) {
1030
1035
  user.setLogin(user.getId());
1031
1036
  }
@@ -1042,8 +1047,11 @@ public class UserService {
1042
1047
  }
1043
1048
  if (details.get("email") != null) {
1044
1049
  user.setEmail(((String) details.get("email")).toLowerCase());
1050
+ } else if (sub.contains("|") && (username != null && username.contains("@"))) {
1051
+ // special handling for Auth0
1052
+ user.setEmail(username);
1045
1053
  } else {
1046
- user.setEmail((String) details.get("sub"));
1054
+ user.setEmail(sub);
1047
1055
  }
1048
1056
  if (details.get("langKey") != null) {
1049
1057
  user.setLangKey((String) details.get("langKey"));
@@ -357,7 +357,7 @@ jhipster:
357
357
  # CORS is only enabled by default with the "dev" profile
358
358
  cors:
359
359
  # Allow Ionic for JHipster by default (* no longer allowed in Spring Boot 2.4+)
360
- allowed-origins: "http://localhost:8100,https://localhost:8100,http://localhost:9000,https://localhost:9000<%_ if (!skipClient) { _%>,http://localhost:<%= devServerPort %>,https://localhost:<%= devServerPort %><%_ } _%>"
360
+ allowed-origins: "http://localhost:8100,https://localhost:8100,http://localhost:9000,https://localhost:9000<%_ if (!skipClient) { _%>,http://localhost:<%= devServerPort %>,https://localhost:<%= devServerPort %><%_ if (applicationTypeGateway && microfrontend) { for ({applicationIndex, devServerPort: microserviceDevServerPort = devServerPort + applicationIndex} of Object.values(jhipsterConfig.applications || {})) { _%>,http://localhost:<%= microserviceDevServerPort %>,https://localhost:<%= microserviceDevServerPort %><%_ } } _%><%_ } _%>"
361
361
  allowed-methods: "*"
362
362
  allowed-headers: "*"
363
363
  <%_ if (authenticationTypeSession) { _%>
@@ -251,7 +251,7 @@ server:
251
251
  shutdown: graceful # see https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-graceful-shutdown
252
252
  compression:
253
253
  enabled: true
254
- mime-types: text/html,text/xml,text/plain,text/css, application/javascript, application/json
254
+ mime-types: text/html,text/xml,text/plain,text/css,application/javascript,application/json,image/svg+xml
255
255
  min-response-size: 1024
256
256
 
257
257
  # ===================================================================
@@ -92,17 +92,17 @@ management:
92
92
  roles: "ROLE_ADMIN"
93
93
  probes:
94
94
  enabled: true
95
+ group:
96
+ liveness:
97
+ include: livenessState
98
+ readiness:
99
+ include: readinessState<% if (databaseTypeSql) { %>,db<% } %>
95
100
  jhimetrics:
96
101
  enabled: true
97
102
  info:
98
103
  git:
99
104
  mode: full
100
105
  health:
101
- group:
102
- liveness:
103
- include: livenessState
104
- readiness:
105
- include: readinessState<% if (databaseTypeSql) { %>,db<% } %>
106
106
  mail:
107
107
  enabled: false # When using the MailService, configure an SMTP server and set this to true
108
108
  metrics:
@@ -320,8 +320,8 @@ jhipster:
320
320
  api-docs:
321
321
  default-include-pattern: ${server.servlet.context-path:}/api/.*
322
322
  management-include-pattern: ${server.servlet.context-path:}/management/.*
323
- title: <%= baseName %> API
324
- description: <%= baseName %> API documentation
323
+ title: <%= humanizedBaseName %> API
324
+ description: <%= humanizedBaseName %> API documentation
325
325
  version: 0.0.1
326
326
  terms-of-service-url:
327
327
  contact-name:
@@ -78,7 +78,7 @@
78
78
 
79
79
  <ul>
80
80
  <%_ if (microfrontend) { %>
81
- <li>Microfrontends packages don't provide a stand-alone front-end. Packaged microfrontend should be accessed through a JHipster gateway.</li>
81
+ <li>JHipster's microfrontends implementation doesn't provide a stand-alone UI. Packaged microfrontends should be accessed through a JHipster gateway.</li>
82
82
  <li>Stand-alone development server can be started by `npm start`.</li>
83
83
  <%_ } else { %>
84
84
  <li>It does not have a front-end. The front-end should be generated on a JHipster gateway.</li>
@@ -0,0 +1,113 @@
1
+ <%#
2
+ Copyright 2013-2021 the original author or authors from the JHipster project.
3
+
4
+ This file is part of the JHipster project, see https://www.jhipster.tech/
5
+ for more information.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ https://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
18
+ -%>
19
+ package <%= packageName %>.management;
20
+
21
+ import io.micrometer.core.instrument.Counter;
22
+ import io.micrometer.core.instrument.MeterRegistry;
23
+ import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
24
+ import org.junit.jupiter.api.BeforeEach;
25
+ import org.junit.jupiter.api.Test;
26
+
27
+ import java.util.Collection;
28
+
29
+ import static org.assertj.core.api.Assertions.assertThat;
30
+
31
+ class SecurityMetersServiceTests {
32
+ private static final String INVALID_TOKENS_METER_EXPECTED_NAME = "security.authentication.invalid-tokens";
33
+
34
+ private MeterRegistry meterRegistry;
35
+
36
+ private SecurityMetersService securityMetersService;
37
+
38
+ @BeforeEach
39
+ public void setup() {
40
+ meterRegistry = new SimpleMeterRegistry();
41
+
42
+ securityMetersService = new SecurityMetersService(meterRegistry);
43
+ }
44
+
45
+ @Test
46
+ public void testInvalidTokensCountersByCauseAreCreated() {
47
+ meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).counter();
48
+
49
+ meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
50
+ .tag("cause", "expired")
51
+ .counter();
52
+
53
+ meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
54
+ .tag("cause", "unsupported")
55
+ .counter();
56
+
57
+ meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
58
+ .tag("cause", "invalid-signature")
59
+ .counter();
60
+
61
+ meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
62
+ .tag("cause", "malformed")
63
+ .counter();
64
+
65
+ Collection<Counter> counters = meterRegistry.find(INVALID_TOKENS_METER_EXPECTED_NAME).counters();
66
+
67
+ assertThat(counters.size()).isEqualTo(4);
68
+ }
69
+
70
+ @Test
71
+ public void testCountMethodsShouldBeBoundToCorrectCounters() {
72
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
73
+ .tag("cause", "expired")
74
+ .counter().count()).isEqualTo(0);
75
+
76
+ securityMetersService.trackTokenExpired();
77
+
78
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
79
+ .tag("cause", "expired")
80
+ .counter().count()).isEqualTo(1);
81
+
82
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
83
+ .tag("cause", "unsupported")
84
+ .counter().count()).isEqualTo(0);
85
+
86
+ securityMetersService.trackTokenUnsupported();
87
+
88
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
89
+ .tag("cause", "unsupported")
90
+ .counter().count()).isEqualTo(1);
91
+
92
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
93
+ .tag("cause", "invalid-signature")
94
+ .counter().count()).isEqualTo(0);
95
+
96
+ securityMetersService.trackTokenInvalidSignature();
97
+
98
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
99
+ .tag("cause", "invalid-signature")
100
+ .counter().count()).isEqualTo(1);
101
+
102
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
103
+ .tag("cause", "malformed")
104
+ .counter().count()).isEqualTo(0);
105
+
106
+ securityMetersService.trackTokenMalformed();
107
+
108
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
109
+ .tag("cause", "malformed")
110
+ .counter().count()).isEqualTo(1);
111
+ }
112
+
113
+ }
@@ -18,8 +18,10 @@
18
18
  -%>
19
19
  package <%= packageName %>.security.jwt;
20
20
 
21
+ import <%= packageName %>.management.SecurityMetersService;
21
22
  import <%= packageName %>.security.AuthoritiesConstants;
22
23
  import tech.jhipster.config.JHipsterProperties;
24
+ import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
23
25
  import io.jsonwebtoken.io.Decoders;
24
26
  import io.jsonwebtoken.security.Keys;
25
27
 
@@ -63,7 +65,10 @@ class JWTFilterTest {
63
65
  JHipsterProperties jHipsterProperties = new JHipsterProperties();
64
66
  String base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8";
65
67
  jHipsterProperties.getSecurity().getAuthentication().getJwt().setBase64Secret(base64Secret);
66
- tokenProvider = new TokenProvider(jHipsterProperties);
68
+
69
+ SecurityMetersService securityMetersService = new SecurityMetersService(new SimpleMeterRegistry());
70
+
71
+ tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
67
72
  ReflectionTestUtils.setField(tokenProvider, "key", Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret)));
68
73
 
69
74
  ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", 60000);
@@ -0,0 +1,198 @@
1
+ <%#
2
+ Copyright 2013-2021 the original author or authors from the JHipster project.
3
+
4
+ This file is part of the JHipster project, see https://www.jhipster.tech/
5
+ for more information.
6
+
7
+ Licensed under the Apache License, Version 2.0 (the "License");
8
+ you may not use this file except in compliance with the License.
9
+ You may obtain a copy of the License at
10
+
11
+ https://www.apache.org/licenses/LICENSE-2.0
12
+
13
+ Unless required by applicable law or agreed to in writing, software
14
+ distributed under the License is distributed on an "AS IS" BASIS,
15
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ See the License for the specific language governing permissions and
17
+ limitations under the License.
18
+ -%>
19
+ package <%= packageName %>.security.jwt;
20
+
21
+ import <%= packageName %>.security.AuthoritiesConstants;
22
+ import <%= packageName %>.management.SecurityMetersService;
23
+
24
+ import io.jsonwebtoken.Jwts;
25
+ import io.jsonwebtoken.SignatureAlgorithm;
26
+ import io.jsonwebtoken.io.Decoders;
27
+ import io.jsonwebtoken.security.Keys;
28
+
29
+ import io.micrometer.core.instrument.Counter;
30
+ import io.micrometer.core.instrument.MeterRegistry;
31
+ import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
32
+
33
+ import org.junit.jupiter.api.BeforeEach;
34
+ import org.junit.jupiter.api.Test;
35
+
36
+ import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
37
+ import org.springframework.security.core.Authentication;
38
+ import org.springframework.security.core.GrantedAuthority;
39
+ import org.springframework.security.core.authority.SimpleGrantedAuthority;
40
+ import org.springframework.test.util.ReflectionTestUtils;
41
+ import tech.jhipster.config.JHipsterProperties;
42
+
43
+ import java.security.Key;
44
+ import java.util.ArrayList;
45
+ import java.util.Collection;
46
+ import java.util.Date;
47
+
48
+ import static org.assertj.core.api.Assertions.assertThat;
49
+
50
+ class TokenProviderSecurityMetersTests {
51
+
52
+ private static final long ONE_MINUTE = 60000;
53
+ private static final String INVALID_TOKENS_METER_EXPECTED_NAME = "security.authentication.invalid-tokens";
54
+
55
+ private MeterRegistry meterRegistry;
56
+
57
+ private TokenProvider tokenProvider;
58
+
59
+ @BeforeEach
60
+ public void setup() {
61
+ JHipsterProperties jHipsterProperties = new JHipsterProperties();
62
+ String base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8";
63
+ jHipsterProperties.getSecurity().getAuthentication().getJwt().setBase64Secret(base64Secret);
64
+
65
+ meterRegistry = new SimpleMeterRegistry();
66
+
67
+ SecurityMetersService securityMetersService = new SecurityMetersService(meterRegistry);
68
+
69
+ tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
70
+ Key key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret));
71
+
72
+ ReflectionTestUtils.setField(tokenProvider, "key", key);
73
+ ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", ONE_MINUTE);
74
+ }
75
+
76
+ @Test
77
+ public void testValidTokenShouldNotCountAnything() {
78
+ Collection<Counter> counters = meterRegistry.find(INVALID_TOKENS_METER_EXPECTED_NAME).counters();
79
+
80
+ assertThat(aggregate(counters)).isEqualTo(0);
81
+
82
+ String validToken = createValidToken();
83
+
84
+ tokenProvider.validateToken(validToken);
85
+
86
+ assertThat(aggregate(counters)).isEqualTo(0);
87
+ }
88
+
89
+ @Test
90
+ public void testTokenExpiredCount() {
91
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
92
+ .tag("cause", "expired")
93
+ .counter().count()).isEqualTo(0);
94
+
95
+ String expiredToken = createExpiredToken();
96
+
97
+ tokenProvider.validateToken(expiredToken);
98
+
99
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
100
+ .tag("cause", "expired")
101
+ .counter().count()).isEqualTo(1);
102
+ }
103
+
104
+ @Test
105
+ void testTokenUnsupportedCount() {
106
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
107
+ .tag("cause", "unsupported")
108
+ .counter().count()).isEqualTo(0);
109
+
110
+ String unsupportedToken = createUnsupportedToken();
111
+
112
+ tokenProvider.validateToken(unsupportedToken);
113
+
114
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
115
+ .tag("cause", "unsupported")
116
+ .counter().count()).isEqualTo(1);
117
+ }
118
+
119
+ @Test
120
+ public void testTokenSignatureInvalidCount() {
121
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
122
+ .tag("cause", "invalid-signature")
123
+ .counter().count()).isEqualTo(0);
124
+
125
+ String tokenWithDifferentSignature = createTokenWithDifferentSignature();
126
+
127
+ tokenProvider.validateToken(tokenWithDifferentSignature);
128
+
129
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
130
+ .tag("cause", "invalid-signature")
131
+ .counter().count()).isEqualTo(1);
132
+ }
133
+
134
+ @Test
135
+ public void testTokenMalformedCount() {
136
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
137
+ .tag("cause", "malformed")
138
+ .counter().count()).isEqualTo(0);
139
+
140
+ String malformedToken = createMalformedToken();
141
+
142
+ tokenProvider.validateToken(malformedToken);
143
+
144
+ assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME)
145
+ .tag("cause", "malformed")
146
+ .counter().count()).isEqualTo(1);
147
+ }
148
+
149
+ private String createValidToken() {
150
+ Authentication authentication = createAuthentication();
151
+
152
+ return tokenProvider.createToken(authentication, false);
153
+ }
154
+
155
+ private String createExpiredToken() {
156
+ ReflectionTestUtils.setField(tokenProvider, "tokenValidityInMilliseconds", -ONE_MINUTE);
157
+
158
+ Authentication authentication = createAuthentication();
159
+
160
+ return tokenProvider.createToken(authentication, false);
161
+ }
162
+
163
+ private Authentication createAuthentication() {
164
+ Collection<GrantedAuthority> authorities = new ArrayList<>();
165
+ authorities.add(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
166
+ return new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities);
167
+ }
168
+
169
+ private String createUnsupportedToken() {
170
+ Key key = (Key) ReflectionTestUtils.getField(tokenProvider, "key");
171
+
172
+ return Jwts.builder().setPayload("payload").signWith(key, SignatureAlgorithm.HS256).compact();
173
+ }
174
+
175
+ private String createMalformedToken() {
176
+ String validToken = createValidToken();
177
+
178
+ return "X" + validToken;
179
+ }
180
+
181
+ private String createTokenWithDifferentSignature() {
182
+ Key otherKey = Keys.hmacShaKeyFor(
183
+ Decoders.BASE64.decode("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8")
184
+ );
185
+
186
+ return Jwts
187
+ .builder()
188
+ .setSubject("anonymous")
189
+ .signWith(otherKey, SignatureAlgorithm.HS512)
190
+ .setExpiration(new Date(new Date().getTime() + ONE_MINUTE))
191
+ .compact();
192
+ }
193
+
194
+ private double aggregate(Collection<Counter> counters) {
195
+ return counters.stream().mapToDouble(Counter::count).sum();
196
+ }
197
+
198
+ }
@@ -19,6 +19,7 @@
19
19
  package <%= packageName %>.security.jwt;
20
20
 
21
21
  import <%= packageName %>.security.AuthoritiesConstants;
22
+ import <%= packageName %>.management.SecurityMetersService;
22
23
 
23
24
  import java.security.Key;
24
25
  import java.util.*;
@@ -31,6 +32,8 @@ import org.springframework.security.core.GrantedAuthority;
31
32
  import org.springframework.security.core.authority.SimpleGrantedAuthority;
32
33
  import org.springframework.test.util.ReflectionTestUtils;
33
34
 
35
+ import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
36
+
34
37
  import tech.jhipster.config.JHipsterProperties;
35
38
  import io.jsonwebtoken.Jwts;
36
39
  import io.jsonwebtoken.SignatureAlgorithm;
@@ -53,7 +56,10 @@ class TokenProviderTest {
53
56
  JHipsterProperties jHipsterProperties = new JHipsterProperties();
54
57
  String base64Secret = "fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8";
55
58
  jHipsterProperties.getSecurity().getAuthentication().getJwt().setBase64Secret(base64Secret);
56
- tokenProvider = new TokenProvider(jHipsterProperties);
59
+
60
+ SecurityMetersService securityMetersService = new SecurityMetersService(new SimpleMeterRegistry());
61
+
62
+ tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
57
63
  key = Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret));
58
64
 
59
65
  ReflectionTestUtils.setField(tokenProvider, "key", key);
@@ -111,7 +117,9 @@ class TokenProviderTest {
111
117
  JHipsterProperties jHipsterProperties = new JHipsterProperties();
112
118
  jHipsterProperties.getSecurity().getAuthentication().getJwt().setSecret(secret);
113
119
 
114
- TokenProvider tokenProvider = new TokenProvider(jHipsterProperties);
120
+ SecurityMetersService securityMetersService = new SecurityMetersService(new SimpleMeterRegistry());
121
+
122
+ TokenProvider tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
115
123
 
116
124
  Key key = (Key) ReflectionTestUtils.getField(tokenProvider, "key");
117
125
  assertThat(key).isNotNull().isEqualTo(Keys.hmacShaKeyFor(secret.getBytes(StandardCharsets.UTF_8)));
@@ -123,7 +131,9 @@ class TokenProviderTest {
123
131
  JHipsterProperties jHipsterProperties = new JHipsterProperties();
124
132
  jHipsterProperties.getSecurity().getAuthentication().getJwt().setBase64Secret(base64Secret);
125
133
 
126
- TokenProvider tokenProvider = new TokenProvider(jHipsterProperties);
134
+ SecurityMetersService securityMetersService = new SecurityMetersService(new SimpleMeterRegistry());
135
+
136
+ TokenProvider tokenProvider = new TokenProvider(jHipsterProperties, securityMetersService);
127
137
 
128
138
  Key key = (Key) ReflectionTestUtils.getField(tokenProvider, "key");
129
139
  assertThat(key).isNotNull().isEqualTo(Keys.hmacShaKeyFor(Decoders.BASE64.decode(base64Secret)));
@@ -50,6 +50,7 @@ import java.util.List;
50
50
  import java.util.Map;
51
51
  import java.util.Optional;
52
52
 
53
+ import static org.junit.jupiter.api.Assertions.fail;
53
54
  import static org.mockito.ArgumentMatchers.*;
54
55
  import static org.mockito.Mockito.*;
55
56
 
@@ -179,6 +180,20 @@ class AuthorizationHeaderUtilTest {
179
180
  }
180
181
 
181
182
  private OAuth2AuthorizedClient getTestOAuth2AuthorizedClient(boolean accessTokenExpired) {
183
+ Instant issuedAt = Instant.now();
184
+ Instant expiresAt;
185
+ if (accessTokenExpired) {
186
+ expiresAt = issuedAt.plus(Duration.ofNanos(1));
187
+ try {
188
+ Thread.sleep(1);
189
+ } catch (Exception e) {
190
+ fail("Error in Thread.sleep(1) : " + e.getMessage());
191
+ }
192
+ } else {
193
+ expiresAt = issuedAt.plus(Duration.ofMinutes(3));
194
+ }
195
+ OAuth2AccessToken token = new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "tokenVal", issuedAt, expiresAt);
196
+
182
197
  return new OAuth2AuthorizedClient(
183
198
  ClientRegistration.withRegistrationId(VALID_REGISTRATION_ID)
184
199
  .authorizationGrantType(AuthorizationGrantType.AUTHORIZATION_CODE)
@@ -189,8 +204,7 @@ class AuthorizationHeaderUtilTest {
189
204
  .tokenUri("https://localhost:8080/auth/realms/master/protocol/openid-connect/token")
190
205
  .build(),
191
206
  "sub",
192
- new OAuth2AccessToken(OAuth2AccessToken.TokenType.BEARER, "tokenVal", Instant.now(),
193
- accessTokenExpired ? Instant.now() : Instant.now().plus(Duration.ofMinutes(3))),
207
+ token,
194
208
  new OAuth2RefreshToken("refreshVal", Instant.now()));
195
209
  }
196
210
 
@@ -50,6 +50,9 @@ class CustomClaimConverterIT {
50
50
  private static final String USERNAME = "admin";
51
51
  private static final String NAME = "John";
52
52
  private static final String FAMILY_NAME = "Doe";
53
+ private static final String FULL_NAME = NAME + " " + FAMILY_NAME;
54
+ private static final String NAME_SUFFIX = "Sr.";
55
+ private static final String EMAIL = "john.doe@gmail.com";
53
56
 
54
57
  private final ObjectMapper mapper = new ObjectMapper();
55
58
 
@@ -161,4 +164,64 @@ class CustomClaimConverterIT {
161
164
  .doesNotContainKeys("given_name", "family_name");
162
165
  }).doesNotThrowAnyException();
163
166
  }
167
+
168
+ @Test
169
+ void testConvert_withName() {
170
+ // GIVEN
171
+ Map<String, Object> claims = new HashMap<>();
172
+ claims.put("sub", "123");
173
+ // AND
174
+ ObjectNode user = mapper.createObjectNode();
175
+ user.put("preferred_username", USERNAME);
176
+ user.put("name", FULL_NAME);
177
+ mockHttpGetUserInfo(user);
178
+
179
+ assertThatCode(() -> {
180
+ Map<String, Object> convertedClaims = customClaimConverter.convert(claims);
181
+ assertThat(convertedClaims)
182
+ .containsEntry("preferred_username", USERNAME)
183
+ .containsEntry("given_name", NAME)
184
+ .containsEntry("family_name", FAMILY_NAME);
185
+ }).doesNotThrowAnyException();
186
+ }
187
+
188
+ @Test
189
+ void testConvert_withLastNameMultipleWords() {
190
+ // GIVEN
191
+ Map<String, Object> claims = new HashMap<>();
192
+ claims.put("sub", "123");
193
+ // AND
194
+ ObjectNode user = mapper.createObjectNode();
195
+ user.put("preferred_username", USERNAME);
196
+ user.put("name", FULL_NAME + " " + NAME_SUFFIX);
197
+ mockHttpGetUserInfo(user);
198
+
199
+ assertThatCode(() -> {
200
+ Map<String, Object> convertedClaims = customClaimConverter.convert(claims);
201
+ System.out.println(convertedClaims);
202
+ assertThat(convertedClaims)
203
+ .containsEntry("preferred_username", USERNAME)
204
+ .containsEntry("given_name", NAME)
205
+ .containsEntry("family_name", FAMILY_NAME + " " + NAME_SUFFIX);
206
+ }).doesNotThrowAnyException();
207
+ }
208
+
209
+ @Test
210
+ void testConvert_withEmail() {
211
+ // GIVEN
212
+ Map<String, Object> claims = new HashMap<>();
213
+ claims.put("sub", "123");
214
+ // AND
215
+ ObjectNode user = mapper.createObjectNode();
216
+ user.put("preferred_username", USERNAME);
217
+ user.put("email", EMAIL);
218
+ mockHttpGetUserInfo(user);
219
+
220
+ assertThatCode(() -> {
221
+ Map<String, Object> convertedClaims = customClaimConverter.convert(claims);
222
+ assertThat(convertedClaims)
223
+ .containsEntry("preferred_username", USERNAME)
224
+ .containsEntry("email", EMAIL);
225
+ }).doesNotThrowAnyException();
226
+ }
164
227
  }