@solidxai/core 0.1.13-beta.2 → 0.1.13-beta.21

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 (517) hide show
  1. package/CHANGELOG.md +10107 -0
  2. package/CLAUDE.md +5 -6
  3. package/README.md +19 -0
  4. package/dist/commands/run-tests.command.d.ts +9 -1
  5. package/dist/commands/run-tests.command.d.ts.map +1 -1
  6. package/dist/commands/run-tests.command.js +69 -6
  7. package/dist/commands/run-tests.command.js.map +1 -1
  8. package/dist/commands/seed.command.d.ts +2 -0
  9. package/dist/commands/seed.command.d.ts.map +1 -1
  10. package/dist/commands/seed.command.js +21 -0
  11. package/dist/commands/seed.command.js.map +1 -1
  12. package/dist/config/cache.options.d.ts.map +1 -1
  13. package/dist/config/cache.options.js +2 -2
  14. package/dist/config/cache.options.js.map +1 -1
  15. package/dist/constants/chatter-message.constants.d.ts +1 -0
  16. package/dist/constants/chatter-message.constants.d.ts.map +1 -1
  17. package/dist/constants/chatter-message.constants.js +3 -1
  18. package/dist/constants/chatter-message.constants.js.map +1 -1
  19. package/dist/constants/draft-publish-fields.d.ts +2 -0
  20. package/dist/constants/draft-publish-fields.d.ts.map +1 -0
  21. package/dist/constants/draft-publish-fields.js +5 -0
  22. package/dist/constants/draft-publish-fields.js.map +1 -0
  23. package/dist/constants/error-messages.d.ts +7 -0
  24. package/dist/constants/error-messages.d.ts.map +1 -1
  25. package/dist/constants/error-messages.js +7 -0
  26. package/dist/constants/error-messages.js.map +1 -1
  27. package/dist/constants/media-file-types.d.ts +12 -0
  28. package/dist/constants/media-file-types.d.ts.map +1 -1
  29. package/dist/constants/media-file-types.js +66 -1
  30. package/dist/constants/media-file-types.js.map +1 -1
  31. package/dist/constants/success-messages.d.ts +3 -0
  32. package/dist/constants/success-messages.d.ts.map +1 -1
  33. package/dist/constants/success-messages.js +3 -0
  34. package/dist/constants/success-messages.js.map +1 -1
  35. package/dist/constants/user.constants.d.ts +2 -0
  36. package/dist/constants/user.constants.d.ts.map +1 -0
  37. package/dist/constants/user.constants.js +5 -0
  38. package/dist/constants/user.constants.js.map +1 -0
  39. package/dist/controllers/action-metadata.controller.d.ts +1 -1
  40. package/dist/controllers/action-metadata.controller.js +1 -1
  41. package/dist/controllers/agent-event.controller.d.ts +1 -1
  42. package/dist/controllers/agent-event.controller.js +1 -1
  43. package/dist/controllers/agent-session.controller.d.ts +1 -1
  44. package/dist/controllers/agent-session.controller.js +1 -1
  45. package/dist/controllers/authentication.controller.d.ts +1 -1
  46. package/dist/controllers/authentication.controller.d.ts.map +1 -1
  47. package/dist/controllers/authentication.controller.js +4 -3
  48. package/dist/controllers/authentication.controller.js.map +1 -1
  49. package/dist/controllers/chatter-message.controller.d.ts +5 -0
  50. package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
  51. package/dist/controllers/chatter-message.controller.js +14 -0
  52. package/dist/controllers/chatter-message.controller.js.map +1 -1
  53. package/dist/controllers/dashboard-user-layout.controller.d.ts +1 -1
  54. package/dist/controllers/dashboard-user-layout.controller.js +1 -1
  55. package/dist/controllers/email-template.controller.d.ts +1 -1
  56. package/dist/controllers/email-template.controller.js +1 -1
  57. package/dist/controllers/export-template.controller.d.ts +1 -1
  58. package/dist/controllers/export-template.controller.d.ts.map +1 -1
  59. package/dist/controllers/export-template.controller.js +6 -4
  60. package/dist/controllers/export-template.controller.js.map +1 -1
  61. package/dist/controllers/export-transaction.controller.d.ts +1 -1
  62. package/dist/controllers/export-transaction.controller.js +1 -1
  63. package/dist/controllers/field-metadata.controller.d.ts +2 -2
  64. package/dist/controllers/import-transaction-error-log.controller.d.ts +1 -1
  65. package/dist/controllers/import-transaction-error-log.controller.js +1 -1
  66. package/dist/controllers/import-transaction.controller.d.ts +1 -1
  67. package/dist/controllers/import-transaction.controller.d.ts.map +1 -1
  68. package/dist/controllers/import-transaction.controller.js +7 -7
  69. package/dist/controllers/import-transaction.controller.js.map +1 -1
  70. package/dist/controllers/list-of-values.controller.d.ts +1 -1
  71. package/dist/controllers/list-of-values.controller.js +1 -1
  72. package/dist/controllers/locale.controller.d.ts +1 -1
  73. package/dist/controllers/locale.controller.js +1 -1
  74. package/dist/controllers/mcp-audit-log.controller.d.ts +1 -1
  75. package/dist/controllers/mcp-audit-log.controller.js +1 -1
  76. package/dist/controllers/media.controller.d.ts +2 -2
  77. package/dist/controllers/media.controller.d.ts.map +1 -1
  78. package/dist/controllers/media.controller.js +13 -8
  79. package/dist/controllers/media.controller.js.map +1 -1
  80. package/dist/controllers/menu-item-metadata.controller.d.ts +1 -1
  81. package/dist/controllers/menu-item-metadata.controller.js +1 -1
  82. package/dist/controllers/model-sequence.controller.d.ts +1 -1
  83. package/dist/controllers/model-sequence.controller.js +1 -1
  84. package/dist/controllers/module-package.controller.d.ts.map +1 -1
  85. package/dist/controllers/module-package.controller.js +2 -3
  86. package/dist/controllers/module-package.controller.js.map +1 -1
  87. package/dist/controllers/mpin-authentication.controller.d.ts +44 -0
  88. package/dist/controllers/mpin-authentication.controller.d.ts.map +1 -0
  89. package/dist/controllers/mpin-authentication.controller.js +102 -0
  90. package/dist/controllers/mpin-authentication.controller.js.map +1 -0
  91. package/dist/controllers/mq-message-queue.controller.d.ts +1 -1
  92. package/dist/controllers/mq-message-queue.controller.js +1 -1
  93. package/dist/controllers/mq-message.controller.d.ts +1 -1
  94. package/dist/controllers/mq-message.controller.js +1 -1
  95. package/dist/controllers/permission-metadata.controller.d.ts +1 -1
  96. package/dist/controllers/permission-metadata.controller.js +1 -1
  97. package/dist/controllers/role-metadata.controller.d.ts +1 -1
  98. package/dist/controllers/role-metadata.controller.js +1 -1
  99. package/dist/controllers/saved-filters.controller.d.ts +1 -1
  100. package/dist/controllers/saved-filters.controller.js +1 -1
  101. package/dist/controllers/scheduled-job.controller.d.ts +1 -1
  102. package/dist/controllers/scheduled-job.controller.js +1 -1
  103. package/dist/controllers/security-rule.controller.d.ts +1 -1
  104. package/dist/controllers/security-rule.controller.js +1 -1
  105. package/dist/controllers/sms-template.controller.d.ts +1 -1
  106. package/dist/controllers/sms-template.controller.js +1 -1
  107. package/dist/controllers/user-activity-history.controller.d.ts +1 -1
  108. package/dist/controllers/user-activity-history.controller.js +1 -1
  109. package/dist/controllers/user-view-metadata.controller.d.ts +1 -1
  110. package/dist/controllers/user-view-metadata.controller.js +1 -1
  111. package/dist/controllers/user.controller.d.ts +2 -2
  112. package/dist/controllers/user.controller.js +2 -2
  113. package/dist/controllers/view-metadata.controller.d.ts +2 -2
  114. package/dist/controllers/view-metadata.controller.js +1 -1
  115. package/dist/controllers/workflow-definition.controller.d.ts +1 -1
  116. package/dist/controllers/workflow-definition.controller.js +1 -1
  117. package/dist/controllers/workflow-execution-artifact.controller.d.ts +1 -1
  118. package/dist/controllers/workflow-execution-artifact.controller.js +1 -1
  119. package/dist/controllers/workflow-execution-log.controller.d.ts +1 -1
  120. package/dist/controllers/workflow-execution-log.controller.js +1 -1
  121. package/dist/controllers/workflow-execution.controller.d.ts +1 -1
  122. package/dist/controllers/workflow-execution.controller.js +1 -1
  123. package/dist/controllers/workflow-secret.controller.d.ts +1 -1
  124. package/dist/controllers/workflow-secret.controller.js +1 -1
  125. package/dist/controllers/workflow-step-execution.controller.d.ts +1 -1
  126. package/dist/controllers/workflow-step-execution.controller.js +1 -1
  127. package/dist/controllers/workflow-trigger-execution.controller.d.ts +1 -1
  128. package/dist/controllers/workflow-trigger-execution.controller.js +1 -1
  129. package/dist/dtos/basic-filters.dto.d.ts +0 -1
  130. package/dist/dtos/basic-filters.dto.d.ts.map +1 -1
  131. package/dist/dtos/basic-filters.dto.js +1 -6
  132. package/dist/dtos/basic-filters.dto.js.map +1 -1
  133. package/dist/dtos/change-mpin.dto.d.ts +6 -0
  134. package/dist/dtos/change-mpin.dto.d.ts.map +1 -0
  135. package/dist/dtos/change-mpin.dto.js +39 -0
  136. package/dist/dtos/change-mpin.dto.js.map +1 -0
  137. package/dist/dtos/create-field-metadata.dto.d.ts +3 -6
  138. package/dist/dtos/create-field-metadata.dto.d.ts.map +1 -1
  139. package/dist/dtos/create-field-metadata.dto.js +15 -10
  140. package/dist/dtos/create-field-metadata.dto.js.map +1 -1
  141. package/dist/dtos/create-model-sequence.dto.d.ts +1 -1
  142. package/dist/dtos/create-model-sequence.dto.d.ts.map +1 -1
  143. package/dist/dtos/create-model-sequence.dto.js +1 -1
  144. package/dist/dtos/create-model-sequence.dto.js.map +1 -1
  145. package/dist/dtos/mpin-login.dto.d.ts +5 -0
  146. package/dist/dtos/mpin-login.dto.d.ts.map +1 -0
  147. package/dist/dtos/mpin-login.dto.js +33 -0
  148. package/dist/dtos/mpin-login.dto.js.map +1 -0
  149. package/dist/dtos/setup-mpin.dto.d.ts +7 -0
  150. package/dist/dtos/setup-mpin.dto.d.ts.map +1 -0
  151. package/dist/dtos/setup-mpin.dto.js +47 -0
  152. package/dist/dtos/setup-mpin.dto.js.map +1 -0
  153. package/dist/entities/common.entity.d.ts +4 -0
  154. package/dist/entities/common.entity.d.ts.map +1 -1
  155. package/dist/entities/common.entity.js +25 -1
  156. package/dist/entities/common.entity.js.map +1 -1
  157. package/dist/entities/dashboard-user-layout.entity.js +2 -2
  158. package/dist/entities/dashboard-user-layout.entity.js.map +1 -1
  159. package/dist/entities/field-metadata.entity.d.ts +1 -0
  160. package/dist/entities/field-metadata.entity.d.ts.map +1 -1
  161. package/dist/entities/field-metadata.entity.js +5 -1
  162. package/dist/entities/field-metadata.entity.js.map +1 -1
  163. package/dist/entities/saved-filters.entity.js +3 -3
  164. package/dist/entities/saved-filters.entity.js.map +1 -1
  165. package/dist/entities/user-device-credential.entity.d.ts +18 -0
  166. package/dist/entities/user-device-credential.entity.d.ts.map +1 -0
  167. package/dist/entities/user-device-credential.entity.js +91 -0
  168. package/dist/entities/user-device-credential.entity.js.map +1 -0
  169. package/dist/entities/user.entity.d.ts.map +1 -1
  170. package/dist/entities/user.entity.js +36 -0
  171. package/dist/entities/user.entity.js.map +1 -1
  172. package/dist/entities/view-metadata.entity.js.map +1 -1
  173. package/dist/entities/workflow-execution-artifact.entity.d.ts.map +1 -1
  174. package/dist/entities/workflow-execution-artifact.entity.js +4 -3
  175. package/dist/entities/workflow-execution-artifact.entity.js.map +1 -1
  176. package/dist/entities/workflow-execution-log.entity.d.ts.map +1 -1
  177. package/dist/entities/workflow-execution-log.entity.js +4 -3
  178. package/dist/entities/workflow-execution-log.entity.js.map +1 -1
  179. package/dist/entities/workflow-execution.entity.d.ts.map +1 -1
  180. package/dist/entities/workflow-execution.entity.js +3 -2
  181. package/dist/entities/workflow-execution.entity.js.map +1 -1
  182. package/dist/entities/workflow-secret.entity.d.ts.map +1 -1
  183. package/dist/entities/workflow-secret.entity.js +3 -2
  184. package/dist/entities/workflow-secret.entity.js.map +1 -1
  185. package/dist/entities/workflow-step-execution.entity.d.ts.map +1 -1
  186. package/dist/entities/workflow-step-execution.entity.js +3 -2
  187. package/dist/entities/workflow-step-execution.entity.js.map +1 -1
  188. package/dist/entities/workflow-trigger-execution.entity.d.ts.map +1 -1
  189. package/dist/entities/workflow-trigger-execution.entity.js +7 -6
  190. package/dist/entities/workflow-trigger-execution.entity.js.map +1 -1
  191. package/dist/factories/mail.factory.d.ts.map +1 -1
  192. package/dist/factories/mail.factory.js +4 -0
  193. package/dist/factories/mail.factory.js.map +1 -1
  194. package/dist/filters/http-exception.filter.d.ts.map +1 -1
  195. package/dist/filters/http-exception.filter.js +5 -1
  196. package/dist/filters/http-exception.filter.js.map +1 -1
  197. package/dist/helpers/bootstrap.helper.d.ts +5 -2
  198. package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
  199. package/dist/helpers/bootstrap.helper.js +7 -3
  200. package/dist/helpers/bootstrap.helper.js.map +1 -1
  201. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +7 -0
  202. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
  203. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +66 -32
  204. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
  205. package/dist/helpers/file-download.helper.d.ts +9 -0
  206. package/dist/helpers/file-download.helper.d.ts.map +1 -0
  207. package/dist/helpers/file-download.helper.js +19 -0
  208. package/dist/helpers/file-download.helper.js.map +1 -0
  209. package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
  210. package/dist/helpers/model-metadata-helper.service.js +30 -1
  211. package/dist/helpers/model-metadata-helper.service.js.map +1 -1
  212. package/dist/helpers/security.helper.d.ts +5 -1
  213. package/dist/helpers/security.helper.d.ts.map +1 -1
  214. package/dist/helpers/security.helper.js +15 -4
  215. package/dist/helpers/security.helper.js.map +1 -1
  216. package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
  217. package/dist/helpers/solid-core-error-codes-provider.service.js +45 -0
  218. package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
  219. package/dist/helpers/solid-microservice-adapter.service.d.ts.map +1 -1
  220. package/dist/helpers/solid-microservice-adapter.service.js +1 -1
  221. package/dist/helpers/solid-microservice-adapter.service.js.map +1 -1
  222. package/dist/helpers/solid-registry.js +1 -1
  223. package/dist/helpers/solid-registry.js.map +1 -1
  224. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  225. package/dist/helpers/typeorm-db-helper.js +9 -0
  226. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  227. package/dist/index.d.ts +10 -0
  228. package/dist/index.d.ts.map +1 -1
  229. package/dist/index.js +10 -0
  230. package/dist/index.js.map +1 -1
  231. package/dist/interfaces/active-user-data.interface.d.ts +1 -0
  232. package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
  233. package/dist/interfaces/active-user-data.interface.js.map +1 -1
  234. package/dist/interfaces.d.ts +1 -0
  235. package/dist/interfaces.d.ts.map +1 -1
  236. package/dist/interfaces.js.map +1 -1
  237. package/dist/repository/user-device-credential.repository.d.ts +12 -0
  238. package/dist/repository/user-device-credential.repository.d.ts.map +1 -0
  239. package/dist/repository/user-device-credential.repository.js +34 -0
  240. package/dist/repository/user-device-credential.repository.js.map +1 -0
  241. package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
  242. package/dist/seeders/module-metadata-seeder.service.js +51 -30
  243. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  244. package/dist/seeders/module-test-data.service.d.ts +3 -1
  245. package/dist/seeders/module-test-data.service.d.ts.map +1 -1
  246. package/dist/seeders/module-test-data.service.js +8 -2
  247. package/dist/seeders/module-test-data.service.js.map +1 -1
  248. package/dist/seeders/seed-data/solid-core-metadata.json +290 -78
  249. package/dist/services/api-key.service.d.ts.map +1 -1
  250. package/dist/services/api-key.service.js +1 -1
  251. package/dist/services/api-key.service.js.map +1 -1
  252. package/dist/services/authentication.service.d.ts +9 -5
  253. package/dist/services/authentication.service.d.ts.map +1 -1
  254. package/dist/services/authentication.service.js +102 -23
  255. package/dist/services/authentication.service.js.map +1 -1
  256. package/dist/services/chatter-message.service.d.ts +16 -1
  257. package/dist/services/chatter-message.service.d.ts.map +1 -1
  258. package/dist/services/chatter-message.service.js +100 -16
  259. package/dist/services/chatter-message.service.js.map +1 -1
  260. package/dist/services/crud-helper.service.d.ts +6 -4
  261. package/dist/services/crud-helper.service.d.ts.map +1 -1
  262. package/dist/services/crud-helper.service.js +32 -48
  263. package/dist/services/crud-helper.service.js.map +1 -1
  264. package/dist/services/crud.service.d.ts +13 -1
  265. package/dist/services/crud.service.d.ts.map +1 -1
  266. package/dist/services/crud.service.js +94 -68
  267. package/dist/services/crud.service.js.map +1 -1
  268. package/dist/services/datasource-introspection.service.d.ts.map +1 -1
  269. package/dist/services/datasource-introspection.service.js.map +1 -1
  270. package/dist/services/draft-publish-helper.service.d.ts +53 -0
  271. package/dist/services/draft-publish-helper.service.d.ts.map +1 -0
  272. package/dist/services/draft-publish-helper.service.js +402 -0
  273. package/dist/services/draft-publish-helper.service.js.map +1 -0
  274. package/dist/services/field-metadata.service.d.ts +2 -2
  275. package/dist/services/field-metadata.service.d.ts.map +1 -1
  276. package/dist/services/field-metadata.service.js +4 -1
  277. package/dist/services/field-metadata.service.js.map +1 -1
  278. package/dist/services/internationalisation-helper.service.d.ts +19 -0
  279. package/dist/services/internationalisation-helper.service.d.ts.map +1 -0
  280. package/dist/services/internationalisation-helper.service.js +107 -0
  281. package/dist/services/internationalisation-helper.service.js.map +1 -0
  282. package/dist/services/locale.service.d.ts +1 -1
  283. package/dist/services/media-storage.utils.d.ts +1 -0
  284. package/dist/services/media-storage.utils.d.ts.map +1 -1
  285. package/dist/services/media-storage.utils.js +12 -1
  286. package/dist/services/media-storage.utils.js.map +1 -1
  287. package/dist/services/media.service.d.ts +3 -2
  288. package/dist/services/media.service.d.ts.map +1 -1
  289. package/dist/services/media.service.js +45 -29
  290. package/dist/services/media.service.js.map +1 -1
  291. package/dist/services/metadata-validation.service.d.ts +7 -0
  292. package/dist/services/metadata-validation.service.d.ts.map +1 -0
  293. package/dist/services/metadata-validation.service.js +42 -0
  294. package/dist/services/metadata-validation.service.js.map +1 -0
  295. package/dist/services/model-metadata.service.d.ts.map +1 -1
  296. package/dist/services/model-metadata.service.js +2 -1
  297. package/dist/services/model-metadata.service.js.map +1 -1
  298. package/dist/services/module-metadata.service.d.ts.map +1 -1
  299. package/dist/services/module-metadata.service.js +9 -1
  300. package/dist/services/module-metadata.service.js.map +1 -1
  301. package/dist/services/mpin.service.d.ts +67 -0
  302. package/dist/services/mpin.service.d.ts.map +1 -0
  303. package/dist/services/mpin.service.js +282 -0
  304. package/dist/services/mpin.service.js.map +1 -0
  305. package/dist/services/object.utils.d.ts +2 -0
  306. package/dist/services/object.utils.d.ts.map +1 -0
  307. package/dist/services/object.utils.js +11 -0
  308. package/dist/services/object.utils.js.map +1 -0
  309. package/dist/services/refresh-token-ids-storage.service.d.ts +25 -6
  310. package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
  311. package/dist/services/refresh-token-ids-storage.service.js +80 -42
  312. package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
  313. package/dist/services/setting.service.d.ts.map +1 -1
  314. package/dist/services/setting.service.js +6 -1
  315. package/dist/services/setting.service.js.map +1 -1
  316. package/dist/services/settings/default-settings-provider.service.d.ts +248 -12
  317. package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
  318. package/dist/services/settings/default-settings-provider.service.js +143 -6
  319. package/dist/services/settings/default-settings-provider.service.js.map +1 -1
  320. package/dist/services/user.service.d.ts +2 -2
  321. package/dist/services/user.service.d.ts.map +1 -1
  322. package/dist/services/user.service.js +9 -3
  323. package/dist/services/user.service.js.map +1 -1
  324. package/dist/services/view-metadata.service.d.ts +1 -2
  325. package/dist/services/view-metadata.service.d.ts.map +1 -1
  326. package/dist/services/view-metadata.service.js +3 -55
  327. package/dist/services/view-metadata.service.js.map +1 -1
  328. package/dist/services/workflow/nodes/execution-fail.node.d.ts +6 -0
  329. package/dist/services/workflow/nodes/execution-fail.node.d.ts.map +1 -0
  330. package/dist/services/workflow/nodes/execution-fail.node.js +81 -0
  331. package/dist/services/workflow/nodes/execution-fail.node.js.map +1 -0
  332. package/dist/services/workflow/nodes/for-each.node.d.ts +2 -0
  333. package/dist/services/workflow/nodes/for-each.node.d.ts.map +1 -1
  334. package/dist/services/workflow/nodes/for-each.node.js +114 -5
  335. package/dist/services/workflow/nodes/for-each.node.js.map +1 -1
  336. package/dist/services/workflow/nodes/if.node.d.ts.map +1 -1
  337. package/dist/services/workflow/nodes/if.node.js +7 -0
  338. package/dist/services/workflow/nodes/if.node.js.map +1 -1
  339. package/dist/services/workflow/nodes/log-write.node.d.ts.map +1 -1
  340. package/dist/services/workflow/nodes/log-write.node.js +2 -0
  341. package/dist/services/workflow/nodes/log-write.node.js.map +1 -1
  342. package/dist/services/workflow/nodes/loop-until.node.d.ts +12 -0
  343. package/dist/services/workflow/nodes/loop-until.node.d.ts.map +1 -0
  344. package/dist/services/workflow/nodes/loop-until.node.js +281 -0
  345. package/dist/services/workflow/nodes/loop-until.node.js.map +1 -0
  346. package/dist/services/workflow/nodes/parallel.node.d.ts.map +1 -1
  347. package/dist/services/workflow/nodes/parallel.node.js +7 -0
  348. package/dist/services/workflow/nodes/parallel.node.js.map +1 -1
  349. package/dist/services/workflow/nodes/sequential.node.d.ts.map +1 -1
  350. package/dist/services/workflow/nodes/sequential.node.js +7 -0
  351. package/dist/services/workflow/nodes/sequential.node.js.map +1 -1
  352. package/dist/services/workflow/nodes/switch.node.d.ts.map +1 -1
  353. package/dist/services/workflow/nodes/switch.node.js +7 -0
  354. package/dist/services/workflow/nodes/switch.node.js.map +1 -1
  355. package/dist/services/workflow/workflow-definition-validator.service.d.ts.map +1 -1
  356. package/dist/services/workflow/workflow-definition-validator.service.js +5 -2
  357. package/dist/services/workflow/workflow-definition-validator.service.js.map +1 -1
  358. package/dist/services/workflow/workflow-expression.service.d.ts.map +1 -1
  359. package/dist/services/workflow/workflow-expression.service.js +5 -0
  360. package/dist/services/workflow/workflow-expression.service.js.map +1 -1
  361. package/dist/services/workflow/workflow-node-registry.service.d.ts +2 -1
  362. package/dist/services/workflow/workflow-node-registry.service.d.ts.map +1 -1
  363. package/dist/services/workflow/workflow-node-registry.service.js +7 -0
  364. package/dist/services/workflow/workflow-node-registry.service.js.map +1 -1
  365. package/dist/services/workflow/workflow-runtime.service.d.ts +8 -0
  366. package/dist/services/workflow/workflow-runtime.service.d.ts.map +1 -1
  367. package/dist/services/workflow/workflow-runtime.service.js +197 -32
  368. package/dist/services/workflow/workflow-runtime.service.js.map +1 -1
  369. package/dist/services/workflow-definition.service.d.ts +1 -1
  370. package/dist/solid-core.module.d.ts +1 -3
  371. package/dist/solid-core.module.d.ts.map +1 -1
  372. package/dist/solid-core.module.js +28 -40
  373. package/dist/solid-core.module.js.map +1 -1
  374. package/dist/testing/adapters/ui/playwright-adapter.d.ts +5 -0
  375. package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -1
  376. package/dist/testing/adapters/ui/playwright-adapter.js +17 -1
  377. package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -1
  378. package/dist/testing/adapters/ui/ui.types.d.ts +2 -0
  379. package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -1
  380. package/dist/testing/adapters/ui/ui.types.js.map +1 -1
  381. package/dist/testing/reporter/console-reporter.d.ts +3 -0
  382. package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
  383. package/dist/testing/reporter/console-reporter.js +2 -0
  384. package/dist/testing/reporter/console-reporter.js.map +1 -1
  385. package/dist/testing/reporter/progress-reporter.d.ts +64 -0
  386. package/dist/testing/reporter/progress-reporter.d.ts.map +1 -0
  387. package/dist/testing/reporter/progress-reporter.js +224 -0
  388. package/dist/testing/reporter/progress-reporter.js.map +1 -0
  389. package/dist/testing/reporter/reporter.types.d.ts +3 -0
  390. package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
  391. package/dist/testing/reporter/reporter.types.js.map +1 -1
  392. package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
  393. package/dist/testing/runner/run-from-metadata.js +1 -0
  394. package/dist/testing/runner/run-from-metadata.js.map +1 -1
  395. package/dist/testing/steps/ui/actions.step.d.ts.map +1 -1
  396. package/dist/testing/steps/ui/actions.step.js +6 -2
  397. package/dist/testing/steps/ui/actions.step.js.map +1 -1
  398. package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -1
  399. package/dist/testing/steps/ui/assertions.step.js +11 -3
  400. package/dist/testing/steps/ui/assertions.step.js.map +1 -1
  401. package/dist/testing/steps/ui/form.step.d.ts.map +1 -1
  402. package/dist/testing/steps/ui/form.step.js +9 -3
  403. package/dist/testing/steps/ui/form.step.js.map +1 -1
  404. package/dist/testing/steps/ui/manual.step.js +1 -1
  405. package/dist/testing/steps/ui/manual.step.js.map +1 -1
  406. package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -1
  407. package/dist/testing/steps/ui/navigation.step.js +3 -1
  408. package/dist/testing/steps/ui/navigation.step.js.map +1 -1
  409. package/dist/theme/theme-registry.d.ts +14 -0
  410. package/dist/theme/theme-registry.d.ts.map +1 -0
  411. package/dist/theme/theme-registry.js +147 -0
  412. package/dist/theme/theme-registry.js.map +1 -0
  413. package/dist/types/workflow-dsl.types.d.ts +14 -0
  414. package/dist/types/workflow-dsl.types.d.ts.map +1 -1
  415. package/dist/types/workflow-dsl.types.js.map +1 -1
  416. package/package.json +2 -2
  417. package/src/commands/run-tests.command.ts +64 -4
  418. package/src/commands/seed.command.ts +19 -0
  419. package/src/config/cache.options.ts +9 -1
  420. package/src/constants/chatter-message.constants.ts +12 -0
  421. package/src/constants/draft-publish-fields.ts +5 -0
  422. package/src/constants/error-messages.ts +14 -0
  423. package/src/constants/media-file-types.ts +128 -0
  424. package/src/constants/success-messages.ts +5 -0
  425. package/src/constants/user.constants.ts +13 -0
  426. package/src/controllers/authentication.controller.ts +5 -2
  427. package/src/controllers/chatter-message.controller.ts +8 -0
  428. package/src/controllers/export-template.controller.ts +5 -3
  429. package/src/controllers/import-transaction.controller.ts +6 -6
  430. package/src/controllers/media.controller.ts +17 -6
  431. package/src/controllers/module-package.controller.ts +2 -3
  432. package/src/controllers/mpin-authentication.controller.ts +67 -0
  433. package/src/dtos/basic-filters.dto.ts +0 -4
  434. package/src/dtos/change-mpin.dto.ts +18 -0
  435. package/src/dtos/create-field-metadata.dto.ts +17 -9
  436. package/src/dtos/create-model-sequence.dto.ts +1 -1
  437. package/src/dtos/mpin-login.dto.ts +24 -0
  438. package/src/dtos/setup-mpin.dto.ts +51 -0
  439. package/src/entities/common.entity.ts +24 -0
  440. package/src/entities/dashboard-user-layout.entity.ts +2 -2
  441. package/src/entities/field-metadata.entity.ts +3 -0
  442. package/src/entities/saved-filters.entity.ts +3 -3
  443. package/src/entities/user-device-credential.entity.ts +130 -0
  444. package/src/entities/user.entity.ts +53 -36
  445. package/src/entities/view-metadata.entity.ts +2 -2
  446. package/src/entities/workflow-execution-artifact.entity.ts +4 -3
  447. package/src/entities/workflow-execution-log.entity.ts +4 -3
  448. package/src/entities/workflow-execution.entity.ts +3 -2
  449. package/src/entities/workflow-secret.entity.ts +3 -2
  450. package/src/entities/workflow-step-execution.entity.ts +3 -2
  451. package/src/entities/workflow-trigger-execution.entity.ts +7 -6
  452. package/src/factories/mail.factory.ts +7 -1
  453. package/src/filters/http-exception.filter.ts +11 -1
  454. package/src/helpers/bootstrap.helper.ts +43 -6
  455. package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +90 -37
  456. package/src/helpers/file-download.helper.ts +45 -0
  457. package/src/helpers/model-metadata-helper.service.ts +32 -1
  458. package/src/helpers/security.helper.ts +35 -8
  459. package/src/helpers/solid-core-error-codes-provider.service.ts +53 -0
  460. package/src/helpers/solid-microservice-adapter.service.ts +6 -1
  461. package/src/helpers/solid-registry.ts +1 -1
  462. package/src/helpers/typeorm-db-helper.ts +12 -1
  463. package/src/index.ts +10 -0
  464. package/src/interfaces/active-user-data.interface.ts +9 -0
  465. package/src/interfaces.ts +1 -0
  466. package/src/repository/user-device-credential.repository.ts +17 -0
  467. package/src/seeders/module-metadata-seeder.service.ts +61 -39
  468. package/src/seeders/module-test-data.service.ts +6 -0
  469. package/src/seeders/seed-data/solid-core-metadata.json +290 -78
  470. package/src/services/api-key.service.ts +13 -1
  471. package/src/services/authentication.service.ts +203 -41
  472. package/src/services/chatter-message.service.ts +180 -19
  473. package/src/services/crud-helper.service.ts +35 -50
  474. package/src/services/crud.service.ts +132 -105
  475. package/src/services/datasource-introspection.service.ts +5 -0
  476. package/src/services/draft-publish-helper.service.ts +581 -0
  477. package/src/services/field-metadata.service.ts +5 -2
  478. package/src/services/internationalisation-helper.service.ts +148 -0
  479. package/src/services/media-storage.utils.ts +26 -1
  480. package/src/services/media.service.ts +68 -36
  481. package/src/services/metadata-validation.service.ts +39 -0
  482. package/src/services/model-metadata.service.ts +4 -1
  483. package/src/services/module-metadata.service.ts +10 -1
  484. package/src/services/mpin.service.ts +447 -0
  485. package/src/services/object.utils.ts +10 -0
  486. package/src/services/refresh-token-ids-storage.service.ts +229 -90
  487. package/src/services/setting.service.ts +8 -1
  488. package/src/services/settings/default-settings-provider.service.ts +154 -6
  489. package/src/services/user.service.ts +18 -3
  490. package/src/services/view-metadata.service.ts +5 -145
  491. package/src/services/workflow/nodes/execution-fail.node.ts +82 -0
  492. package/src/services/workflow/nodes/for-each.node.ts +140 -6
  493. package/src/services/workflow/nodes/if.node.ts +7 -0
  494. package/src/services/workflow/nodes/log-write.node.ts +2 -0
  495. package/src/services/workflow/nodes/loop-until.node.ts +343 -0
  496. package/src/services/workflow/nodes/parallel.node.ts +7 -0
  497. package/src/services/workflow/nodes/sequential.node.ts +7 -0
  498. package/src/services/workflow/nodes/switch.node.ts +7 -0
  499. package/src/services/workflow/workflow-definition-validator.service.ts +5 -2
  500. package/src/services/workflow/workflow-expression.service.ts +5 -0
  501. package/src/services/workflow/workflow-node-registry.service.ts +11 -0
  502. package/src/services/workflow/workflow-runtime.service.ts +274 -39
  503. package/src/solid-core.module.ts +46 -15
  504. package/src/testing/README.md +75 -3
  505. package/src/testing/adapters/ui/playwright-adapter.ts +25 -0
  506. package/src/testing/adapters/ui/ui.types.ts +2 -0
  507. package/src/testing/reporter/console-reporter.ts +4 -0
  508. package/src/testing/reporter/progress-reporter.ts +251 -0
  509. package/src/testing/reporter/reporter.types.ts +3 -0
  510. package/src/testing/runner/run-from-metadata.ts +1 -0
  511. package/src/testing/steps/ui/actions.step.ts +8 -4
  512. package/src/testing/steps/ui/assertions.step.ts +18 -5
  513. package/src/testing/steps/ui/form.step.ts +16 -6
  514. package/src/testing/steps/ui/manual.step.ts +1 -1
  515. package/src/testing/steps/ui/navigation.step.ts +4 -2
  516. package/src/theme/theme-registry.ts +181 -0
  517. package/src/types/workflow-dsl.types.ts +43 -0
