generator-pninja 1.2.1 → 1.5.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 (299) hide show
  1. package/README.md +50 -10
  2. package/generators/app/index.js +49 -13
  3. package/generators/app/templates/package.json.ejs +23 -22
  4. package/generators/auth/index.js +27 -7
  5. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/composer.json +39 -0
  6. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/config/keycloak.php +134 -0
  7. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/Exceptions/InvalidTokenException.php +50 -0
  8. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/JwksFetcher.php +271 -0
  9. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/KeycloakGuard.php +254 -0
  10. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/KeycloakGuardServiceProvider.php +52 -0
  11. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/Testing/ActingAsKeycloakUser.php +98 -0
  12. package/generators/auth/templates/packages/pninja/laravel-keycloak-guard/src/TokenDecoder.php +163 -0
  13. package/generators/client/index.js +39 -7
  14. package/generators/client/react.inc.js +142 -116
  15. package/generators/client/templates/react/.env.ejs +2 -1
  16. package/generators/client/templates/react/package-lock.json.ejs +7 -6
  17. package/generators/client/templates/react/package.json.ejs +1 -1
  18. package/generators/client/templates/react/public/locales/entities/entities.json.ejs +2 -2
  19. package/generators/client/templates/react/public/locales/migrations/am.json +43 -0
  20. package/generators/client/templates/react/public/locales/migrations/ar.json +43 -0
  21. package/generators/client/templates/react/public/locales/migrations/az.json +43 -0
  22. package/generators/client/templates/react/public/locales/migrations/bg.json +43 -0
  23. package/generators/client/templates/react/public/locales/migrations/bn.json +43 -0
  24. package/generators/client/templates/react/public/locales/migrations/ca.json +43 -0
  25. package/generators/client/templates/react/public/locales/migrations/cs.json +43 -0
  26. package/generators/client/templates/react/public/locales/migrations/cy.json +43 -0
  27. package/generators/client/templates/react/public/locales/migrations/da.json +43 -0
  28. package/generators/client/templates/react/public/locales/migrations/de.json +43 -0
  29. package/generators/client/templates/react/public/locales/migrations/el.json +43 -0
  30. package/generators/client/templates/react/public/locales/migrations/en.json +43 -0
  31. package/generators/client/templates/react/public/locales/migrations/es.json +43 -0
  32. package/generators/client/templates/react/public/locales/migrations/et.json +43 -0
  33. package/generators/client/templates/react/public/locales/migrations/eu.json +43 -0
  34. package/generators/client/templates/react/public/locales/migrations/fa.json +43 -0
  35. package/generators/client/templates/react/public/locales/migrations/fi.json +43 -0
  36. package/generators/client/templates/react/public/locales/migrations/fr.json +43 -0
  37. package/generators/client/templates/react/public/locales/migrations/fy.json +43 -0
  38. package/generators/client/templates/react/public/locales/migrations/ga.json +43 -0
  39. package/generators/client/templates/react/public/locales/migrations/gl.json +43 -0
  40. package/generators/client/templates/react/public/locales/migrations/gu.json +43 -0
  41. package/generators/client/templates/react/public/locales/migrations/ha.json +43 -0
  42. package/generators/client/templates/react/public/locales/migrations/he.json +43 -0
  43. package/generators/client/templates/react/public/locales/migrations/hi.json +43 -0
  44. package/generators/client/templates/react/public/locales/migrations/hr.json +43 -0
  45. package/generators/client/templates/react/public/locales/migrations/ht.json +43 -0
  46. package/generators/client/templates/react/public/locales/migrations/hu.json +43 -0
  47. package/generators/client/templates/react/public/locales/migrations/hy.json +43 -0
  48. package/generators/client/templates/react/public/locales/migrations/id.json +43 -0
  49. package/generators/client/templates/react/public/locales/migrations/is.json +43 -0
  50. package/generators/client/templates/react/public/locales/migrations/it.json +43 -0
  51. package/generators/client/templates/react/public/locales/migrations/ja.json +43 -0
  52. package/generators/client/templates/react/public/locales/migrations/kk.json +43 -0
  53. package/generators/client/templates/react/public/locales/migrations/ko.json +43 -0
  54. package/generators/client/templates/react/public/locales/migrations/lt.json +43 -0
  55. package/generators/client/templates/react/public/locales/migrations/lv.json +43 -0
  56. package/generators/client/templates/react/public/locales/migrations/mi.json +43 -0
  57. package/generators/client/templates/react/public/locales/migrations/ms.json +43 -0
  58. package/generators/client/templates/react/public/locales/migrations/mt.json +43 -0
  59. package/generators/client/templates/react/public/locales/migrations/nl.json +43 -0
  60. package/generators/client/templates/react/public/locales/migrations/no.json +43 -0
  61. package/generators/client/templates/react/public/locales/migrations/om.json +43 -0
  62. package/generators/client/templates/react/public/locales/migrations/pl.json +43 -0
  63. package/generators/client/templates/react/public/locales/migrations/pt.json +43 -0
  64. package/generators/client/templates/react/public/locales/migrations/ro.json +43 -0
  65. package/generators/client/templates/react/public/locales/migrations/ru.json +43 -0
  66. package/generators/client/templates/react/public/locales/migrations/rw.json +43 -0
  67. package/generators/client/templates/react/public/locales/migrations/sk.json +43 -0
  68. package/generators/client/templates/react/public/locales/migrations/sl.json +43 -0
  69. package/generators/client/templates/react/public/locales/migrations/sq.json +43 -0
  70. package/generators/client/templates/react/public/locales/migrations/sr.json +43 -0
  71. package/generators/client/templates/react/public/locales/migrations/sv.json +43 -0
  72. package/generators/client/templates/react/public/locales/migrations/sw.json +43 -0
  73. package/generators/client/templates/react/public/locales/migrations/ta.json +43 -0
  74. package/generators/client/templates/react/public/locales/migrations/tr.json +43 -0
  75. package/generators/client/templates/react/public/locales/migrations/uk.json +43 -0
  76. package/generators/client/templates/react/public/locales/migrations/ur.json +43 -0
  77. package/generators/client/templates/react/public/locales/migrations/uz.json +43 -0
  78. package/generators/client/templates/react/public/locales/migrations/vi.json +43 -0
  79. package/generators/client/templates/react/public/locales/migrations/yo.json +43 -0
  80. package/generators/client/templates/react/public/locales/migrations/zh.json +43 -0
  81. package/generators/client/templates/react/public/locales/migrations/zu.json +43 -0
  82. package/generators/client/templates/react/public/locales/searchReindex/am.json +60 -0
  83. package/generators/client/templates/react/public/locales/searchReindex/ar.json +60 -0
  84. package/generators/client/templates/react/public/locales/searchReindex/az.json +60 -0
  85. package/generators/client/templates/react/public/locales/searchReindex/bg.json +60 -0
  86. package/generators/client/templates/react/public/locales/searchReindex/bn.json +60 -0
  87. package/generators/client/templates/react/public/locales/searchReindex/ca.json +60 -0
  88. package/generators/client/templates/react/public/locales/searchReindex/cs.json +60 -0
  89. package/generators/client/templates/react/public/locales/searchReindex/cy.json +60 -0
  90. package/generators/client/templates/react/public/locales/searchReindex/da.json +60 -0
  91. package/generators/client/templates/react/public/locales/searchReindex/de.json +60 -0
  92. package/generators/client/templates/react/public/locales/searchReindex/el.json +60 -0
  93. package/generators/client/templates/react/public/locales/searchReindex/en.json +60 -0
  94. package/generators/client/templates/react/public/locales/searchReindex/es.json +60 -0
  95. package/generators/client/templates/react/public/locales/searchReindex/et.json +60 -0
  96. package/generators/client/templates/react/public/locales/searchReindex/eu.json +60 -0
  97. package/generators/client/templates/react/public/locales/searchReindex/fa.json +60 -0
  98. package/generators/client/templates/react/public/locales/searchReindex/fi.json +60 -0
  99. package/generators/client/templates/react/public/locales/searchReindex/fr.json +60 -0
  100. package/generators/client/templates/react/public/locales/searchReindex/fy.json +60 -0
  101. package/generators/client/templates/react/public/locales/searchReindex/ga.json +60 -0
  102. package/generators/client/templates/react/public/locales/searchReindex/gl.json +60 -0
  103. package/generators/client/templates/react/public/locales/searchReindex/gu.json +60 -0
  104. package/generators/client/templates/react/public/locales/searchReindex/ha.json +60 -0
  105. package/generators/client/templates/react/public/locales/searchReindex/he.json +60 -0
  106. package/generators/client/templates/react/public/locales/searchReindex/hi.json +60 -0
  107. package/generators/client/templates/react/public/locales/searchReindex/hr.json +60 -0
  108. package/generators/client/templates/react/public/locales/searchReindex/ht.json +60 -0
  109. package/generators/client/templates/react/public/locales/searchReindex/hu.json +60 -0
  110. package/generators/client/templates/react/public/locales/searchReindex/hy.json +60 -0
  111. package/generators/client/templates/react/public/locales/searchReindex/id.json +60 -0
  112. package/generators/client/templates/react/public/locales/searchReindex/is.json +60 -0
  113. package/generators/client/templates/react/public/locales/searchReindex/it.json +60 -0
  114. package/generators/client/templates/react/public/locales/searchReindex/ja.json +60 -0
  115. package/generators/client/templates/react/public/locales/searchReindex/kk.json +60 -0
  116. package/generators/client/templates/react/public/locales/searchReindex/ko.json +60 -0
  117. package/generators/client/templates/react/public/locales/searchReindex/lt.json +60 -0
  118. package/generators/client/templates/react/public/locales/searchReindex/lv.json +60 -0
  119. package/generators/client/templates/react/public/locales/searchReindex/mi.json +60 -0
  120. package/generators/client/templates/react/public/locales/searchReindex/ms.json +60 -0
  121. package/generators/client/templates/react/public/locales/searchReindex/mt.json +60 -0
  122. package/generators/client/templates/react/public/locales/searchReindex/nl.json +60 -0
  123. package/generators/client/templates/react/public/locales/searchReindex/no.json +60 -0
  124. package/generators/client/templates/react/public/locales/searchReindex/om.json +60 -0
  125. package/generators/client/templates/react/public/locales/searchReindex/pl.json +60 -0
  126. package/generators/client/templates/react/public/locales/searchReindex/pt.json +60 -0
  127. package/generators/client/templates/react/public/locales/searchReindex/ro.json +60 -0
  128. package/generators/client/templates/react/public/locales/searchReindex/ru.json +60 -0
  129. package/generators/client/templates/react/public/locales/searchReindex/rw.json +60 -0
  130. package/generators/client/templates/react/public/locales/searchReindex/sk.json +60 -0
  131. package/generators/client/templates/react/public/locales/searchReindex/sl.json +60 -0
  132. package/generators/client/templates/react/public/locales/searchReindex/sq.json +60 -0
  133. package/generators/client/templates/react/public/locales/searchReindex/sr.json +60 -0
  134. package/generators/client/templates/react/public/locales/searchReindex/sv.json +60 -0
  135. package/generators/client/templates/react/public/locales/searchReindex/sw.json +60 -0
  136. package/generators/client/templates/react/public/locales/searchReindex/ta.json +60 -0
  137. package/generators/client/templates/react/public/locales/searchReindex/tr.json +60 -0
  138. package/generators/client/templates/react/public/locales/searchReindex/uk.json +60 -0
  139. package/generators/client/templates/react/public/locales/searchReindex/ur.json +60 -0
  140. package/generators/client/templates/react/public/locales/searchReindex/uz.json +60 -0
  141. package/generators/client/templates/react/public/locales/searchReindex/vi.json +60 -0
  142. package/generators/client/templates/react/public/locales/searchReindex/yo.json +60 -0
  143. package/generators/client/templates/react/public/locales/searchReindex/zh.json +60 -0
  144. package/generators/client/templates/react/public/locales/searchReindex/zu.json +60 -0
  145. package/generators/client/templates/react/public/locales/seeder/am.json +32 -0
  146. package/generators/client/templates/react/public/locales/seeder/ar.json +32 -0
  147. package/generators/client/templates/react/public/locales/seeder/az.json +32 -0
  148. package/generators/client/templates/react/public/locales/seeder/bg.json +32 -0
  149. package/generators/client/templates/react/public/locales/seeder/bn.json +32 -0
  150. package/generators/client/templates/react/public/locales/seeder/ca.json +32 -0
  151. package/generators/client/templates/react/public/locales/seeder/cs.json +32 -0
  152. package/generators/client/templates/react/public/locales/seeder/cy.json +32 -0
  153. package/generators/client/templates/react/public/locales/seeder/da.json +32 -0
  154. package/generators/client/templates/react/public/locales/seeder/de.json +32 -0
  155. package/generators/client/templates/react/public/locales/seeder/el.json +32 -0
  156. package/generators/client/templates/react/public/locales/seeder/en.json +32 -0
  157. package/generators/client/templates/react/public/locales/seeder/es.json +32 -0
  158. package/generators/client/templates/react/public/locales/seeder/et.json +32 -0
  159. package/generators/client/templates/react/public/locales/seeder/eu.json +32 -0
  160. package/generators/client/templates/react/public/locales/seeder/fa.json +32 -0
  161. package/generators/client/templates/react/public/locales/seeder/fi.json +32 -0
  162. package/generators/client/templates/react/public/locales/seeder/fr.json +32 -0
  163. package/generators/client/templates/react/public/locales/seeder/fy.json +32 -0
  164. package/generators/client/templates/react/public/locales/seeder/ga.json +32 -0
  165. package/generators/client/templates/react/public/locales/seeder/gl.json +32 -0
  166. package/generators/client/templates/react/public/locales/seeder/gu.json +32 -0
  167. package/generators/client/templates/react/public/locales/seeder/ha.json +32 -0
  168. package/generators/client/templates/react/public/locales/seeder/he.json +32 -0
  169. package/generators/client/templates/react/public/locales/seeder/hi.json +32 -0
  170. package/generators/client/templates/react/public/locales/seeder/hr.json +32 -0
  171. package/generators/client/templates/react/public/locales/seeder/ht.json +32 -0
  172. package/generators/client/templates/react/public/locales/seeder/hu.json +32 -0
  173. package/generators/client/templates/react/public/locales/seeder/hy.json +32 -0
  174. package/generators/client/templates/react/public/locales/seeder/id.json +32 -0
  175. package/generators/client/templates/react/public/locales/seeder/is.json +32 -0
  176. package/generators/client/templates/react/public/locales/seeder/it.json +32 -0
  177. package/generators/client/templates/react/public/locales/seeder/ja.json +32 -0
  178. package/generators/client/templates/react/public/locales/seeder/kk.json +32 -0
  179. package/generators/client/templates/react/public/locales/seeder/ko.json +32 -0
  180. package/generators/client/templates/react/public/locales/seeder/lt.json +32 -0
  181. package/generators/client/templates/react/public/locales/seeder/lv.json +32 -0
  182. package/generators/client/templates/react/public/locales/seeder/mi.json +32 -0
  183. package/generators/client/templates/react/public/locales/seeder/ms.json +32 -0
  184. package/generators/client/templates/react/public/locales/seeder/mt.json +32 -0
  185. package/generators/client/templates/react/public/locales/seeder/nl.json +32 -0
  186. package/generators/client/templates/react/public/locales/seeder/no.json +32 -0
  187. package/generators/client/templates/react/public/locales/seeder/om.json +32 -0
  188. package/generators/client/templates/react/public/locales/seeder/pl.json +32 -0
  189. package/generators/client/templates/react/public/locales/seeder/pt.json +32 -0
  190. package/generators/client/templates/react/public/locales/seeder/ro.json +32 -0
  191. package/generators/client/templates/react/public/locales/seeder/ru.json +32 -0
  192. package/generators/client/templates/react/public/locales/seeder/rw.json +32 -0
  193. package/generators/client/templates/react/public/locales/seeder/sk.json +32 -0
  194. package/generators/client/templates/react/public/locales/seeder/sl.json +32 -0
  195. package/generators/client/templates/react/public/locales/seeder/sq.json +32 -0
  196. package/generators/client/templates/react/public/locales/seeder/sr.json +32 -0
  197. package/generators/client/templates/react/public/locales/seeder/sv.json +32 -0
  198. package/generators/client/templates/react/public/locales/seeder/sw.json +32 -0
  199. package/generators/client/templates/react/public/locales/seeder/ta.json +32 -0
  200. package/generators/client/templates/react/public/locales/seeder/tr.json +32 -0
  201. package/generators/client/templates/react/public/locales/seeder/uk.json +32 -0
  202. package/generators/client/templates/react/public/locales/seeder/ur.json +32 -0
  203. package/generators/client/templates/react/public/locales/seeder/uz.json +32 -0
  204. package/generators/client/templates/react/public/locales/seeder/vi.json +32 -0
  205. package/generators/client/templates/react/public/locales/seeder/yo.json +32 -0
  206. package/generators/client/templates/react/public/locales/seeder/zh.json +32 -0
  207. package/generators/client/templates/react/public/locales/seeder/zu.json +32 -0
  208. package/generators/client/templates/react/src/App.tsx.ejs +40 -3
  209. package/generators/client/templates/react/src/components/LangSelect.tsx.ejs +1 -1
  210. package/generators/client/templates/react/src/components/Menu.tsx.ejs +40 -9
  211. package/generators/client/templates/react/src/components/Toast.tsx.ejs +3 -3
  212. package/generators/client/templates/react/src/components/entities/EntityForm.tsx.ejs +21 -21
  213. package/generators/client/templates/react/src/components/formElements/RadioGroup.tsx.ejs +1 -1
  214. package/generators/client/templates/react/src/i18n.js.ejs +1 -1
  215. package/generators/client/templates/react/src/index.css.ejs +1 -5
  216. package/generators/client/templates/react/src/pages/admin/Migrations.tsx.ejs +427 -0
  217. package/generators/client/templates/react/src/pages/search-reindex/SearchReindexList.tsx.ejs +716 -0
  218. package/generators/client/templates/react/src/pages/seeder/SeederList.tsx.ejs +478 -0
  219. package/generators/client/templates/react/src/shared/entitiesIcons.tsx.ejs +1 -3
  220. package/generators/client/templates/react/src/shared/model/entity.model.ts.ejs +4 -4
  221. package/generators/client/utils/getEntityFillableProperties.js +6 -6
  222. package/generators/client/utils/getModelForeignIds.js +16 -16
  223. package/generators/client/utils/getModelRelatedEntities.js +39 -43
  224. package/generators/entities/index.js +114 -117
  225. package/generators/entities/templates/EntityFactory.php.ejs +0 -11
  226. package/generators/entities/templates/database/seeders/AcRuleSeeder.php.ejs +83 -0
  227. package/generators/entities/templates/database/seeders/DatabaseSeeder.php.ejs +28 -0
  228. package/generators/entities/templates/database/seeders/EntitySeeder.php.ejs +30 -0
  229. package/generators/entities/templates/database/seeders/ManyToManySeeder.php.ejs +20 -0
  230. package/generators/entities/templates/database/seeders/csv/.gitkeep +0 -0
  231. package/generators/entities/templates/migration_add_columns_to_table.php.ejs +27 -0
  232. package/generators/entities/templates/migration_create_table.php.ejs +1 -1
  233. package/generators/entities/templates/migration_remove_columns_from_table.php.ejs +27 -0
  234. package/generators/entities/templates/migration_remove_pivot_table.php.ejs +24 -0
  235. package/generators/entities/utils/controllers-generator.js +151 -180
  236. package/generators/entities/utils/entity-splitter.js +204 -0
  237. package/generators/entities/utils/factories-generator.js +79 -73
  238. package/generators/entities/utils/migrations-generator.js +285 -149
  239. package/generators/entities/utils/models-generator.js +189 -199
  240. package/generators/entities/utils/routers-generator.js +15 -14
  241. package/generators/entities/utils/validateJDL.js +139 -0
  242. package/generators/entity/index.js +1016 -0
  243. package/generators/final/index.js +3 -1
  244. package/generators/final/templates/README.md.ejs +109 -1
  245. package/generators/search/index.js +112 -82
  246. package/generators/server/index.js +121 -0
  247. package/generators/server/templates/.gitkeep.ejs +0 -0
  248. package/generators/server/templates/ApiErrorHandler.php.ejs +31 -0
  249. package/generators/server/templates/DatabaseErrorHandler.php.ejs +154 -0
  250. package/generators/server/templates/NotFoundErrorHandler.php.ejs +41 -0
  251. package/generators/server/templates/Providers/AppServiceProvider.php.ejs +53 -0
  252. package/generators/server/templates/ValidationErrorHandler.php.ejs +27 -0
  253. package/generators/server/templates/app/Http/Controllers/MigrationsController.php.ejs +56 -0
  254. package/generators/server/templates/app/Http/Controllers/SearchReindexController.php.ejs +133 -0
  255. package/generators/server/templates/app/Http/Controllers/SeederController.php.ejs +75 -0
  256. package/generators/{entities → server}/templates/app/Http/Middleware/AccessControl.php.ejs +3 -0
  257. package/generators/server/templates/app/Http/Requests/ReindexRequest.php.ejs +32 -0
  258. package/generators/server/templates/app/Http/Requests/SeedCsvRequest.php.ejs +13 -0
  259. package/generators/server/templates/app/Http/Requests/SeedRequest.php.ejs +34 -0
  260. package/generators/server/templates/app/Jobs/ReindexEntityJob.php.ejs +63 -0
  261. package/generators/server/templates/app/Jobs/RunMigrationsJob.php.ejs +46 -0
  262. package/generators/server/templates/app/Jobs/RunSeederJob.php.ejs +43 -0
  263. package/generators/server/templates/app/Resolvers/Keycloak__UserResolver.php.ejs +34 -0
  264. package/generators/server/templates/app/Traits/HandlesApiErrors.php.ejs +39 -0
  265. package/generators/server/templates/app/Traits/HandlesUserRoles.php.ejs +90 -0
  266. package/generators/server/templates/app/Traits/SeederHelpers.php.ejs +56 -0
  267. package/generators/server/templates/app.php.ejs +31 -0
  268. package/generators/server/templates/config/audit.php.ejs +202 -0
  269. package/generators/server/templates/config/lauthz-rbac-model.conf +14 -0
  270. package/generators/server/templates/config/lauthz.php +70 -0
  271. package/generators/server/templates/database/migrations/create_ac_rules_table.php.ejs +28 -0
  272. package/generators/server/templates/database/migrations/create_audits_table.php.ejs +52 -0
  273. package/generators/server/templates/filesystems.php.ejs +81 -0
  274. package/generators/{entities → server}/templates/routes/api.php.ejs +39 -2
  275. package/generators/{entities → server}/templates/routes/console.php.ejs +1 -1
  276. package/generators/utils/AcRule.js +44 -2
  277. package/generators/utils/entities-utils.js +114 -0
  278. package/generators/utils/getWiths.js +21 -24
  279. package/generators/utils/hello.js +2 -2
  280. package/generators/utils/reserved-words.js +39 -0
  281. package/package.json +1 -1
  282. package/generators/entities/templates/DatabaseSeeder.php.ejs +0 -179
  283. package/generators/entities/templates/app/Http/Controllers/AcRuleController.php.ejs +0 -151
  284. package/generators/entities/templates/app/Models/AcRule.php.ejs +0 -37
  285. package/generators/entities/templates/database/seeders/csv/AcRule.csv.ejs +0 -7
  286. package/generators/router/index.js +0 -12
  287. /package/generators/{entities → client}/templates/blobs/dummy.pdf +0 -0
  288. /package/generators/{entities → client}/templates/blobs/dummy.png +0 -0
  289. /package/generators/{entities → server}/templates/Casts/Base64BinaryCast.php.ejs +0 -0
  290. /package/generators/{entities → server}/templates/Rules/Base64MaxSize.php.ejs +0 -0
  291. /package/generators/{entities → server}/templates/Rules/Base64MinSize.php.ejs +0 -0
  292. /package/generators/{entities → server}/templates/app/Http/Controllers/AuditController.php.ejs +0 -0
  293. /package/generators/{entities → server}/templates/app/Http/Controllers/FileController.php.ejs +0 -0
  294. /package/generators/{entities → server}/templates/app/Http/Controllers/KeycloakProxyController.php.ejs +0 -0
  295. /package/generators/{entities → server}/templates/app/Http/Controllers/LogController.php.ejs +0 -0
  296. /package/generators/{entities → server}/templates/app/Http/Controllers/ScoutQuerySanitizer.php.ejs +0 -0
  297. /package/generators/{entities → server}/templates/app/Http/Controllers/SessionAuthController.php.ejs +0 -0
  298. /package/generators/{entities → server}/templates/app/Http/Controllers/UserRoleController.php.ejs +0 -0
  299. /package/generators/{entities → server}/templates/app/Http/Middleware/SessionAuth.php.ejs +0 -0
