generator-jhipster 8.0.0 → 8.1.0

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 (258) hide show
  1. package/README.md +61 -57
  2. package/dist/cli/environment-builder.mjs +11 -4
  3. package/dist/cli/program.mjs +1 -1
  4. package/dist/generators/angular/cleanup.mjs +7 -0
  5. package/dist/generators/angular/files-angular.mjs +3 -4
  6. package/dist/generators/angular/generator.mjs +2 -15
  7. package/dist/generators/angular/needle-api/needle-client-angular.mjs +2 -8
  8. package/dist/generators/angular/resources/package.json +23 -23
  9. package/dist/generators/angular/support/translate-angular.mjs +2 -2
  10. package/dist/generators/angular/templates/README.md.jhi.client.angular.ejs +1 -1
  11. package/dist/generators/angular/templates/angular.json.ejs +3 -7
  12. package/dist/generators/angular/templates/src/main/webapp/app/account/activate/activate.component.html.ejs +6 -4
  13. package/dist/generators/angular/templates/src/main/webapp/app/account/password/password-strength-bar/password-strength-bar.component.ts.ejs +1 -1
  14. package/dist/generators/angular/templates/src/main/webapp/app/account/password/password.component.html.ejs +39 -33
  15. package/dist/generators/angular/templates/src/main/webapp/app/account/password-reset/finish/password-reset-finish.component.html.ejs +44 -36
  16. package/dist/generators/angular/templates/src/main/webapp/app/account/password-reset/init/password-reset-init.component.html.ejs +24 -23
  17. package/dist/generators/angular/templates/src/main/webapp/app/account/register/register.component.html.ejs +74 -62
  18. package/dist/generators/angular/templates/src/main/webapp/app/account/sessions/sessions.component.html.ejs +12 -4
  19. package/dist/generators/angular/templates/src/main/webapp/app/account/settings/settings.component.html.ejs +54 -48
  20. package/dist/generators/angular/templates/src/main/webapp/app/admin/admin.routes.ts.ejs +74 -0
  21. package/dist/generators/angular/templates/src/main/webapp/app/admin/configuration/configuration.component.html.ejs +15 -5
  22. package/dist/generators/angular/templates/src/main/webapp/app/admin/docs/docs.component.ts.ejs +1 -1
  23. package/dist/generators/angular/templates/src/main/webapp/app/admin/gateway/gateway.component.html.ejs +20 -7
  24. package/dist/generators/angular/templates/src/main/webapp/app/admin/health/health.component.html.ejs +10 -7
  25. package/dist/generators/angular/templates/src/main/webapp/app/admin/health/modal/health-modal.component.html.ejs +9 -3
  26. package/dist/generators/angular/templates/src/main/webapp/app/admin/logs/logs.component.html.ejs +12 -4
  27. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/jvm-memory/jvm-memory.component.html.ejs +13 -7
  28. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-cache/metrics-cache.component.html.ejs +6 -2
  29. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-datasource/metrics-datasource.component.html.ejs +3 -1
  30. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-endpoints-requests/metrics-endpoints-requests.component.html.ejs +13 -9
  31. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-garbagecollector/metrics-garbagecollector.component.html.ejs +13 -5
  32. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-modal-threads/metrics-modal-threads.component.html.ejs +21 -7
  33. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-request/metrics-request.component.html.ejs +6 -2
  34. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/blocks/metrics-system/metrics-system.component.html.ejs +3 -1
  35. package/dist/generators/angular/templates/src/main/webapp/app/admin/metrics/metrics.component.html.ejs +16 -7
  36. package/dist/generators/angular/templates/src/main/webapp/app/admin/tracker/tracker.component.html.ejs +3 -1
  37. package/dist/generators/angular/templates/src/main/webapp/app/admin/user-management/delete/user-management-delete-dialog.component.html.ejs +3 -1
  38. package/dist/generators/angular/templates/src/main/webapp/app/admin/user-management/detail/user-management-detail.component.html.ejs +11 -4
  39. package/dist/generators/angular/templates/src/main/webapp/app/admin/user-management/list/user-management.component.html.ejs +20 -11
  40. package/dist/generators/angular/templates/src/main/webapp/app/admin/user-management/update/user-management-update.component.html.ejs +48 -34
  41. package/dist/generators/angular/templates/src/main/webapp/app/app.component.ts.ejs +73 -0
  42. package/dist/generators/angular/templates/src/main/webapp/app/app.config.ts.ejs +67 -0
  43. package/dist/generators/angular/templates/src/main/webapp/app/app.routes.ts.ejs +85 -0
  44. package/dist/generators/angular/templates/src/main/webapp/app/core/microfrontend/index.ts.ejs +5 -4
  45. package/dist/generators/angular/templates/src/main/webapp/app/core/util/alert.service.spec.ts.ejs +1 -1
  46. package/dist/generators/angular/templates/src/main/webapp/app/core/util/data-util.service.ts.ejs +2 -2
  47. package/dist/generators/angular/templates/src/main/webapp/app/core/util/event-manager.service.spec.ts.ejs +12 -12
  48. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_.model.ts.ejs +4 -4
  49. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/delete/_entityFile_-delete-dialog.component.html.ejs +3 -1
  50. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/detail/_entityFile_-detail.component.html.ejs +26 -14
  51. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/list/_entityFile_.component.html.ejs +38 -25
  52. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/list/_entityFile_.component.ts.ejs +1 -1
  53. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/update/_entityFile_-form.service.spec.ts.ejs +2 -2
  54. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/update/_entityFile_-form.service.ts.ejs +5 -12
  55. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/update/_entityFile_-update.component.html.ejs +55 -21
  56. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/update/_entityFile_-update.component.spec.ts.ejs +2 -2
  57. package/dist/generators/angular/templates/src/main/webapp/app/entities/_entityFolder_/update/_entityFile_-update.component.ts.ejs +10 -10
  58. package/dist/generators/angular/templates/src/main/webapp/app/entities/entity.routes.ts.ejs +25 -0
  59. package/dist/generators/angular/templates/src/main/webapp/app/home/home.component.html.ejs +21 -17
  60. package/dist/generators/angular/templates/src/main/webapp/app/home/home.component.ts.ejs +1 -1
  61. package/dist/generators/angular/templates/src/main/webapp/app/layouts/error/error.component.html.ejs +3 -3
  62. package/dist/generators/angular/templates/src/main/webapp/app/layouts/main/main.component.spec.ts.ejs +5 -2
  63. package/dist/generators/angular/templates/src/main/webapp/app/layouts/main/main.component.ts.ejs +5 -1
  64. package/dist/generators/angular/templates/src/main/webapp/app/layouts/navbar/navbar.component.html.ejs +97 -78
  65. package/dist/generators/angular/templates/src/main/webapp/app/layouts/navbar/navbar.component.ts.ejs +1 -1
  66. package/dist/generators/angular/templates/src/main/webapp/app/layouts/profiles/page-ribbon.component.scss.ejs +1 -1
  67. package/dist/generators/angular/templates/src/main/webapp/app/layouts/profiles/page-ribbon.component.ts.ejs +6 -4
  68. package/dist/generators/angular/templates/src/main/webapp/app/login/login.component.html.ejs +3 -3
  69. package/dist/generators/angular/templates/src/main/webapp/app/shared/alert/alert-error.component.html.ejs +6 -2
  70. package/dist/generators/angular/templates/src/main/webapp/app/shared/alert/alert.component.html.ejs +6 -2
  71. package/dist/generators/angular/templates/src/main/webapp/app/shared/filter/filter.component.html.ejs +11 -7
  72. package/dist/generators/angular/templates/src/main/webapp/app/shared/filter/filter.model.spec.ts.ejs +1 -1
  73. package/dist/generators/angular/templates/src/main/webapp/app/shared/sort/sort-by.directive.spec.ts.ejs +3 -3
  74. package/dist/generators/angular/templates/src/main/webapp/bootstrap.ts.ejs +5 -5
  75. package/dist/generators/angular/templates/src/main/webapp/content/scss/global.scss.ejs +1 -1
  76. package/dist/generators/angular/templates/webpack/webpack.microfrontend.js.ejs +2 -2
  77. package/dist/generators/app/README.md +108 -0
  78. package/dist/generators/app/USAGE +3 -0
  79. package/dist/generators/app/command.mjs +3 -3
  80. package/dist/generators/app/generator.mjs +11 -0
  81. package/dist/generators/base/command.mjs +0 -11
  82. package/dist/generators/base-application/generator.mjs +5 -6
  83. package/dist/generators/base-application/support/entities.mjs +2 -2
  84. package/dist/generators/base-application/support/index.mjs +1 -0
  85. package/dist/generators/base-application/support/prepare-entity.mjs +0 -1
  86. package/dist/generators/base-application/support/prepare-relationship.mjs +4 -0
  87. package/dist/generators/base-application/support/update-application-entities-transform.mjs +52 -0
  88. package/dist/generators/base-core/generator.mjs +17 -4
  89. package/dist/generators/base-entity-changes/generator.mjs +1 -1
  90. package/dist/generators/bootstrap/command.mjs +6 -0
  91. package/dist/generators/bootstrap/generator.mjs +27 -9
  92. package/dist/generators/bootstrap-application/generator.mjs +1 -19
  93. package/dist/generators/bootstrap-application-base/command.mjs +30 -0
  94. package/dist/generators/bootstrap-application-base/generator.mjs +27 -5
  95. package/dist/generators/bootstrap-application-base/index.mjs +1 -0
  96. package/dist/generators/bootstrap-application-base/support/export-jdl-transform.mjs +61 -0
  97. package/dist/generators/bootstrap-application-base/support/import-jdl-transform.mjs +64 -0
  98. package/dist/generators/bootstrap-application-base/support/index.mjs +2 -0
  99. package/dist/generators/client/command.mjs +2 -0
  100. package/dist/generators/client/resources/package.json +4 -4
  101. package/dist/generators/client/support/entity-definition.mjs +3 -3
  102. package/dist/generators/client/templates/README.md.jhi.client.ejs +2 -2
  103. package/dist/generators/client/templates/src/main/webapp/index.html.ejs +2 -2
  104. package/dist/generators/common/command.mjs +2 -0
  105. package/dist/generators/common/resources/package.json +3 -3
  106. package/dist/generators/common/templates/sonar-project.properties.ejs +1 -1
  107. package/dist/generators/cypress/templates/src/test/javascript/cypress/e2e/entity/_entity_.cy.ts.ejs +0 -1
  108. package/dist/generators/docker/generator.mjs +1 -1
  109. package/dist/generators/docker/templates/docker/cassandra.yml.ejs +2 -2
  110. package/dist/generators/docker/templates/docker/keycloak.yml.ejs +1 -1
  111. package/dist/generators/docker/templates/docker/realm-config/jhipster-realm.json.ejs +4 -1
  112. package/dist/generators/docker-compose/generator.mjs +4 -11
  113. package/dist/generators/docker-compose/templates/docker-compose.yml.ejs +1 -1
  114. package/dist/generators/docker-compose/templates/realm-config/jhipster-realm.json.ejs +4 -1
  115. package/dist/generators/export-jdl/generator.mjs +1 -1
  116. package/dist/generators/feign-client/cleanup.mjs +12 -0
  117. package/dist/generators/feign-client/files.mjs +35 -0
  118. package/dist/generators/feign-client/generator.mjs +65 -0
  119. package/dist/generators/feign-client/index.mjs +19 -0
  120. package/dist/generators/feign-client/templates/src/main/java/_package_/client/AuthorizationHeaderUtil.java.ejs +174 -0
  121. package/dist/generators/feign-client/templates/src/main/java/_package_/client/AuthorizedFeignClient.java.ejs +72 -0
  122. package/dist/generators/feign-client/templates/src/main/java/_package_/client/OAuth2InterceptedFeignConfiguration.java.ejs +35 -0
  123. package/dist/generators/feign-client/templates/src/main/java/_package_/client/OAuthIdpTokenResponseDTO.java.ejs +161 -0
  124. package/dist/generators/feign-client/templates/src/main/java/_package_/client/TokenRelayRequestInterceptor.java.ejs +42 -0
  125. package/dist/generators/feign-client/templates/src/main/java/_package_/client/UserFeignClientInterceptor_jwt.java.ejs +36 -0
  126. package/dist/generators/feign-client/templates/src/main/java/_package_/config/FeignConfiguration.java.ejs +45 -0
  127. package/dist/generators/feign-client/templates/src/test/java/_package_/client/AuthorizationHeaderUtilTest.java.ejs +263 -0
  128. package/dist/generators/generate-blueprint/command.mjs +1 -1
  129. package/dist/generators/generate-blueprint/resources/package.json +1 -1
  130. package/dist/generators/generate-blueprint/templates/vitest.config.ts.ejs +1 -1
  131. package/dist/generators/generator-constants.mjs +9 -5
  132. package/dist/generators/generator-list.mjs +1 -0
  133. package/dist/generators/git/generator.mjs +3 -5
  134. package/dist/generators/gradle/constants.mjs +1 -1
  135. package/dist/generators/java/command.mjs +6 -0
  136. package/dist/generators/java/entity-files.mjs +4 -0
  137. package/dist/generators/java/generator.mjs +3 -2
  138. package/dist/generators/java/templates/src/main/java/_package_/_entityPackage_/domain/_persistClass_.java.jhi.jackson_identity_info.ejs +30 -0
  139. package/dist/generators/jdl/generator.mjs +18 -23
  140. package/dist/generators/kubernetes/templates/keycloak/keycloak-configmap.yml.ejs +4 -1
  141. package/dist/generators/kubernetes/templates/keycloak/keycloak.yml.ejs +1 -1
  142. package/dist/generators/languages/generator.mjs +24 -15
  143. package/dist/generators/languages/prompts.mjs +3 -1
  144. package/dist/generators/languages/support/translate.mjs +1 -1
  145. package/dist/generators/languages/templates/entity/i18n/entity_pt-br.json.ejs +1 -1
  146. package/dist/generators/liquibase/README.md +19 -0
  147. package/dist/generators/project-name/generator.mjs +14 -19
  148. package/dist/generators/project-name/support/name-resolver.mjs +35 -6
  149. package/dist/generators/react/resources/package.json +24 -24
  150. package/dist/generators/react/templates/src/main/webapp/app/config/notification-middleware.spec.ts.ejs +4 -4
  151. package/dist/generators/react/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-detail.tsx.ejs +1 -2
  152. package/dist/generators/react/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-update.tsx.ejs +12 -13
  153. package/dist/generators/react/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_.tsx.ejs +3 -8
  154. package/dist/generators/react/templates/src/main/webapp/app/entities/_entityFolder_/_entityModel_.model.ts.ejs +1 -1
  155. package/dist/generators/react/templates/src/main/webapp/app/shared/layout/header/header.scss.ejs +1 -1
  156. package/dist/generators/react/templates/src/main/webapp/app/shared/reducers/reducer.utils.ts.ejs +1 -1
  157. package/dist/generators/react/templates/src/main/webapp/app/shared/util/date-utils.ts.ejs +1 -1
  158. package/dist/generators/server/cleanup.mjs +5 -0
  159. package/dist/generators/server/command.mjs +13 -2
  160. package/dist/generators/server/entity-files.mjs +3 -3
  161. package/dist/generators/server/files.mjs +2 -38
  162. package/dist/generators/server/generator.mjs +35 -19
  163. package/dist/generators/server/jdl/application-definition.mjs +5 -2
  164. package/dist/generators/server/options/feign-client.mjs +24 -0
  165. package/dist/generators/server/options/index.mjs +1 -0
  166. package/dist/generators/server/resources/Dockerfile +16 -16
  167. package/dist/generators/server/resources/gradle/libs.versions.toml +4 -4
  168. package/dist/generators/server/resources/pom.xml +11 -11
  169. package/dist/generators/server/support/config.mjs +1 -0
  170. package/dist/generators/server/support/prepare-entity.mjs +4 -1
  171. package/dist/generators/server/templates/build.gradle.ejs +1 -2
  172. package/dist/generators/server/templates/gradle/profile_dev.gradle.ejs +3 -21
  173. package/dist/generators/server/templates/gradle/profile_prod.gradle.ejs +5 -15
  174. package/dist/generators/server/templates/pom.xml.ejs +1 -4
  175. package/dist/generators/server/templates/src/main/java/_package_/_entityPackage_/_partials_entity_/get_all_template.ejs +7 -7
  176. package/dist/generators/server/templates/src/main/java/_package_/_entityPackage_/_partials_entity_/search_template.ejs +4 -4
  177. package/dist/generators/server/templates/src/main/java/_package_/_entityPackage_/repository/_entityClass_Repository.java.ejs +1 -1
  178. package/dist/generators/server/templates/src/main/java/_package_/_entityPackage_/service/mapper/_entityClass_Mapper.java.ejs +2 -2
  179. package/dist/generators/server/templates/src/main/java/_package_/_entityPackage_/web/rest/_entityClass_Resource.java.ejs +3 -3
  180. package/dist/generators/server/templates/src/main/java/_package_/config/SecurityConfiguration_imperative.java.ejs +20 -2
  181. package/dist/generators/server/templates/src/main/java/_package_/config/SecurityConfiguration_reactive.java.ejs +4 -1
  182. package/dist/generators/server/templates/src/main/java/_package_/security/oauth2/CustomClaimConverter.java.ejs +1 -5
  183. package/dist/generators/server/templates/src/main/java/_package_/service/MailService.java.ejs +48 -12
  184. package/dist/generators/server/templates/src/main/java/_package_/web/rest/AccountResource.java.ejs +1 -1
  185. package/dist/generators/server/templates/src/main/java/_package_/web/rest/LogoutResource_imperative.java.ejs +4 -13
  186. package/dist/generators/server/templates/src/main/java/_package_/web/rest/LogoutResource_reactive.java.ejs +5 -11
  187. package/dist/generators/server/templates/src/main/java/_package_/web/rest/PublicUserResource.java.ejs +3 -3
  188. package/dist/generators/server/templates/src/main/java/_package_/web/rest/UserResource.java.ejs +6 -6
  189. package/dist/generators/server/templates/src/main/resources/config/application.yml.ejs +8 -7
  190. package/dist/generators/server/templates/src/test/java/_package_/TechnicalStructureTest.java.ejs +1 -1
  191. package/dist/generators/server/templates/src/test/java/_package_/_entityPackage_/web/rest/_entityClass_ResourceIT.java.ejs +8 -8
  192. package/dist/generators/server/templates/src/test/java/_package_/web/rest/errors/ExceptionTranslatorTestController.java.ejs +2 -2
  193. package/dist/generators/spring-cache/internal/dependencies.mjs +1 -1
  194. package/dist/generators/spring-cache/templates/gradle/cache.gradle.ejs +1 -1
  195. package/dist/generators/spring-cache/templates/src/main/java/_package_/config/CacheFactoryConfiguration.java.ejs +1 -1
  196. package/dist/generators/spring-cloud-stream/templates/src/main/java/_package_/web/rest/KafkaResource_imperative.java.ejs +1 -1
  197. package/dist/generators/spring-cloud-stream/templates/src/main/java/_package_/web/rest/KafkaResource_reactive.java.ejs +1 -1
  198. package/dist/generators/spring-cloud-stream/templates/src/test/java/_package_/web/rest/KafkaResourceIT_reactive.java.ejs +3 -0
  199. package/dist/generators/spring-data-elasticsearch/templates/src/main/java/_package_/_entityPackage_/domain/_persistClass_.java.jhi.elastic_search.ejs +1 -1
  200. package/dist/generators/spring-data-elasticsearch/templates/src/main/java/_package_/_entityPackage_/repository/search/_entityClass_SearchRepository.java.ejs +1 -1
  201. package/dist/generators/spring-data-elasticsearch/templates/src/main/java/_package_/repository/search/UserSearchRepository.java.ejs +4 -4
  202. package/dist/generators/spring-data-neo4j/generator.mjs +43 -1
  203. package/dist/generators/spring-data-neo4j/templates/src/main/java/_package_/_entityPackage_/domain/_persistClass_.java.jhi.spring_data_neo4j.ejs +1 -1
  204. package/dist/generators/spring-data-relational/README.md +7 -0
  205. package/dist/generators/spring-data-relational/generator.mjs +2 -1
  206. package/dist/generators/spring-data-relational/internal/dependencies.mjs +29 -8
  207. package/dist/generators/spring-data-relational/support/database-data.mjs +4 -0
  208. package/dist/generators/spring-data-relational/templates/src/main/java/_package_/repository/EntityManager_reactive.java.ejs +49 -8
  209. package/dist/generators/spring-data-relational/templates/src/test/java/_package_/config/SqlTestContainersSpringContextCustomizerFactory.java.ejs +1 -1
  210. package/dist/generators/upgrade/generator.mjs +3 -3
  211. package/dist/generators/vue/resources/package.json +21 -21
  212. package/dist/generators/vue/templates/package.json.ejs +1 -0
  213. package/dist/generators/vue/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-details.vue.ejs +1 -2
  214. package/dist/generators/vue/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-update.component.spec.ts.ejs +1 -1
  215. package/dist/generators/vue/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-update.component.ts.ejs +3 -3
  216. package/dist/generators/vue/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_-update.vue.ejs +2 -15
  217. package/dist/generators/vue/templates/src/main/webapp/app/entities/_entityFolder_/_entityFile_.vue.ejs +2 -7
  218. package/dist/jdl/converters/jdl-to-json/jdl-to-json-basic-entity-converter.js +1 -0
  219. package/dist/jdl/converters/json-to-jdl-converter.js +1 -1
  220. package/dist/jdl/converters/json-to-jdl-entity-converter.js +1 -0
  221. package/dist/jdl/converters/parsed-jdl-to-jdl-object/entity-converter.js +5 -0
  222. package/dist/jdl/converters/parsed-jdl-to-jdl-object/parsed-jdl-to-jdl-object-converter.js +0 -27
  223. package/dist/jdl/exporters/jhipster-entity-exporter.js +3 -2
  224. package/dist/jdl/jhipster/default-application-options.js +1 -1
  225. package/dist/jdl/jhipster/field-types.js +1 -1
  226. package/dist/jdl/jhipster/json-entity.js +6 -0
  227. package/dist/jdl/models/jdl-entity.js +16 -1
  228. package/dist/jdl/models/jdl-field.js +13 -0
  229. package/dist/jdl/models/jdl-object.js +3 -3
  230. package/dist/jdl/models/jdl-relationship.js +23 -5
  231. package/dist/jdl/parsing/lexer/application-tokens.js +1 -1
  232. package/dist/testing/helpers.mjs +10 -3
  233. package/dist/types/cli/environment-builder.d.mts +2 -0
  234. package/dist/types/generators/angular/needle-api/needle-client-angular.d.mts +0 -1
  235. package/dist/types/generators/base/api.d.mts +12 -0
  236. package/dist/types/generators/base/support/needles.d.mts +1 -1
  237. package/dist/types/generators/base-application/generator.d.mts +2 -2
  238. package/dist/types/generators/base-application/support/index.d.mts +1 -0
  239. package/dist/types/generators/base-application/support/update-application-entities-transform.d.mts +4 -0
  240. package/dist/types/generators/base-application/types/relationship.d.mts +4 -0
  241. package/dist/types/generators/base-core/generator.d.mts +7 -1
  242. package/dist/types/generators/bootstrap-application-base/support/export-jdl-transform.d.mts +8 -0
  243. package/dist/types/generators/bootstrap-application-base/support/import-jdl-transform.d.mts +6 -0
  244. package/dist/types/generators/bootstrap-application-base/support/index.d.mts +2 -0
  245. package/dist/types/generators/client/support/entity-definition.d.mts +2 -2
  246. package/dist/types/generators/feign-client/types-export.d.ts +1 -0
  247. package/dist/types/generators/generator-constants.d.mts +52 -48
  248. package/dist/types/generators/generator-list.d.mts +1 -0
  249. package/dist/types/generators/project-name/support/name-resolver.d.mts +9 -1
  250. package/dist/types/generators/server/options/feign-client.d.mts +21 -0
  251. package/dist/types/generators/server/options/index.d.mts +1 -0
  252. package/dist/types/jdl/converters/json-to-jdl-converter.d.ts +1 -0
  253. package/dist/types/jdl/converters/parsed-jdl-to-jdl-object/option-converter.d.ts +1 -1
  254. package/dist/types/jdl/jhipster/json-entity.d.ts +2 -0
  255. package/dist/types/jdl/models/jdl-entity.d.ts +1 -0
  256. package/dist/types/jdl/models/jdl-relationship.d.ts +0 -18
  257. package/dist/types/jdl/types/types.d.mts +2 -2
  258. package/package.json +27 -27