@@ -8,6 +8,7 @@ import { Response } from 'express';
8
8
  import { StartExportSyncDto } from 'src/dtos/export.dto';
9
9
  import { ActiveUser } from 'src/decorators/active-user.decorator';
10
10
  import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
11
+ import { setFileDownloadHeaders } from 'src/helpers/file-download.helper';
11
12
 
12
13
  @ApiTags('Solid Core')
13
14
  @Controller('export-template') //FIXME: Change this to the model plural name
@@ -91,9 +92,10 @@ export class ExportTemplateController {
91
92
  throw new InternalServerErrorException("Export stream is null");
92
93
  }
93
94
  // ✅ Set response headers for streaming
94
- res.setHeader('Content-Disposition', `attachment; filename="${exportFileInfo.fileName}"`);
95
- res.setHeader('Content-Type', exportFileInfo.mimeType);
96
- res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition, Content-Type');
95
+ setFileDownloadHeaders(res, {
96
+ fileName: exportFileInfo.fileName,
97
+ mimeType: exportFileInfo.mimeType,
98
+ });
97
99
  // Pipe the strea to the response as an excel file
98
100
  exportFileInfo.exportStream.pipe(res);
99
101
  }
@@ -7,6 +7,7 @@ import { UpdateImportTransactionDto } from '../dtos/update-import-transaction.dt
7
7
  import { Response } from 'express';