package/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  # generator-pninja
6
6
 
7
7
  Generate a full **Laravel + React + Vite** application from a single **JDL model**.
8
- Backend + Frontend + Docker + Database ready in seconds ⚡
8
+ Backend + Frontend + Docker + Database ready in seconds ⚡
9
9
 
10
10
  [![License][license-badge]][license-url]
11
11
  [![npm version][npm-version-badge]][npm-version-url]
@@ -15,7 +15,7 @@ Backend + Frontend + Docker + Database — ready in seconds ⚡
15
15
 
16
16
  ## License
17
17
 
18
- This project is licensed under the Apache License 2.0 see the [LICENSE.txt](LICENSE.txt) file for details.
18
+ This project is licensed under the Apache License 2.0 see the [LICENSE.txt](LICENSE.txt) file for details.
19
19
 
20
20
  ## What is PNinja?
21
21
 
@@ -27,7 +27,7 @@ This project is licensed under the Apache License 2.0 — see the [LICENSE.txt](
27
27
  - **Search engine:** Database, Algolia, Elasticsearch, Meilisearch, Typesense, Solr
28
28
  - **Docker Compose**
29
29
 
30
- All based on a **single JDL file** describing your domain!
30
+ All based on **JDL files** describing your domain!
31
31
 
32
32
  ## Installation
33
33
 
@@ -39,6 +39,18 @@ npm install -g yo generator-pninja
39
39
 
40
40
  ## Usage
41
41
 
42
+ ### 1. Create the Application
43
+
44
+ Generate the base application structure (server + client without entities):
45
+
46
+ ```bash
47
+ yo pninja
48
+ ```
49
+
50
+ **Answer a few prompts** ... and you're ready ⚡
51
+
52
+ ### 2. Generate Entities from JDL
53
+
42
54
  **Create your entity definition file using JDL:**
43
55
 
44
56
  ```bash
@@ -48,13 +60,34 @@ touch entities.jdl # or any other name of your choice
48
60
  and edit it using this guide:
49
61
  https://www.jhipster.tech/jdl/intro/
50
62
 
51
- **Run the generator:**
63
+ **Run the entities generator:**
52
64
 
53
65
  ```bash
54
- yo pninja
66
+ yo pninja:entities entities.jdl
55
67
  ```
56
68
 
57
- **Answer a few prompts** ... and you're ready
69
+ You can run this command multiple times with different JDL files:
70
+
71
+ ```bash
72
+ yo pninja:entities core-entities.jdl
73
+ yo pninja:entities additional-entities.jdl
74
+ ```
75
+
76
+ ### 3. Interactive Entity Creation (Alternative)
77
+
78
+ For incremental development or to modify entities individually, use the **entity sub-generator**:
79
+
80
+ ```bash
81
+ yo pninja:entity [EntityName]
82
+ ```
83
+
84
+ This interactive command allows you to:
85
+
86
+ - Create new entities step by step
87
+ - Add or remove fields and relationships
88
+ - Update existing entities (regenerate, add, or remove)
89
+
90
+ All entity configurations are stored in `.pninja/<EntityName>.json` files.
58
91
 
59
92
  ## What you get
60
93
 
@@ -63,6 +96,7 @@ my-app/
63
96
  ├── client/ # React + Vite app
64
97
  ├── docker/ # Docker compose
65
98
  ├── server/ # Laravel project
99
+ ├── .pninja/ # Entity configurations
66
100
  ├── package.json # With commands
67
101
  └── README.md
68
102
  ```
@@ -80,15 +114,19 @@ Fully wired together: auth, routing, forms, CRUD, migrations.
80
114
  ### Data Management
81
115
 
82
116
  - **Soft Delete Support** - Logical deletion with `deleted_at` timestamps (use `@softDelete` annotation in JDL)
83
- ```jdl
117
+
118
+ ```jdl
84
119
  @softDelete
85
120
  entity MyEntity {
86
121
  name String required
87
122
  description String
88
123
  }
89
- ```
124
+ ```
125
+
90
126
  - **CSV Database Seeding** - Populate your database from CSV files
91
127
  - **Audit Logging** - Complete change tracking for all entity modifications
128
+ - **Interactive Entity Generator** - Create and modify entities through CLI prompts
129
+ - **Incremental Migrations** - Automatic database migrations for entity changes
92
130
 
93
131
  ### Search & Indexing
94
132
 
@@ -112,13 +150,15 @@ Fully wired together: auth, routing, forms, CRUD, migrations.
112
150
  - **Responsive Design** - Mobile-first approach
113
151
  - **Tailwind CSS** - Utility-first styling
114
152
  - **Material Symbols Icons** - Associate icons to entities using `@icon` annotation in JDL
115
- ```jdl
153
+
154
+ ```jdl
116
155
  @icon("star")
117
156
  entity MyEntity {
118
157
  name String required
119
158
  description String
120
159
  }
121
- ```
160
+ ```
161
+
122
162
  - **Component Library** - Pre-built accessible components
123
163
 
124
164
  ### DevOps Ready
@@ -12,13 +12,37 @@ const __dirname = path.dirname(__filename);
12
12
  export default class extends Generator {
13
13
  constructor(args, opts) {
14
14
  super(args, opts);
15
- this.option('fromMain', {
16
- type: Boolean,
17
- default: false
15
+ this.option('name', {
16
+ type: String,
17
+ description: 'Your project name'
18
18
  });
19
+ this.option('dmbs', {
20
+ type: String,
21
+ description: 'Your DBMS'
22
+ });
23
+ this.option('authentication', {
24
+ type: String,
25
+ description: 'The type of authentication to use',
26
+ });
27
+ this.option('clientType', {
28
+ type: String,
29
+ description: 'The type of client to use',
30
+ });
31
+ this.option('nativeLanguage', {
32
+ type: String,
33
+ description: 'The native language of the application',
34
+ });
35
+ this.option('languages', {
36
+ type: String,
37
+ description: 'Additional languages to install (comma separated)',
38
+ });
39
+ this.option('searchEngine', {
40
+ type: String,
41
+ description: 'The search engine to use (database, algolia, elastic, meilisearch, typesense, solr, null)',
42
+ })
19
43
  }
20
44
  async initializing() {
21
- hello(this.log);
45
+ hello(this.log, true);
22
46
  this.log(`\n${colors.whiteBright('Application files will be generated in folder:')} ${colors.yellow(process.env.PWD)}\n`);
23
47
 
24
48
  // sub generator Auth
@@ -31,22 +55,23 @@ export default class extends Generator {
31
55
  }, {
32
56
  fromMain: true,
33
57
  env: this.env,
58
+ authentication: this.options.authentication,
34
59
  resolved: authGeneratorPath,
35
60
  namespace: 'pninja:auth'
36
61
  });
37
62
 
38
- // sub generator Entities
39
- const entitiesGeneratorPath = path.resolve(__dirname, '../entities/index.js');
40
- const { default: EntitiesGenerator } = await import(entitiesGeneratorPath);
63
+ // sub generator Server
64
+ const serverGeneratorPath = path.resolve(__dirname, '../server/index.js');
65
+ const { default: ServerGenerator } = await import(serverGeneratorPath);
41
66
 
42
67
  await this.composeWith({
43
- Generator: EntitiesGenerator,
44
- path: path.dirname(entitiesGeneratorPath)
68
+ Generator: ServerGenerator,
69
+ path: path.dirname(serverGeneratorPath)
45
70
  }, {
46
71
  fromMain: true,
47
72
  env: this.env,
48
- resolved: entitiesGeneratorPath,
49
- namespace: 'pninja:entities'
73
+ resolved: serverGeneratorPath,
74
+ namespace: 'pninja:server'
50
75
  });
51
76
 
52
77
  // sub generator Client
@@ -58,6 +83,9 @@ export default class extends Generator {
58
83
  }, {
59
84
  fromMain: true,
60
85
  env: this.env,
86
+ clientType: this.options.clientType,
87
+ nativeLanguage: this.options.nativeLanguage,
88
+ languages: this.options.languages,
61
89
  resolved: clientGeneratorPath,
62
90
  namespace: 'pninja:client'
63
91
  });
@@ -73,6 +101,7 @@ export default class extends Generator {
73
101
  fromMain: true,
74
102
  env: this.env,
75
103
  resolved: searchGeneratorPath,
104
+ searchEngine: this.options.searchEngine,
76
105
  namespace: 'pninja:search'
77
106
  });
78
107
 
@@ -105,18 +134,25 @@ export default class extends Generator {
105
134
  });
106
135
  }