@@ -3,14 +3,14 @@
3
3
  "dayjs": "1.11.10"
4
4
  },
5
5
  "devDependencies": {
6
- "@cypress/code-coverage": "3.12.7",
6
+ "@cypress/code-coverage": "3.12.13",
7
7
  "babel-loader": "9.1.3",
8
8
  "babel-plugin-istanbul": "6.1.1",
9
- "cypress": "13.4.0",
9
+ "cypress": "13.6.1",
10
10
  "cypress-audit": "1.1.0",
11
11
  "eslint-plugin-cypress": "2.15.1",
12
- "lighthouse": "11.2.0",
12
+ "lighthouse": "11.3.0",
13
13
  "nyc": "15.1.0",
14
- "swagger-ui-dist": "5.9.1"
14
+ "swagger-ui-dist": "5.10.3"
15
15
  }
16
16
  }
@@ -34,14 +34,14 @@ const { ANGULAR, VUE } = clientFrameworkTypes;
34
34
  * @param {string} dto - dto
35
35
  * @param [customDateType]
36
36
  * @param {boolean} embedded - either the actual entity is embedded or not
37
- * @param { string} clientFramwork
37
+ * @param { string} clientFramework
38
38
  * @returns variablesWithTypes: Array
39
39
  */
40
- const generateEntityClientFields = (primaryKey, fields, relationships, dto, customDateType = 'dayjs.Dayjs', embedded = false, clientFramwork = ANGULAR) => {
40
+ const generateEntityClientFields = (primaryKey, fields, relationships, dto, customDateType = 'dayjs.Dayjs', embedded = false, clientFramework = ANGULAR) => {
41
41
  const variablesWithTypes = [];
42
42
  if (!embedded && primaryKey) {
43
43
  const tsKeyType = getTypescriptKeyType(primaryKey);
44
- if (clientFramwork === VUE) {
44
+ if (clientFramework === VUE) {
45
45
  variablesWithTypes.push(`id?: ${tsKeyType}`);
46
46
  }
47
47
  }
@@ -109,7 +109,7 @@ The service worker initialization code is commented out by default. To enable it
109
109
  Note: [Workbox](https://developers.google.com/web/tools/workbox/) powers JHipster's service worker. It dynamically generates the `service-worker.js` file.
110
110
  <%_ } _%>
111
111
  <%_ if (clientFrameworkAngular) { _%>
112
- The service worker initialization code is disabled by default. To enable it, uncomment the following code in `<%= clientSrcDir %>app/app.module.ts`:
112
+ The service worker initialization code is disabled by default. To enable it, uncomment the following code in `<%= clientSrcDir %>app/app.config.ts`:
113
113
 
114
114
  ```typescript
115
115
  ServiceWorkerModule.register('ngsw-worker.js', { enabled: false }),
@@ -132,7 +132,7 @@ To benefit from TypeScript type definitions from [DefinitelyTyped][] repository
132
132
 
133
133
  Then you would import the JS and CSS files specified in library's installation instructions so that [Webpack][] knows about them:
134
134
  <%_ if (clientFrameworkAngular) { _%>
135
- Edit [<%= clientSrcDir %>app/app.module.ts](<%= clientSrcDir %>app/app.module.ts) file:
135
+ Edit [<%= clientSrcDir %>app/app.config.ts](<%= clientSrcDir %>app/app.config.ts) file:
136
136
 
137
137
  ```
138
138
  import 'leaflet/dist/leaflet.js';
@@ -43,7 +43,7 @@
43
43
  </p>
44
44
  <![endif]-->
45
45
  <%_ if (clientFrameworkAngular) { _%>
46
- <<%= jhiPrefixDashed %>-main>
46
+ <<%= jhiPrefixDashed %>-app>
47
47
  <%_ } else { _%>
48
48
  <div id="<% if (clientFrameworkReact) { %>root<% } else { %>app<% } %>">
49
49
  <%_ } _%>
@@ -95,7 +95,7 @@
95
95
  </div>
96
96
  </div>
97
97
  <%_ if (clientFrameworkAngular) { _%>
98
- </<%= jhiPrefixDashed %>-main>
98
+ </<%= jhiPrefixDashed %>-app>
99
99
  <%_ } else { _%>
100
100
  </div>
101
101
  <%_ } _%>
@@ -1,3 +1,4 @@
1
+ import { GENERATOR_BOOTSTRAP_APPLICATION_BASE } from '../generator-list.mjs';
1
2
  const command = {
2
3
  options: {
3
4
  prettierTabWidth: {
@@ -11,5 +12,6 @@ const command = {
11
12
  scope: 'storage',
12
13
  },
13
14
  },
15
+ import: [GENERATOR_BOOTSTRAP_APPLICATION_BASE],
14
16
  };
15
17
  export default command;
@@ -2,8 +2,8 @@
2
2
  "devDependencies": {
3
3
  "concurrently": "8.2.2",
4
4
  "husky": "8.0.3",
5
- "lint-staged": "15.0.2",
6
- "npm": "10.2.2",
7
- "wait-on": "7.0.1"
5
+ "lint-staged": "15.2.0",
6
+ "npm": "10.2.4",
7
+ "wait-on": "7.2.0"
8
8
  }
9
9
  }
@@ -1,7 +1,7 @@
1
1
  sonar.projectKey=<%= baseName %>
2
2
  sonar.projectName=<%= baseName %> generated by jhipster
3
3
 
4
- # Typescript tests files must be inside sources and tests, othewise `INFO: Test execution data ignored for 80 unknown files, including:` is shown.
4
+ # Typescript tests files must be inside sources and tests, otherwise `INFO: Test execution data ignored for 80 unknown files, including:` is shown.
5
5
  sonar.sources=src
6
6
  sonar.tests=src
7
7
  sonar.host.url=http://localhost:9001
@@ -335,7 +335,6 @@ describe('<%= entityClass %> e2e test', () => {
335
335
  <%_ } _%>
336
336
  <%_ }); _%>
337
337
  <%_ for (relationship of requiredRelationships) {
338
- const ownerSide = relationship.ownerSide;
339
338
  const relationshipName = relationship.relationshipName;
340
339
  _%>
341
340
  cy.get(`[data-cy="<%= relationship.relationshipFieldName %>"]`).select(<%= relationship.collection ? '[0]' : '1' %>);
@@ -209,7 +209,7 @@ export default class DockerGenerator extends BaseApplicationGenerator {
209
209
  });
210
210
  if (application.databaseTypeCassandra) {
211
211
  // Wait for migration
212
- postServicesSleep = 5;
212
+ postServicesSleep = 10;
213
213
  }
214
214
  }
215
215
  else {
@@ -33,10 +33,10 @@ services:
33
33
  - 127.0.0.1:9042:9042
34
34
  - 127.0.0.1:9160:9160
35
35
  healthcheck:
36
- test: ['CMD-SHELL', '[ $$(nodetool statusgossip) = running ]']
36
+ test: ['CMD', 'cqlsh', '-e', 'describe keyspaces']
37
37
  interval: 5s
38
38
  timeout: 25s
39
- retries: 10
39
+ retries: 20
40
40
  cassandra-migration:
41
41
  environment:
42
42
  - CASSANDRA_CONTACT_POINT=<%= baseName.toLowerCase() %>-cassandra
@@ -21,7 +21,7 @@ name: <%= baseName.toLowerCase() %>
21
21
  services:
22
22
  keycloak:
23
23
  image: <%- dockerContainers.keycloak %>
24
- command: ['start-dev --import-realm']
24
+ command: 'start-dev --import-realm'
25
25
  volumes:
26
26
  - ./realm-config:/opt/keycloak/data/import
27
27
  - ./realm-config/keycloak-health-check.sh:/opt/keycloak/health-check.sh
@@ -475,6 +475,7 @@
475
475
  "totpAppFreeOTPName",
476
476
  "totpAppMicrosoftAuthenticatorName"
477
477
  ],
478
+ "localizationTexts": {},
478
479
  "webAuthnPolicyRpEntityName": "keycloak",
479
480
  "webAuthnPolicySignatureAlgorithms": [
480
481
  "ES256"
@@ -487,6 +488,7 @@
487
488
  "webAuthnPolicyCreateTimeout": 0,
488
489
  "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
489
490
  "webAuthnPolicyAcceptableAaguids": [],
491
+ "webAuthnPolicyExtraOrigins": [],
490
492
  "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
491
493
  "webAuthnPolicyPasswordlessSignatureAlgorithms": [
492
494
  "ES256"
@@ -499,6 +501,7 @@
499
501
  "webAuthnPolicyPasswordlessCreateTimeout": 0,
500
502
  "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
501
503
  "webAuthnPolicyPasswordlessAcceptableAaguids": [],
504
+ "webAuthnPolicyPasswordlessExtraOrigins": [],
502
505
  "users": [
503
506
  {
504
507
  "id": "f742ba6f-1d8a-4dec-bf15-e02dab508283",
@@ -2576,7 +2579,7 @@
2576
2579
  "frontendUrl": "",
2577
2580
  "acr.loa.map": "[]"
2578
2581
  },
2579
- "keycloakVersion": "22.0.1",
2582
+ "keycloakVersion": "23.0.1",
2580
2583
  "userManagedAccessAllowed": false,
2581
2584
  "clientProfiles": {
2582
2585
  "profiles": []
@@ -66,18 +66,11 @@ export default class DockerComposeGenerator extends BaseWorkspacesGenerator {
66
66
  async checkDockerCompose() {
67
67
  if (this.skipChecks)
68
68
  return;
69
- const { stdout, exitCode } = await this.spawnCommand('docker compose version', { reject: false, stdio: 'pipe' });
69
+ const { exitCode } = await this.spawnCommand('docker compose version', { reject: false, stdio: 'pipe' });
70
70
  if (exitCode !== 0) {
71
- this.log.error(chalk.red('Docker Compose 1.6.0 or later is not installed on your computer.\n' +
72
- ' Read https://docs.docker.com/compose/install/\n'));
73
- }
74
- const composeVersion = stdout.split(' ')[2].replace(/,/g, '');
75
- const composeVersionMajor = composeVersion.split('.')[0];
76
- const composeVersionMinor = composeVersion.split('.')[1];
77
- if (composeVersionMajor < 1 || (composeVersionMajor === 1 && composeVersionMinor < 6)) {
78
- this.log.error(chalk.red(`$Docker Compose version 1.6.0 or later is not installed on your computer.
79
- Docker Compose version found: ${composeVersion}
80
- Read https://docs.docker.com/compose/install`));
71
+ throw new Error(`Docker Compose V2 is not installed on your computer.
72
+ Read https://docs.docker.com/compose/install/
73
+ `);
81
74
  }
82
75
  },
83
76
  };
@@ -110,7 +110,7 @@ services:
110
110
  <%_ if (usesOauth2) { _%>
111
111
  keycloak:
112
112
  image: <%- dockerContainers.keycloak %>
113
- command: ['start-dev --import-realm']
113
+ command: 'start-dev --import-realm'
114
114
  volumes:
115
115
  - ./realm-config:/opt/keycloak/data/import
116
116
  - ./realm-config/keycloak-health-check.sh:/opt/keycloak/health-check.sh
@@ -475,6 +475,7 @@
475
475
  "totpAppFreeOTPName",
476
476
  "totpAppMicrosoftAuthenticatorName"
477
477
  ],
478
+ "localizationTexts": {},
478
479
  "webAuthnPolicyRpEntityName": "keycloak",
479
480
  "webAuthnPolicySignatureAlgorithms": [
480
481
  "ES256"
@@ -487,6 +488,7 @@
487
488
  "webAuthnPolicyCreateTimeout": 0,
488
489
  "webAuthnPolicyAvoidSameAuthenticatorRegister": false,
489
490
  "webAuthnPolicyAcceptableAaguids": [],
491
+ "webAuthnPolicyExtraOrigins": [],
490
492
  "webAuthnPolicyPasswordlessRpEntityName": "keycloak",
491
493
  "webAuthnPolicyPasswordlessSignatureAlgorithms": [
492
494
  "ES256"
@@ -499,6 +501,7 @@
499
501
  "webAuthnPolicyPasswordlessCreateTimeout": 0,
500
502
  "webAuthnPolicyPasswordlessAvoidSameAuthenticatorRegister": false,
501
503
  "webAuthnPolicyPasswordlessAcceptableAaguids": [],
504
+ "webAuthnPolicyPasswordlessExtraOrigins": [],
502
505
  "users": [
503
506
  {
504
507
  "id": "f742ba6f-1d8a-4dec-bf15-e02dab508283",
@@ -2578,7 +2581,7 @@
2578
2581
  "frontendUrl": "",
2579
2582
  "acr.loa.map": "[]"
2580
2583
  },
2581
- "keycloakVersion": "22.0.1",
2584
+ "keycloakVersion": "23.0.1",
2582
2585
  "userManagedAccessAllowed": false,
2583
2586
  "clientProfiles": {
2584
2587
  "profiles": []
@@ -51,7 +51,7 @@ export default class extends BaseGenerator {
51
51
  }
52
52
  catch (error) {
53
53
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
54
- throw new Error(`An error occurred while exporting to JDL: ${error.message}\n${error}`);
54
+ throw new Error(`An error occurred while exporting to JDL: ${error.message}\n${error}`, { cause: error });
55
55
  }
56
56
  },
57
57
  });
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Removes server files that where generated in previous JHipster versions and therefore
3
+ * need to be removed.
4
+ */
5
+ export default function cleanupTask({ application }) {
6
+ if (this.isJhipsterVersionLessThan('8.0.1')) {
7
+ if (application.authenticationTypeOauth2) {
8
+ this.removeFile(`${application.javaPackageSrcDir}security/oauth2/AuthorizationHeaderUtil.java`);
9
+ this.removeFile(`${application.javaPackageTestDir}security/oauth2/AuthorizationHeaderUtilTest.java`);
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,35 @@
1
+ import { SERVER_MAIN_SRC_DIR, SERVER_TEST_SRC_DIR } from '../generator-constants.mjs';
2
+ import { moveToJavaPackageSrcDir, moveToJavaPackageTestDir } from '../java/support/index.mjs';
3
+ export const feignFiles = {
4
+ microserviceFeignFiles: [
5
+ {
6
+ path: `${SERVER_MAIN_SRC_DIR}_package_/`,
7
+ renameTo: moveToJavaPackageSrcDir,
8
+ templates: ['config/FeignConfiguration.java'],
9
+ },
10
+ {
11
+ condition: generator => generator.authenticationTypeOauth2,
12
+ path: `${SERVER_MAIN_SRC_DIR}_package_/`,
13
+ renameTo: moveToJavaPackageSrcDir,
14
+ templates: [
15
+ 'client/AuthorizationHeaderUtil.java',
16
+ 'client/AuthorizedFeignClient.java',
17
+ 'client/OAuth2InterceptedFeignConfiguration.java',
18
+ 'client/TokenRelayRequestInterceptor.java',
19
+ 'client/OAuthIdpTokenResponseDTO.java',
20
+ ],
21
+ },
22
+ {
23
+ condition: generator => generator.authenticationTypeJwt,
24
+ path: `${SERVER_MAIN_SRC_DIR}_package_/`,
25
+ renameTo: moveToJavaPackageSrcDir,
26
+ templates: ['client/UserFeignClientInterceptor_jwt.java'],
27
+ },
28
+ {
29
+ condition: generator => generator.authenticationTypeOauth2,
30
+ path: `${SERVER_TEST_SRC_DIR}_package_/`,
31
+ renameTo: moveToJavaPackageTestDir,
32
+ templates: ['client/AuthorizationHeaderUtilTest.java'],
33
+ },
34
+ ],
35
+ };
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Copyright 2013-2023 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
+ import BaseApplicationGenerator from '../base-application/index.mjs';
20
+ import { GENERATOR_BOOTSTRAP_APPLICATION, GENERATOR_FEIGN_CLIENT } from '../generator-list.mjs';
21
+ import { feignFiles } from './files.mjs';
22
+ import cleanupTask from './cleanup.mjs';
23
+ export default class FeignClientGenerator extends BaseApplicationGenerator {
24
+ async beforeQueue() {
25
+ if (!this.fromBlueprint) {
26
+ await this.composeWithBlueprints(GENERATOR_FEIGN_CLIENT);
27
+ }
28
+ if (!this.delegateToBlueprint) {
29
+ await this.dependsOnJHipster(GENERATOR_BOOTSTRAP_APPLICATION);
30
+ }
31
+ }
32
+ get writing() {
33
+ return this.asWritingTaskGroup({
34
+ cleanupTask,
35
+ async writeTask({ application }) {
36
+ await this.writeFiles({
37
+ sections: feignFiles,
38
+ context: application,
39
+ });
40
+ },
41
+ });
42
+ }
43
+ get [BaseApplicationGenerator.WRITING]() {
44
+ return this.delegateTasksToBlueprint(() => this.writing);
45
+ }
46
+ get postWriting() {
47
+ return this.asPostWritingTaskGroup({
48
+ addDependencies({ application, source }) {
49
+ const openFeignArtifact = { groupId: 'org.springframework.cloud', artifactId: 'spring-cloud-starter-openfeign' };
50
+ if (application.buildToolMaven) {
51
+ source.addMavenDependency?.(openFeignArtifact);
52
+ }
53
+ if (application.buildToolGradle) {
54
+ source.addGradleDependency?.({
55
+ ...openFeignArtifact,
56
+ scope: 'implementation',
57
+ });
58
+ }
59
+ },
60
+ });
61
+ }
62
+ get [BaseApplicationGenerator.POST_WRITING]() {
63
+ return this.asPostWritingTaskGroup(this.delegateTasksToBlueprint(() => this.postWriting));
64
+ }
65
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Copyright 2013-2023 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
+ export { default } from './generator.mjs';
@@ -0,0 +1,174 @@
1
+ <%#
2
+ Copyright 2013-2023 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 %>.client;
20
+
21
+ import java.net.URI;
22
+ import java.time.Duration;
23
+ import java.time.Instant;
24
+ import java.util.HashMap;
25
+ import java.util.Map;
26
+ import java.util.Optional;
27
+
28
+ import org.slf4j.Logger;
29
+ import org.slf4j.LoggerFactory;
30
+ import org.springframework.boot.web.client.RestTemplateBuilder;
31
+ import org.springframework.http.MediaType;
32
+ import org.springframework.http.RequestEntity;
33
+ import org.springframework.http.ResponseEntity;
34
+ import org.springframework.http.converter.FormHttpMessageConverter;
35
+ import org.springframework.security.core.Authentication;
36
+ import org.springframework.security.core.context.SecurityContextHolder;
37
+ import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
38
+ import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
39
+ import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
40
+ import org.springframework.security.oauth2.client.http.OAuth2ErrorResponseErrorHandler;
41
+ import org.springframework.security.oauth2.core.*;
42
+ import org.springframework.security.oauth2.core.endpoint.OAuth2AccessTokenResponse;
43
+ import org.springframework.security.oauth2.core.endpoint.OAuth2ParameterNames;
44
+ import org.springframework.security.oauth2.core.http.converter.OAuth2AccessTokenResponseHttpMessageConverter;
45
+ import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken;
46
+ import org.springframework.stereotype.Component;
47
+ import org.springframework.util.LinkedMultiValueMap;
48
+ import org.springframework.util.MultiValueMap;
49
+ import org.springframework.web.client.RestTemplate;
50
+
51
+ import java.util.regex.Pattern;
52
+ import java.util.stream.Collectors;
53
+
54
+ @Component
55
+ public class AuthorizationHeaderUtil {
56
+
57
+ private final OAuth2AuthorizedClientService clientService;
58
+ private final RestTemplateBuilder restTemplateBuilder;
59
+ private final Logger log = LoggerFactory.getLogger(AuthorizationHeaderUtil.class);
60
+
61
+ public AuthorizationHeaderUtil(OAuth2AuthorizedClientService clientService, RestTemplateBuilder restTemplateBuilder) {
62
+ this.clientService = clientService;
63
+ this.restTemplateBuilder = restTemplateBuilder;
64
+ }
65
+
66
+ public Optional<String> getAuthorizationHeader() {
67
+ Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
68
+ if (authentication instanceof OAuth2AuthenticationToken) {
69
+ OAuth2AuthenticationToken oauthToken = (OAuth2AuthenticationToken) authentication;
70
+ String name = oauthToken.getName();
71
+ String registrationId = oauthToken.getAuthorizedClientRegistrationId();
72
+ OAuth2AuthorizedClient client = clientService.loadAuthorizedClient(
73
+ registrationId,
74
+ name);
75
+
76
+ if (null == client) {
77
+ throw new OAuth2AuthorizationException(new OAuth2Error("access_denied", "The token is expired", null));
78
+ }
79
+ OAuth2AccessToken accessToken = client.getAccessToken();
80
+
81
+ if (accessToken != null) {
82
+ String tokenType = accessToken.getTokenType().getValue();
83
+ String accessTokenValue = accessToken.getTokenValue();
84
+ if (isExpired(accessToken)) {
85
+ log.info("AccessToken expired, refreshing automatically");
86
+ accessTokenValue = refreshToken(client, oauthToken);
87
+ if (null == accessTokenValue) {
88
+ SecurityContextHolder.getContext().setAuthentication(null);
89
+ throw new OAuth2AuthorizationException(new OAuth2Error("access_denied", "The token is expired", null));
90
+ }
91
+ }
92
+ String authorizationHeaderValue = String.format("%s %s", tokenType, accessTokenValue);
93
+ return Optional.of(authorizationHeaderValue);
94
+ }
95
+
96
+ } else if (authentication instanceof JwtAuthenticationToken) {
97
+ JwtAuthenticationToken accessToken = (JwtAuthenticationToken) authentication;
98
+ String tokenValue = accessToken.getToken().getTokenValue();
99
+ String authorizationHeaderValue = String.format("%s %s", OAuth2AccessToken.TokenType.BEARER.getValue(), tokenValue);
100
+ return Optional.of(authorizationHeaderValue);
101
+ }
102
+ return Optional.empty();
103
+ }
104
+
105
+ private String refreshToken(OAuth2AuthorizedClient client, OAuth2AuthenticationToken oauthToken) {
106
+ OAuth2AccessTokenResponse atr = refreshTokenClient(client);
107
+ if (atr == null || atr.getAccessToken() == null) {
108
+ log.info("Failed to refresh token for user");
109
+ return null;
110
+ }
111
+
112
+ OAuth2RefreshToken refreshToken = atr.getRefreshToken() != null ? atr.getRefreshToken(): client.getRefreshToken();
113
+ OAuth2AuthorizedClient updatedClient = new OAuth2AuthorizedClient(
114
+ client.getClientRegistration(),
115
+ client.getPrincipalName(),
116
+ atr.getAccessToken(),
117
+ refreshToken
118
+ );
119
+
120
+ clientService.saveAuthorizedClient(updatedClient, oauthToken);
121
+ return atr.getAccessToken().getTokenValue();
122
+ }
123
+
124
+ private OAuth2AccessTokenResponse refreshTokenClient(OAuth2AuthorizedClient currentClient) {
125
+
126
+ MultiValueMap<String, String> formParameters = new LinkedMultiValueMap<>();
127
+ formParameters.add(OAuth2ParameterNames.GRANT_TYPE, AuthorizationGrantType.REFRESH_TOKEN.getValue());
128
+ formParameters.add(OAuth2ParameterNames.REFRESH_TOKEN, currentClient.getRefreshToken().getTokenValue());
129
+ formParameters.add(OAuth2ParameterNames.CLIENT_ID, currentClient.getClientRegistration().getClientId());
130
+ RequestEntity requestEntity = RequestEntity
131
+ .post(URI.create(currentClient.getClientRegistration().getProviderDetails().getTokenUri()))
132
+ .contentType(MediaType.APPLICATION_FORM_URLENCODED)
133
+ .body(formParameters);
134
+ try {
135
+ RestTemplate r = restTemplate(currentClient.getClientRegistration().getClientId(), currentClient.getClientRegistration().getClientSecret());
136
+ ResponseEntity<OAuthIdpTokenResponseDTO> responseEntity = r.exchange(requestEntity, OAuthIdpTokenResponseDTO.class);
137
+ return toOAuth2AccessTokenResponse(responseEntity.getBody());
138
+ } catch (OAuth2AuthorizationException e) {
139
+ log.error("Unable to refresh token", e);
140
+ throw new OAuth2AuthenticationException(e.getError(), e);
141
+ }
142
+ }
143
+
144
+ private OAuth2AccessTokenResponse toOAuth2AccessTokenResponse(OAuthIdpTokenResponseDTO oAuthIdpResponse) {
145
+ Map<String, Object> additionalParameters = new HashMap<>();
146
+ additionalParameters.put("id_token", oAuthIdpResponse.getIdToken());
147
+ additionalParameters.put("not-before-policy", oAuthIdpResponse.getNotBefore());
148
+ additionalParameters.put("refresh_expires_in", oAuthIdpResponse.getRefreshExpiresIn());
149
+ additionalParameters.put("session_state", oAuthIdpResponse.getSessionState());
150
+ return OAuth2AccessTokenResponse.withToken(oAuthIdpResponse.getAccessToken())
151
+ .expiresIn(oAuthIdpResponse.getExpiresIn())
152
+ .refreshToken(oAuthIdpResponse.getRefreshToken())
153
+ .scopes(Pattern.compile("\\s").splitAsStream(oAuthIdpResponse.getScope()).collect(Collectors.toSet()))
154
+ .tokenType(OAuth2AccessToken.TokenType.BEARER)
155
+ .additionalParameters(additionalParameters)
156
+ .build();
157
+ }
158
+
159
+ private RestTemplate restTemplate(String clientId, String clientSecret) {
160
+ return restTemplateBuilder
161
+ .additionalMessageConverters(
162
+ new FormHttpMessageConverter(),
163
+ new OAuth2AccessTokenResponseHttpMessageConverter())
164
+ .errorHandler(new OAuth2ErrorResponseErrorHandler())
165
+ .basicAuthentication(clientId, clientSecret)
166
+ .build();
167
+ }
168
+
169
+ private boolean isExpired(OAuth2AccessToken accessToken) {
170
+ Instant now = Instant.now();
171
+ Instant expiresAt = accessToken.getExpiresAt();
172
+ return now.isAfter(expiresAt.minus(Duration.ofMinutes(1L)));
173
+ }
174
+ }
@@ -0,0 +1,72 @@
1
+ <%#
2
+ Copyright 2013-2023 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 %>.client;
20
+
21
+ import org.springframework.cloud.openfeign.FeignClient;
22
+ import org.springframework.core.annotation.AliasFor;
23
+
24
+ import java.lang.annotation.*;
25
+
26
+ @Retention(RetentionPolicy.RUNTIME)
27
+ @Target(ElementType.TYPE)
28
+ @Documented
29
+ @FeignClient
30
+ public @interface AuthorizedFeignClient {
31
+
32
+ @AliasFor(annotation = FeignClient.class, attribute = "name")
33
+ String name() default "";
34
+
35
+ /**
36
+ * A custom {@code @Configuration} for the feign client.
37
+ *
38
+ * Can contain override {@code @Bean} definition for the pieces that
39
+ * make up the client, for instance {@link feign.codec.Decoder},
40
+ * {@link feign.codec.Encoder}, {@link feign.Contract}.
41
+ *
42
+ * @return the custom {@code @Configuration} for the feign client.
43
+ * @see org.springframework.cloud.openfeign.FeignClientsConfiguration for the defaults.
44
+ */
45
+ @AliasFor(annotation = FeignClient.class, attribute = "configuration")
46
+ Class<?>[] configuration() default OAuth2InterceptedFeignConfiguration.class;
47
+
48
+ /**
49
+ * An absolute URL or resolvable hostname (the protocol is optional).
50
+ * @return the URL.
51
+ */
52
+ String url() default "";
53
+
54
+ /**
55
+ * Whether 404s should be decoded instead of throwing FeignExceptions.
56
+ * @return true if 404s will be decoded; false otherwise.
57
+ */
58
+ boolean decode404() default false;
59
+
60
+ /**
61
+ * Fallback class for the specified Feign client interface. The fallback class must
62
+ * implement the interface annotated by this annotation and be a valid Spring bean.
63
+ * @return the fallback class for the specified Feign client interface.
64
+ */
65
+ Class<?> fallback() default void.class;
66
+
67
+ /**
68
+ * Path prefix to be used by all method-level mappings.
69
+ * @return the path prefix to be used by all method-level mappings.
70
+ */
71
+ String path() default "";
72
+ }