8
8
  import { ActiveUser } from 'src/decorators/active-user.decorator';
9
9
  import { ActiveUserData } from 'src/interfaces/active-user-data.interface';
10
+ import { setFileDownloadHeaders } from 'src/helpers/file-download.helper';
10
11
 
11
12
  enum ShowSoftDeleted {
12
13
  INCLUSIVE = "inclusive",
@@ -27,9 +28,10 @@ export class ImportTransactionController {
27
28
  }
28
29
 
29
30
  // ✅ Set response headers for streaming
30
- res.setHeader('Content-Disposition', `attachment; filename="${importTemplateFileInfo.fileName}"`);
31
- res.setHeader('Content-Type', importTemplateFileInfo.mimeType);
32
- res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition, Content-Type');
31
+ setFileDownloadHeaders(res, {
32
+ fileName: importTemplateFileInfo.fileName,
33
+ mimeType: importTemplateFileInfo.mimeType,
34
+ });
33
35
  // Pipe the stream to the response as an excel file
34
36
  importTemplateFileInfo.stream.pipe(res);
35
37
  }
@@ -117,9 +119,7 @@ export class ImportTransactionController {
117
119
  throw new InternalServerErrorException("Failed records stream is null");
118
120
  }
119
121
  // ✅ Set response headers for streaming