107
136
  async prompting() {
137
+ if (this.options.name && this.options.dbms) {
138
+ this.answers = {
139
+ name: this.options.name,
140
+ dbms: this.options.dbms
141
+ };
142
+ return;
143
+ }
108
144
  this.answers = await this.prompt([
109
145
  {
110
146
  type: "input",
111
147
  name: "name",
112
148
  message: "Your project name",
113
- default: this.config.get('name') || this.appname // Default to current folder name
149
+ default: this.options.name || this.config.get('name') || this.appname // Default to current folder name
114
150
  }, {
115
151
  store: true,
116
152
  type: "list",
117
153
  name: "dbms",
118
154
  message: "Your DBMS",
119
- default: this.config.get('dbms') || 'sqlite',
155
+ default: this.options.dbms || this.config.get('dbms') || 'sqlite',
120
156
  choices: [
121
157
  {
122
158
  name: `SQLite ${colors.dim('(Lightweight, serverless, file-based)')}`,
@@ -1,30 +1,31 @@
1
1
  {
2
- "name": "<%= packageName %>",
3
- "description": "<%= projectDescription %>",
4
- "version": "<%= projectVersion %>",
5
- "author": "<%= authorName %>",
6
- "license": "ISC",
7
- "dependencies": {
8
- },
9
- "scripts": {
10
- "dev": "concurrently \"npm run server\" \"npm run client\"",
11
- "client": "cd client && npm i --loglevel=error && npm run dev",
12
- "dump-server": "cd server && php artisan dump-server",
13
- "migrate": "cd server && php artisan migrate",
14
- "migrate:fresh": "cd server && php artisan migrate:fresh",
15
- "migrate:fresh:seed": "cd server && php artisan migrate:fresh --seed",
16
- "migrate:seed": "cd server && php artisan migrate --seed",
17
- "db:seed": "cd server && php artisan db:seed",
2
+ "name": "<%= packageName %>",
3
+ "description": "<%= projectDescription %>",
4
+ "version": "<%= projectVersion %>",
5
+ "author": "<%= authorName %>",
6
+ "license": "ISC",
7
+ "dependencies": {},
8
+ "scripts": {
9
+ "dev": "concurrently \"npm run server\" \"npm run queue:listen\" \"npm run client\"",
10
+ "client": "cd client && npm i --loglevel=error && npm run dev",
11
+ "dump-server": "cd server && php artisan dump-server",
12
+ "migrate": "cd server && php artisan migrate",
13
+ "migrate:fresh": "cd server && php artisan migrate:fresh",
14
+ "migrate:fresh:seed": "cd server && php artisan migrate:fresh --seed",
15
+ "migrate:seed": "cd server && php artisan migrate --seed",
16
+ "db:seed": "cd server && php artisan db:seed",
18
17
  <% if (searchEngine === 'elastic') { -%>
19
- "elastic:migrate": "cd server && php artisan elastic:migrate",
20
- "elastic:migrate:reset": "cd server && php artisan elastic:migrate:reset",
21
- "elastic:migrate:refresh": "cd server && php artisan elastic:migrate:refresh",
18
+ "elastic:migrate": "cd server && php artisan elastic:migrate",
19
+ "elastic:migrate:reset": "cd server && php artisan elastic:migrate:reset",
20
+ "elastic:migrate:refresh": "cd server && php artisan elastic:migrate:refresh",
22
21
  <% } -%>
23
22
  <% if (searchEngine === 'meilisearch') { -%>
24
- "scout:sync-index-settings": "cd server && php artisan scout:sync-index-settings",
23
+ "scout:sync-index-settings": "cd server && php artisan scout:sync-index-settings",
25
24
  <% } -%>
26
- "seed": "cd server && php artisan db:seed",
27
- "server": "cd server && php artisan serve"
25
+ "seed": "cd server && php artisan db:seed",
26
+ "server": "cd server && php artisan serve",
27
+ "queue:listen": "cd server && php artisan queue:listen",
28
+ "queue:work": "cd server && php artisan queue:work"
28
29
  },
29
30
  "devDependencies": {
30
31
  "concurrently": "^9.2.1"
@@ -14,9 +14,17 @@ export default class AuthGenerator extends Generator {
14
14
  type: Boolean,
15
15
  default: false
16
16
  });
17
+ this.option('authentication', {
18
+ type: String,
19
+ description: 'The type of authentication to use',
20
+ });
17
21
  }
18
22
 
19
23
  async prompting() {
24
+ if (this.options.authentication) {
25
+ this.answers = { authentication: this.options.authentication };
26
+ return;
27
+ }
20
28
  let prompts = [];
21
29
  if (this.options["fromMain"]) {
22
30
  prompts = [...prompts, ...[{
@@ -24,6 +32,7 @@ export default class AuthGenerator extends Generator {
24
32
  type: "list",
25
33
  name: "authentication",
26
34
  message: `Which ${colors.yellow('*type*')} of authentication would you like to use?`,
35
+ default: this.options.authentication || this.config.get('authentication') || 'keycloak',
27
36
  choices: [
28
37
  { name: 'Keycloak', value: 'keycloak' },
29
38
  { name: 'Sanctum', value: 'sanctum', disabled: "Not implemented yet" },
@@ -46,9 +55,10 @@ export default class AuthGenerator extends Generator {
46
55
  return;
47
56
  }
48
57
  if (this.answers.authentication === 'keycloak') {
49
- await this.spawn('composer', ['require', 'robsontenorio/laravel-keycloak-guard'], { cwd: 'server' });
50
- await this.spawn('php', ['artisan', 'vendor:publish', '--provider="KeycloakGuard\\KeycloakGuardServiceProvider"'], { cwd: 'server' });
51
-
58
+ this.fs.copy(
59
+ this.templatePath('packages/pninja/laravel-keycloak-guard/**'),
60
+ this.destinationPath('server/packages/pninja/laravel-keycloak-guard')
61
+ );
52
62
  const envContent = this.fs.read(this.destinationPath(`server/.env`));
53
63
  this.fs.write(this.destinationPath('server/.env'), envContent + `
54
64
  FRONTEND_URL=http://localhost:5173
@@ -57,16 +67,13 @@ KEYCLOAK_BASE_URL=https://sso.yourkeycloakbaseurl.net/auth
57
67
  KEYCLOAK_REALM=yourrealm
58
68
  KEYCLOAK_CLIENT_ID=yourclientid
59
69
  KEYCLOAK_CLIENT_SECRET=yourclientsecret
60
- KEYCLOAK_REALM_PUBLIC_KEY="yourrealmpublickey"
70
+ # KEYCLOAK_REALM_PUBLIC_KEY="yourrealmpublickey"
61
71
  KEYCLOAK_LOAD_USER_FROM_DATABASE=false
62
72
  KEYCLOAK_USER_PROVIDER_CREDENTIAL=username
63
73
  KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE=preferred_username
64
74
  KEYCLOAK_IGNORE_RESOURCES_VALIDATION=true
65
75
  KEYCLOAK_USE_SERVICE_ACCOUNT=true`, { encoding: 'utf8', flag: 'w' });
66
76
 
67
- if (this.fs.exists(`${this.destinationPath('server')}/config/auth.php`)) {
68
- fs.unlinkSync(`${this.destinationPath('server')}/config/auth.php`);
69
- }
70
77
  this.fs.copyTpl(this.templatePath("keycloak.auth.php.ejs"), `${this.destinationPath('server')}/config/auth.php`);
71
78
  let bootstrapAppFileContents = fs.readFileSync(`${this.destinationPath('server')}/bootstrap/app.php`, { encoding: 'utf8', flag: 'r' });
72
79
  const regexprBootstrapAppUse = /(?=use Illuminate\\Foundation\\Application;)/gmis;
@@ -86,4 +93,17 @@ KEYCLOAK_USE_SERVICE_ACCOUNT=true`, { encoding: 'utf8', flag: 'w' });
86
93
  fs.writeFileSync(`${this.destinationPath('server')}/bootstrap/app.php`, bootstrapAppFileContents, { encoding: 'utf8', flag: 'w' });
87
94
  }
88
95
  }
96
+ async install() {
97
+ if (this.config.get('authentication') === 'keycloak') {
98
+ const composerPath = this.destinationPath('server/composer.json');
99
+ const composerContent = JSON.parse(fs.readFileSync(composerPath, { encoding: 'utf8' }));
100
+ composerContent.repositories = composerContent.repositories || [];
101
+ composerContent.repositories.push({
102
+ type: "path",
103
+ url: "./packages/pninja/laravel-keycloak-guard"
104
+ });
105
+ fs.writeFileSync(composerPath, JSON.stringify(composerContent, null, 2), { encoding: 'utf8' });
106
+ await this.spawn('composer', ['require', 'pninja/laravel-keycloak-guard:@dev'], { cwd: 'server' });
107
+ }
108
+ }
89
109
  }
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "pninja/laravel-keycloak-guard",
3
+ "description": "Keycloak JWT Guard for Laravel — without firebase/php-jwt",
4
+ "type": "library",
5
+ "license": "MIT",
6
+ "require": {
7
+ "php": "^8.2",
8
+ "ext-openssl": "*",
9
+ "lcobucci/jwt": "^5.4",
10
+ "lcobucci/clock": "^3.3",
11
+ "illuminate/auth": "^11.0",
12
+ "illuminate/support": "^11.0",
13
+ "illuminate/http": "^11.0"
14
+ },
15
+ "require-dev": {
16
+ "orchestra/testbench": "^9.0",
17
+ "pestphp/pest": "^3.0",
18
+ "phpunit/phpunit": "^11.0"
19
+ },
20
+ "autoload": {
21
+ "psr-4": {
22
+ "Pninja\\KeycloakGuard\\": "src/"
23
+ }
24
+ },
25
+ "autoload-dev": {
26
+ "psr-4": {
27
+ "Pninja\\KeycloakGuard\\Tests\\": "tests/"
28
+ }
29
+ },
30
+ "extra": {
31
+ "laravel": {
32
+ "providers": [
33
+ "Pninja\\KeycloakGuard\\KeycloakGuardServiceProvider"
34
+ ]
35
+ }
36
+ },
37
+ "minimum-stability": "stable",
38
+ "prefer-stable": true
39
+ }
@@ -0,0 +1,134 @@
1
+ <?php
2
+
3
+ return [
4
+
5
+ /*
6
+ |--------------------------------------------------------------------------
7
+ | Keycloak Server URL
8
+ |--------------------------------------------------------------------------
9
+ | Base URL of your Keycloak instance, e.g. https://keycloak.example.com
10
+ | Required when using JWKS discovery (realm_public_key left empty).
11
+ */
12
+ 'base_url' => env('KEYCLOAK_BASE_URL', ''),
13
+
14
+ /*
15
+ |--------------------------------------------------------------------------
16
+ | Keycloak Realm
17
+ |--------------------------------------------------------------------------
18
+ */
19
+ 'realm' => env('KEYCLOAK_REALM', 'master'),
20
+
21
+ /*
22
+ |--------------------------------------------------------------------------
23
+ | Realm Public Key (static)
24
+ |--------------------------------------------------------------------------
25
+ | The RS256 public key copied from:
26
+ | Realm Settings → Keys → RS256 row → Public Key button
27
+ |
28
+ | If left empty, the guard will fetch keys dynamically from the JWKS
29
+ | endpoint: {base_url}/realms/{realm}/protocol/openid-connect/certs
30
+ |
31
+ | Example (without BEGIN/END headers):
32
+ | KEYCLOAK_REALM_PUBLIC_KEY=MIIBIjANBgkqhk...
33
+ */
34
+ 'realm_public_key' => env('KEYCLOAK_REALM_PUBLIC_KEY', ''),
35
+
36
+ /*
37
+ |--------------------------------------------------------------------------
38
+ | Token Encryption Algorithm
39
+ |--------------------------------------------------------------------------
40
+ | Supported: RS256, RS384, RS512, ES256, ES384, ES512, HS256, HS384, HS512
41
+ */
42
+ 'token_encryption_algorithm' => env('KEYCLOAK_TOKEN_ENCRYPTION_ALGORITHM', 'RS256'),
43
+
44
+ /*
45
+ |--------------------------------------------------------------------------
46
+ | Load User From Database
47
+ |--------------------------------------------------------------------------
48
+ | When true the guard calls Auth::user() retrieving the user from DB.
49
+ | When false it builds a user object directly from the JWT claims.
50
+ */
51
+ 'load_user_from_database' => env('KEYCLOAK_LOAD_USER_FROM_DATABASE', true),
52
+
53
+ /*
54
+ |--------------------------------------------------------------------------
55
+ | User Provider Custom Method
56
+ |--------------------------------------------------------------------------
57
+ | When set, this method is called on the UserProvider instead of
58
+ | retrieveByCredentials(). It receives the full decoded token.
59
+ */
60
+ 'user_provider_custom_retrieve_method' => env('KEYCLOAK_USER_PROVIDER_CUSTOM_METHOD', null),
61
+
62
+ /*
63
+ |--------------------------------------------------------------------------
64
+ | User Provider Credential (DB field)
65
+ |--------------------------------------------------------------------------
66
+ | The column in your users table used to look up the user.
67
+ */
68
+ 'user_provider_credential' => env('KEYCLOAK_USER_PROVIDER_CREDENTIAL', 'username'),
69
+
70
+ /*
71
+ |--------------------------------------------------------------------------
72
+ | Token Principal Attribute (JWT claim)
73
+ |--------------------------------------------------------------------------
74
+ | The claim in the JWT token that maps to user_provider_credential.
75
+ */
76
+ 'token_principal_attribute' => env('KEYCLOAK_TOKEN_PRINCIPAL_ATTRIBUTE', 'preferred_username'),
77
+
78
+ /*
79
+ |--------------------------------------------------------------------------
80
+ | Append Decoded Token
81
+ |--------------------------------------------------------------------------
82
+ | When true the decoded token claims are appended to the user object
83
+ | as the `token` attribute.
84
+ */
85
+ 'append_decoded_token' => env('KEYCLOAK_APPEND_DECODED_TOKEN', false),
86
+
87
+ /*
88
+ |--------------------------------------------------------------------------
89
+ | Allowed Resources
90
+ |--------------------------------------------------------------------------
91
+ | Comma-separated list of Keycloak client IDs whose resource_access
92
+ | must be present in the token. Leave empty to skip resource validation.
93
+ |
94
+ | Example: KEYCLOAK_ALLOWED_RESOURCES=my-api,another-api
95
+ */
96
+ 'allowed_resources' => env('KEYCLOAK_ALLOWED_RESOURCES', ''),
97
+
98
+ /*
99
+ |--------------------------------------------------------------------------
100
+ | Ignore Resources Validation
101
+ |--------------------------------------------------------------------------
102
+ | Set to true to completely skip resource_access validation.
103
+ */
104
+ 'ignore_resources_validation' => env('KEYCLOAK_IGNORE_RESOURCES_VALIDATION', false),
105
+
106
+ /*
107
+ |--------------------------------------------------------------------------
108
+ | Leeway (seconds)
109
+ |--------------------------------------------------------------------------
110
+ | Clock skew tolerance between your server and Keycloak.
111
+ | Useful when you get "token not yet valid" / "token expired" errors.
112
+ */
113
+ 'leeway' => env('KEYCLOAK_LEEWAY', 0),
114
+
115
+ /*
116
+ |--------------------------------------------------------------------------
117
+ | Input Key
118
+ |--------------------------------------------------------------------------
119
+ | When set, the guard also looks for a token in this request parameter
120
+ | in addition to the Authorization: Bearer header.
121
+ | Example: KEYCLOAK_INPUT_KEY=api_token
122
+ */
123
+ 'input_key' => env('KEYCLOAK_INPUT_KEY', ''),
124
+
125
+ /*
126
+ |--------------------------------------------------------------------------
127
+ | JWKS Cache TTL (seconds)
128
+ |--------------------------------------------------------------------------
129
+ | How long to cache the remote JWKS response.
130
+ | Set to 0 to disable caching (not recommended in production).
131
+ */
132
+ 'jwks_cache_ttl' => env('KEYCLOAK_JWKS_CACHE_TTL', 300),
133
+
134
+ ];
@@ -0,0 +1,50 @@
1
+ <?php
2
+
3
+ declare(strict_types=1);
4
+
5
+ namespace Pninja\KeycloakGuard\Exceptions;
6
+
7
+ use Exception;
8
+
9
+ class InvalidTokenException extends Exception
10
+ {
11
+ public static function missingToken(): self
12
+ {
13
+ return new self('No token provided in request.');
14
+ }
15
+
16
+ public static function invalidSignature(): self
17
+ {
18
+ return new self('Token signature verification failed.');
19
+ }
20
+
21
+ public static function expired(): self
22
+ {
23
+ return new self('Token has expired.');
24
+ }
25
+
26
+ public static function notYetValid(): self
27
+ {
28
+ return new self('Token is not yet valid.');
29
+ }
30
+
31
+ public static function invalidResource(): self
32
+ {
33
+ return new self('Token does not contain any of the allowed resources.');
34
+ }
35
+
36
+ public static function jwksFetchFailed(string $url, string $reason): self
37
+ {
38
+ return new self("Failed to fetch JWKS from {$url}: {$reason}");
39
+ }
40
+
41
+ public static function publicKeyNotResolved(): self
42
+ {
43
+ return new self('Could not resolve a public key for the token.');
44
+ }
45
+
46
+ public static function unsupportedAlgorithm(string $alg): self
47
+ {
48
+ return new self("Unsupported token algorithm: {$alg}");
49
+ }
50
+ }