120
- res.setHeader('Content-Disposition', `attachment; filename="${fileName}"`);
121
- res.setHeader('Content-Type', mimeType);
122
- res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition, Content-Type');
122
+ setFileDownloadHeaders(res, { fileName, mimeType });
123
123
  // Pipe the strea to the response as an excel file
124
124
  stream.pipe(res);
125
125
  }
@@ -9,6 +9,8 @@ import { SolidRequestContextDto } from 'src/dtos/solid-request-context.dto';
9
9
  import { UpdateMediaDto } from 'src/dtos/update-media.dto';
10
10
  import { MediaService } from 'src/services/media.service';
11
11
  import { Response } from 'express';
12
+ import { getLowercaseFileExtension, INLINE_SAFE_EXTENSIONS } from 'src/constants/media-file-types';
13
+ import { setFileDownloadHeaders } from 'src/helpers/file-download.helper';
12
14
 
13
15
  enum ShowSoftDeleted {
14
16
  INCLUSIVE = "inclusive",
@@ -91,17 +93,26 @@ export class MediaController {
91
93
 
92
94
  @Auth(AuthType.MediaSignedUrl)
93
95
  @ApiQuery({ name: 'token', required: true, type: String, description: "Short-lived signed token obtained from a private Media record's URL - not entered manually." })
94
- @ApiQuery({ name: 'disposition', required: false, enum: ['inline', 'attachment'], description: "'inline' (default) renders/previews in the browser, matching public media. Pass 'attachment' to force a browser download (e.g. from a download button)." })
96
+ @ApiQuery({ name: 'disposition', required: false, enum: ['inline', 'attachment'], description: "'inline' (default) renders/previews in the browser, matching public media - it applies only to types safe to render inline (images, audio, video, pdf); anything else is always downloaded. Pass 'attachment' to force a browser download (e.g. from a download button)." })
95
97
  @Get(':id/download')
96
98
  async download(@Param('id') id: string, @Query('disposition') disposition: string, @Res() res: Response, @SolidRequestContextDecorator() solidRequestContext: SolidRequestContextDto) {
97
99
  const media = await this.service.findOne(+id, {}, solidRequestContext);
98
100
  const { stream, fileName, mimeType } = await this.service.fileDownloadStream(media);
99
101
 
100
- const contentDisposition = disposition === 'attachment' ? 'attachment' : 'inline';
101
- res.setHeader('Content-Disposition', `${contentDisposition}; filename="${fileName}"`);
102
- res.setHeader('Content-Type', mimeType);
103
- res.setHeader('Cross-Origin-Resource-Policy', 'cross-origin');
104
- res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition, Content-Type');
102
+ // Mirror the static-serve hardening in SolidCoreModule: only a small allowlist of media
103
+ // types is ever safe to render inline. Anything else is forced to download rather than be
104
+ // displayed/executed, regardless of the mimetype the record was stored with - nosniff
105
+ // alone would not help here, since it faithfully honours a declared text/html.
106
+ const isInlineSafe = INLINE_SAFE_EXTENSIONS.has(getLowercaseFileExtension(fileName) ?? '');
107
+ const requestedInline = disposition !== 'attachment';
108
+
109
+ setFileDownloadHeaders(res, {
110
+ fileName,
111
+ mimeType: isInlineSafe ? mimeType : 'application/octet-stream',
112
+ disposition: requestedInline && isInlineSafe ? 'inline' : 'attachment',
113
+ crossOriginResourcePolicy: true,
114
+ });
115
+
105
116
  stream.pipe(res);
106
117
  }
107
118
 
@@ -13,6 +13,7 @@ import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
13
13
  import { Response } from 'express';
14
14
  import { ConfirmModulePackageImportDto } from 'src/dtos/confirm-module-package-import.dto';
15
15
  import { RunModulePackageBuildDto } from 'src/dtos/run-module-package-build.dto';
16
+ import { setFileDownloadHeaders } from 'src/helpers/file-download.helper';
16
17
  import { RunModulePackageSeedDto } from 'src/dtos/run-module-package-seed.dto';
17
18
  import { ModulePackageService } from 'src/services/module-package.service';
18
19
 
@@ -39,9 +40,7 @@ export class ModulePackageController {
39
40
  @Res() res: Response,
40
41
  ) {
41
42
  const archive = await this.modulePackageService.exportModulePackage(moduleName);
42
- res.setHeader('Content-Disposition', `attachment; filename="${archive.fileName}"`);
43
- res.setHeader('Content-Type', archive.mimeType);
44
- res.setHeader('Access-Control-Expose-Headers', 'Content-Disposition, Content-Type');
43
+ setFileDownloadHeaders(res, { fileName: archive.fileName, mimeType: archive.mimeType });
45
44
  res.sendFile(archive.filePath);
46
45
  }
47
46
 
@@ -0,0 +1,67 @@
1
+ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, ParseIntPipe, Post } from '@nestjs/common';
2
+ import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
3
+ import { ActiveUser } from '../decorators/active-user.decorator';
4
+ import { Public } from '../decorators/public.decorator';
5
+ import { ChangeMpinDto } from '../dtos/change-mpin.dto';
6
+ import { MpinLoginDto } from '../dtos/mpin-login.dto';
7
+ import { SetupMpinDto } from '../dtos/setup-mpin.dto';
8
+ import { ActiveUserData } from '../interfaces/active-user-data.interface';
9
+ import { MpinService } from '../services/mpin.service';
10
+
11
+ /**
12
+ * There is deliberately no public "is MPIN set up for this identifier" route.
13
+ * That would reintroduce exactly the user-enumeration oracle the opaque
14
+ * credential handle removes. The client decides whether to show the MPIN
15
+ * screen from the presence of its own stored handle.
16
+ */
17
+ @Controller('iam/mpin')
18
+ @ApiTags('Solid Core')
19
+ export class MpinAuthenticationController {
20
+ constructor(private readonly mpinService: MpinService) { }
21
+
22
+ @ApiBearerAuth('jwt')
23
+ @Post('setup')
24
+ @HttpCode(HttpStatus.OK)
25
+ setup(
26
+ @Body() setupMpinDto: SetupMpinDto,
27
+ @ActiveUser() activeUser: ActiveUserData,
28
+ ) {
29
+ return this.mpinService.setupMpin(activeUser, setupMpinDto);
30
+ }
31
+
32
+ @ApiBearerAuth('jwt')
33
+ @Post('change')
34
+ @HttpCode(HttpStatus.OK)
35
+ change(
36
+ @Body() changeMpinDto: ChangeMpinDto,
37
+ @ActiveUser() activeUser: ActiveUserData,
38
+ ) {
39
+ return this.mpinService.changeMpin(activeUser, changeMpinDto);
40
+ }
41
+
42
+ // Public by necessity - the caller has no session yet. The credential
43
+ // handle is unguessable, so this carries no enumeration surface.
44
+ @Public()
45
+ @Post('login')
46
+ @HttpCode(HttpStatus.OK)
47
+ login(@Body() mpinLoginDto: MpinLoginDto) {
48
+ return this.mpinService.loginWithMpin(mpinLoginDto);
49
+ }
50
+
51
+ @ApiBearerAuth('jwt')
52
+ @Get('devices')
53
+ listDevices(@ActiveUser() activeUser: ActiveUserData) {
54
+ return this.mpinService.listDevices(activeUser);
55
+ }
56
+
57
+ // By row id, never by credential handle, so the management UI never has to
58
+ // hold the secret.
59
+ @ApiBearerAuth('jwt')
60
+ @Delete('devices/:id')
61
+ revokeDevice(
62
+ @Param('id', ParseIntPipe) id: number,
63
+ @ActiveUser() activeUser: ActiveUserData,
64
+ ) {
65
+ return this.mpinService.revokeDevice(activeUser, id);
66
+ }
67
+ }
@@ -60,10 +60,6 @@ export class BasicFilterDto extends PaginationQueryDto {
60
60
  @ApiProperty({ description: "locale" })
61
61
  readonly locale?: string;
62
62
 
63
- @IsOptional()
64
- @ApiProperty({ description: "status publish draft" })
65
- readonly status?: string;
66
-
67
63
  // @IsOptional()
68
64
  // @ApiProperty({ description: "default locale id" })
69
65
  // readonly defaultEntityLocaleId?: number;
@@ -0,0 +1,18 @@
1
+ import { IsNotEmpty, IsString, MaxLength } from 'class-validator';
2
+
3
+ export class ChangeMpinDto {
4
+ @IsNotEmpty()
5
+ @IsString()
6
+ @MaxLength(128)
7
+ credentialRef: string;
8
+
9
+ @IsNotEmpty()
10
+ @IsString()
11
+ @MaxLength(32)
12
+ currentMpin: string;
13
+
14
+ @IsNotEmpty()
15
+ @IsString()
16
+ @MaxLength(32)
17
+ newMpin: string;
18
+ }
@@ -1,5 +1,6 @@
1
1
  import { ApiProperty } from '@nestjs/swagger';
2
2
  import { Transform, Type } from 'class-transformer';
3
+ import { DANGEROUS_EXTENSIONS, MEDIA_CATEGORIES, MediaCategory } from '../constants/media-file-types';
3
4
 
4
5
  import {
5
6
  IsArray,
@@ -7,6 +8,7 @@ import {
7
8
  IsEnum,
8
9
  IsIn,
9
10
  IsInt,
11
+ IsNotIn,
10
12
  IsOptional,
11
13
  IsString,
12
14
  Matches,
@@ -155,13 +157,7 @@ export enum DecryptWhenType {
155
157
  afterTransit = 'after-transit',
156
158
  }
157
159
 
158
- export enum MediaType {
159
- image = 'image',
160
- audio = 'audio',
161
- video = 'video',
162
- // document = 'document',
163
- file = 'file',
164
- }
160
+ export type MediaType = MediaCategory;
165
161
 
166
162
  export enum RelationType {
167
163
  manyToOne = 'many-to-one',
@@ -308,7 +304,7 @@ export class CreateFieldMetadataDto {
308
304
  private: boolean;
309
305
 
310
306
  @ApiProperty({ description: 'Allowed media types for the field. Only for type=mediaSingle,mediaMultiple', })
311
- @IsEnum(MediaType, { each: true })
307
+ @IsIn([...MEDIA_CATEGORIES], { each: true })
312
308
  @IsOptional()
313
309
  mediaTypes: MediaType[];
314
310
 
@@ -317,6 +313,18 @@ export class CreateFieldMetadataDto {
317
313
  @IsOptional()
318
314
  mediaMaxSizeKb: number;
319
315
 
316
+ @ApiProperty({ description: 'Explicit allowlist of file extensions (e.g. ["pdf","xlsx","png"]) permitted for this field, checked in addition to any mediaTypes category restriction — both must pass if both are set. For a strict allowlist, leave mediaTypes empty and use this alone. Only for type=mediaSingle,mediaMultiple', })
317
+ @Transform(({ value }) =>
318
+ Array.isArray(value)
319
+ ? value.map((ext: any) => String(ext).toLowerCase().trim().replace(/^\./, ''))
320
+ : value
321
+ )
322
+ @IsArray()
323
+ @IsString({ each: true })
324
+ @IsNotIn([...DANGEROUS_EXTENSIONS], { each: true })
325
+ @IsOptional()
326
+ mediaAllowedExtensions?: string[];
327
+
320
328
  @ApiProperty({ description: 'Configured Media storage provider. Only for type=mediaSingle,mediaMultiple', })
321
329
  @IsInt()
322
330
  @IsOptional()
@@ -464,4 +472,4 @@ export class CreateFieldMetadataDto {
464
472
  @ApiProperty({ description: 'Is Primary Key Field', })
465
473
  @IsBoolean()
466
474
  isPrimaryKey?: boolean;
467
- }
475
+ }
@@ -35,7 +35,7 @@ export class CreateModelSequenceDto {
35
35
  @IsOptional()
36
36
  @IsInt()
37
37
  @ApiProperty()
38
- currentValue: number;
38
+ currentValue?: number;
39
39
  @IsOptional()
40
40
  @IsString()
41
41
  @ApiProperty()
@@ -0,0 +1,24 @@
1
+ import { IsNotEmpty, IsString, MaxLength } from 'class-validator';
2
+
3
+ /**
4
+ * Deliberately carries no identifier - no mobile, email or username.
5
+ *
6
+ * `credentialRef` is a server-issued 256-bit handle that already points at a
7
+ * single credential row, and therefore at a single user. That is what removes
8
+ * the user-enumeration surface a public login route would otherwise have: an
9
+ * attacker cannot probe "does this phone number have MPIN?" because there is
10
+ * nowhere to put a phone number.
11
+ */
12
+ export class MpinLoginDto {
13
+ // Bounded so a pathological payload never reaches the regex test or the
14
+ // hash comparison. The handle is always 64 hex characters.
15
+ @IsNotEmpty()
16
+ @IsString()
17
+ @MaxLength(128)
18
+ credentialRef: string;
19
+
20
+ @IsNotEmpty()
21
+ @IsString()
22
+ @MaxLength(32)
23
+ mpin: string;
24
+ }
@@ -0,0 +1,51 @@
1
+ import { IsNotEmpty, IsOptional, IsString, IsUUID, Matches, MaxLength } from 'class-validator';
2
+
3
+ export class SetupMpinDto {
4
+ /**
5
+ * Stable identifier for the physical device, generated once by the client.
6
+ * Validated as a UUID before it ever reaches a cache key or a bucket name,
7
+ * so it cannot smuggle delimiters into the keyspace.
8
+ */
9
+ @IsUUID()
10
+ deviceId: string;
11
+
12
+ /**
13
+ * A string, not a number, even though it looks like digits.
14
+ *
15
+ * A numeric MPIN cannot carry a leading zero: JSON forbids leading zeros in
16
+ * number literals, so a client serialising `012345` numerically emits
17
+ * `12345` and the server stores a five-digit MPIN the user never chose -
18
+ * which still satisfies the default `^\d{4,6}$` and so raises no error.
19
+ * `mpinRegex` is also tenant-configurable and may permit non-digits.
20
+ *
21
+ * Note this cannot be enforced here: the global ValidationPipe runs with
22
+ * `enableImplicitConversion`, so a numeric payload is coerced to a string
23
+ * before @IsString() sees it. Clients must send a quoted JSON string; that
24
+ * requirement is documented in the mobile integration guide.
25
+ *
26
+ * Length and shape are checked server-side against `mpinRegex`, since that
27
+ * setting is the single authority. This only bounds the input.
28
+ */
29
+ @IsNotEmpty()
30
+ @IsString()
31
+ @MaxLength(32)
32
+ mpin: string;
33
+
34
+ /**
35
+ * Rendered in a device-management list, so it is bounded here rather than
36
+ * trusting every consuming UI to escape it.
37
+ */
38
+ @IsOptional()
39
+ @IsString()
40
+ @MaxLength(64)
41
+ @Matches(/^[\w\s.'()-]*$/, {
42
+ message: 'deviceName may contain only letters, numbers, spaces and . \' ( ) - _',
43
+ })
44
+ deviceName?: string;
45
+
46
+ @IsOptional()
47
+ @IsString()
48
+ @MaxLength(32)
49
+ @Matches(/^[\w.-]*$/, { message: 'platform may contain only letters, numbers and . - _' })
50
+ platform?: string;
51
+ }
@@ -25,6 +25,30 @@ export abstract class CommonEntity {
25
25
  @Column({ name: 'published_at', default: null, nullable: true, transformer: LocalDateTimeTransformer })
26
26
  publishedAt: Date;
27
27
 
28
+ // Optional (not just nullable) because legacy tables (see LegacyCommonEntityWithExistingId)
29
+ // don't carry these versioning columns at all. CRUDService<T extends CommonEntity> is
30
+ // otherwise used for both plain and legacy entities, so these must stay structurally
31
+ // satisfiable by a type that never declares them.
32
+ @Expose()
33
+ @Column({ name: 'is_published', default: false })
34
+ @Index()
35
+ isPublished?: boolean;
36
+
37
+ @Expose()
38
+ @Column({ name: 'is_latest', default: true })
39
+ @Index()
40
+ isLatest?: boolean;
41
+
42
+ @Expose()
43
+ @Column({ type: "int", name: 'initial_entity_version_id', default: null, nullable: true })
44
+ @Index()
45
+ initialEntityVersionId?: number;
46
+
47
+ @Expose()
48
+ @Column({ name: 'published_tracker', default: "na" })
49
+ @Index()
50
+ publishedTracker?: string;
51
+
28
52
  @Expose()
29
53
  @Column({ type: "varchar", name: 'locale_name', default: null })
30
54
  localeName: string;
@@ -6,12 +6,12 @@ import { ModuleMetadata } from 'src/entities/module-metadata.entity'
6
6
  @Entity('ss_dashboard_user_layout')
7
7
  export class DashboardUserLayout extends CommonEntity {
8
8
  @Index()
9
- @ManyToOne(() => User, { onDelete: "CASCADE", nullable: false })
9
+ @ManyToOne(() => User, { nullable: false })
10
10
  @JoinColumn()
11
11
  user: User;
12
12
 
13
13
  @Index()
14
- @ManyToOne(() => ModuleMetadata, { onDelete: "CASCADE", nullable: false })
14
+ @ManyToOne(() => ModuleMetadata, { nullable: false })
15
15
  @JoinColumn()
16
16
  module: ModuleMetadata;
17
17
 
@@ -77,6 +77,9 @@ export class FieldMetadata extends CommonEntity {
77
77
  @Column({ name: 'media_max_size_kb', nullable: true })
78
78
  mediaMaxSizeKb: number;
79
79
 
80
+ @Column({ name: 'media_allowed_extensions', nullable: true, type: "simple-json" })
81
+ mediaAllowedExtensions: string[];
82
+
80
83
  @Index()
81
84
  @ManyToOne(() => MediaStorageProviderMetadata, { onDelete: 'SET NULL' })
82
85
  @JoinColumn({ name: 'media_storage_provider_id' })
@@ -18,17 +18,17 @@ export class SavedFilters extends CommonEntity {
18
18
  isPrivate: boolean = false;
19
19
 
20
20
  @Index()
21
- @ManyToOne(() => User, { onDelete: "CASCADE", nullable: true })
21
+ @ManyToOne(() => User, { nullable: true })
22
22
  @JoinColumn()
23
23
  user: User;
24
24
 
25
25
  @Index()
26
- @ManyToOne(() => ModelMetadata, { onDelete: "CASCADE", nullable: false })
26
+ @ManyToOne(() => ModelMetadata, { nullable: false })
27
27
  @JoinColumn()
28
28
  model: ModelMetadata;
29
29
 
30
30
  @Index()
31
- @ManyToOne(() => ViewMetadata, { onDelete: "CASCADE", nullable: false })
31
+ @ManyToOne(() => ViewMetadata, { nullable: false })
32
32
  @JoinColumn()
33
33
  view: ViewMetadata;
34
34
 
@@ -0,0 +1,130 @@
1
+ import { Exclude, Expose } from "class-transformer";
2
+ import { CommonEntity } from "src/entities/common.entity";
3
+ import { Column, Entity, Index, ManyToOne } from "typeorm";
4
+ import { User } from "./user.entity";
5
+
6
+ /**
7
+ * A per-device MPIN credential.
8
+ *
9
+ * Login presents `credentialRef` (a server-issued opaque handle) plus the MPIN.
10
+ * The handle - not a mobile number or email - is what identifies the account,
11
+ * which is why the login route needs no identifier and offers no user
12
+ * enumeration surface.
13
+ */
14
+ @Entity("ss_user_device_credential")
15
+ // Non-unique: one physical device may legitimately hold credentials for
16
+ // several accounts, and each account setup mints its own row.
17
+ @Index(["user", "deviceId"])
18
+ @Exclude()
19
+ export class UserDeviceCredential extends CommonEntity {
20
+
21
+ // SHA-256 of the opaque handle, and the login lookup key. Never exposed:
22
+ // the raw handle is returned to the client once at setup and never stored.
23
+ // SHA-256 rather than bcrypt because the handle is 256 bits of randomness -
24
+ // there is nothing to brute-force, so a slow hash would only add latency.
25
+ // Same treatment as UserApiKey.hashedKey.
26
+ @Index({ unique: true })
27
+ @Column()
28
+ hashedCredentialRef: string;
29
+
30
+ // bcrypt hash of the MPIN, via HashingService. Never exposed - same
31
+ // treatment as User.password. Slow hashing is warranted here: a 4-6 digit
32
+ // secret is exactly the low-entropy case bcrypt exists for.
33
+ @Column()
34
+ hashedMpin: string;
35
+
36
+ // Mirrors User.passwordScheme / passwordSchemeVersion so
37
+ // HashingService.needsRehash can upgrade the hash on a successful login.
38
+ @Column()
39
+ mpinScheme: string;
40
+
41
+ /**
42
+ * The hashing *policy* version this row was hashed under - not a version of
43
+ * MPIN itself. It comes from `HashingService.currentVersion()`, which
44
+ * `BcryptService` currently returns as **2**, so freshly created rows read
45
+ * 2, exactly as `ss_user.password_scheme_version` does.
46
+ *
47
+ * It matters because `BcryptService.normalize` applies the configured
48
+ * pepper only when `version >= 2`. Storing the version per row means an
49
+ * older hash still verifies after the policy changes: `compare()` uses the
50
+ * version the row was written with, and `needsRehash()` upgrades it on the
51
+ * next successful login.
52
+ *
53
+ * The `default: 1` is inherited from the `User` precedent and is never
54
+ * reached, since every write path sets this explicitly. Note it would be
55
+ * *wrong* if it ever were: a row hashed at 2 but recorded as 1 would be
56
+ * compared without the pepper and could never authenticate.
57
+ */
58
+ @Column({ default: 1 })
59
+ mpinSchemeVersion: number;
60
+
61
+ // Client-supplied, stable for the physical device. Used for grouping and
62
+ // the device-management UI only - never a lookup key. Deliberately NOT
63
+ // unique: several accounts on one device share a deviceId.
64
+ @Expose()
65
+ @Column()
66
+ deviceId: string;
67
+
68
+ /**
69
+ * Human-readable natural key - `<username>-<deviceId>` - unique per row.
70
+ *
71
+ * Neither column alone can serve as the model's user key: `deviceId` is
72
+ * shared by every account on a device, and `deviceName` is nullable.
73
+ * Combining them is unique in both directions - one user across many
74
+ * devices, and many users on one device.
75
+ *
76
+ * Populated by MpinService rather than declared as a `computed` field in
77
+ * the metadata manifest. Computed fields are evaluated by
78
+ * ComputedFieldCrudManager on the generic CRUD path (`crud.service.ts`),
79
+ * which this service bypasses by writing through the repository directly,
80
+ * so a computed declaration would silently leave this null. It is also
81
+ * beyond ConcatComputedFieldProvider, which resolves `dto[field]` flatly
82
+ * within one model and cannot reach `username` across the user relation.
83
+ */
84
+ @Expose()
85
+ @Index({ unique: true })
86
+ @Column()
87
+ credentialKey: string;
88
+
89
+ @Expose()
90
+ @Column({ nullable: true })
91
+ deviceName: string;
92
+
93
+ @Expose()
94
+ @Column({ nullable: true })
95
+ platform: string;
96
+
97
+ // Revocation is a soft-delete: the row survives so that a correct MPIN can
98
+ // be answered with "this device was removed" rather than a baffling
99
+ // "incorrect MPIN". Only active rows count towards mpinMaxDevicesPerUser.
100
+ @Expose()
101
+ @Column({ default: true })
102
+ isActive: boolean;
103
+
104
+ // Cumulative, and reset only on a successful login - never when a lockout
105
+ // expires. That is what makes the second threshold detectable without a
106
+ // separate lockout counter.
107
+ @Expose()
108
+ @Column({ default: 0 })
109
+ failedAttempts: number;
110
+
111
+ @Expose()
112
+ @Column({ nullable: true })
113
+ lockedUntil: Date;
114
+
115
+ @Expose()
116
+ @Column({ nullable: true })
117
+ lastUsedAt: Date;
118
+
119
+ // Deliberately no inverse property on User. Nothing needs
120
+ // `user.deviceCredentials`, and leaving the most widely referenced entity
121
+ // in the system untouched keeps this feature purely additive.
122
+ //
123
+ // `nullable: false` because TypeORM makes relations nullable by default,
124
+ // which would let a credential exist with no owner. Such a row could never
125
+ // authenticate - loginWithMpin rejects it - so it would simply be dead
126
+ // data, but the database should refuse it outright. This also keeps the
127
+ // column honest against the metadata manifest, which declares it required.
128
+ @ManyToOne(() => User, { nullable: false })
129
+ user: User;
130
+ }