@solidxai/core 0.1.6-beta.1 → 0.1.6-beta.10

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 (275) hide show
  1. package/dist/controllers/dashboard-layout.controller.d.ts +47 -0
  2. package/dist/controllers/dashboard-layout.controller.d.ts.map +1 -0
  3. package/dist/controllers/dashboard-layout.controller.js +204 -0
  4. package/dist/controllers/dashboard-layout.controller.js.map +1 -0
  5. package/dist/controllers/scheduled-job.controller.d.ts +1 -0
  6. package/dist/controllers/scheduled-job.controller.d.ts.map +1 -1
  7. package/dist/controllers/scheduled-job.controller.js +12 -0
  8. package/dist/controllers/scheduled-job.controller.js.map +1 -1
  9. package/dist/dtos/create-dashboard-layout.dto.d.ts +8 -0
  10. package/dist/dtos/create-dashboard-layout.dto.d.ts.map +1 -0
  11. package/dist/dtos/create-dashboard-layout.dto.js +53 -0
  12. package/dist/dtos/create-dashboard-layout.dto.js.map +1 -0
  13. package/dist/dtos/create-dashboard-variable.dto.d.ts +1 -0
  14. package/dist/dtos/create-dashboard-variable.dto.d.ts.map +1 -1
  15. package/dist/dtos/create-dashboard-variable.dto.js +7 -1
  16. package/dist/dtos/create-dashboard-variable.dto.js.map +1 -1
  17. package/dist/dtos/update-dashboard-layout.dto.d.ts +8 -0
  18. package/dist/dtos/update-dashboard-layout.dto.d.ts.map +1 -0
  19. package/dist/dtos/update-dashboard-layout.dto.js +53 -0
  20. package/dist/dtos/update-dashboard-layout.dto.js.map +1 -0
  21. package/dist/dtos/update-dashboard-variable.dto.d.ts +1 -0
  22. package/dist/dtos/update-dashboard-variable.dto.d.ts.map +1 -1
  23. package/dist/dtos/update-dashboard-variable.dto.js +7 -1
  24. package/dist/dtos/update-dashboard-variable.dto.js.map +1 -1
  25. package/dist/entities/action-metadata.entity.d.ts.map +1 -1
  26. package/dist/entities/action-metadata.entity.js.map +1 -1
  27. package/dist/entities/ai-interaction.entity.d.ts.map +1 -1
  28. package/dist/entities/ai-interaction.entity.js +5 -4
  29. package/dist/entities/ai-interaction.entity.js.map +1 -1
  30. package/dist/entities/chatter-message-details.entity.d.ts +1 -0
  31. package/dist/entities/chatter-message-details.entity.d.ts.map +1 -1
  32. package/dist/entities/chatter-message-details.entity.js +9 -4
  33. package/dist/entities/chatter-message-details.entity.js.map +1 -1
  34. package/dist/entities/chatter-message.entity.d.ts.map +1 -1
  35. package/dist/entities/chatter-message.entity.js +4 -3
  36. package/dist/entities/chatter-message.entity.js.map +1 -1
  37. package/dist/entities/common.entity.js +1 -1
  38. package/dist/entities/common.entity.js.map +1 -1
  39. package/dist/entities/dashboard-layout.entity.d.ts +9 -0
  40. package/dist/entities/dashboard-layout.entity.d.ts.map +1 -0
  41. package/dist/entities/dashboard-layout.entity.js +41 -0
  42. package/dist/entities/dashboard-layout.entity.js.map +1 -0
  43. package/dist/entities/dashboard-question-sql-dataset-config.entity.d.ts.map +1 -1
  44. package/dist/entities/dashboard-question-sql-dataset-config.entity.js +5 -4
  45. package/dist/entities/dashboard-question-sql-dataset-config.entity.js.map +1 -1
  46. package/dist/entities/dashboard-question.entity.d.ts.map +1 -1
  47. package/dist/entities/dashboard-question.entity.js +5 -4
  48. package/dist/entities/dashboard-question.entity.js.map +1 -1
  49. package/dist/entities/dashboard-variable.entity.d.ts +1 -0
  50. package/dist/entities/dashboard-variable.entity.d.ts.map +1 -1
  51. package/dist/entities/dashboard-variable.entity.js +10 -4
  52. package/dist/entities/dashboard-variable.entity.js.map +1 -1
  53. package/dist/entities/dashboard.entity.d.ts +2 -0
  54. package/dist/entities/dashboard.entity.d.ts.map +1 -1
  55. package/dist/entities/dashboard.entity.js +9 -3
  56. package/dist/entities/dashboard.entity.js.map +1 -1
  57. package/dist/entities/email-attachment.entity.d.ts.map +1 -1
  58. package/dist/entities/email-attachment.entity.js +2 -1
  59. package/dist/entities/email-attachment.entity.js.map +1 -1
  60. package/dist/entities/email-template.entity.js +1 -1
  61. package/dist/entities/email-template.entity.js.map +1 -1
  62. package/dist/entities/export-transaction.entity.d.ts.map +1 -1
  63. package/dist/entities/export-transaction.entity.js +2 -1
  64. package/dist/entities/export-transaction.entity.js.map +1 -1
  65. package/dist/entities/field-metadata.entity.js +2 -2
  66. package/dist/entities/field-metadata.entity.js.map +1 -1
  67. package/dist/entities/import-transaction-error-log.entity.d.ts.map +1 -1
  68. package/dist/entities/import-transaction-error-log.entity.js +3 -2
  69. package/dist/entities/import-transaction-error-log.entity.js.map +1 -1
  70. package/dist/entities/import-transaction.entity.d.ts.map +1 -1
  71. package/dist/entities/import-transaction.entity.js +2 -1
  72. package/dist/entities/import-transaction.entity.js.map +1 -1
  73. package/dist/entities/legacy-common.entity.d.ts.map +1 -1
  74. package/dist/entities/legacy-common.entity.js +1 -1
  75. package/dist/entities/legacy-common.entity.js.map +1 -1
  76. package/dist/entities/mq-message.entity.d.ts.map +1 -1
  77. package/dist/entities/mq-message.entity.js +4 -3
  78. package/dist/entities/mq-message.entity.js.map +1 -1
  79. package/dist/entities/saved-filters.entity.d.ts.map +1 -1
  80. package/dist/entities/saved-filters.entity.js +3 -2
  81. package/dist/entities/saved-filters.entity.js.map +1 -1
  82. package/dist/entities/security-rule.entity.d.ts.map +1 -1
  83. package/dist/entities/security-rule.entity.js +2 -1
  84. package/dist/entities/security-rule.entity.js.map +1 -1
  85. package/dist/entities/sms-template.entity.js +1 -1
  86. package/dist/entities/sms-template.entity.js.map +1 -1
  87. package/dist/entities/user-view-metadata.entity.d.ts.map +1 -1
  88. package/dist/entities/user-view-metadata.entity.js +2 -1
  89. package/dist/entities/user-view-metadata.entity.js.map +1 -1
  90. package/dist/entities/view-metadata.entity.d.ts.map +1 -1
  91. package/dist/entities/view-metadata.entity.js.map +1 -1
  92. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +1 -0
  93. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
  94. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +8 -9
  95. package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
  96. package/dist/helpers/solid-registry.d.ts +3 -1
  97. package/dist/helpers/solid-registry.d.ts.map +1 -1
  98. package/dist/helpers/solid-registry.js.map +1 -1
  99. package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
  100. package/dist/helpers/typeorm-db-helper.js +21 -0
  101. package/dist/helpers/typeorm-db-helper.js.map +1 -1
  102. package/dist/index.d.ts +1 -0
  103. package/dist/index.d.ts.map +1 -1
  104. package/dist/index.js +1 -0
  105. package/dist/index.js.map +1 -1
  106. package/dist/interfaces.d.ts +4 -1
  107. package/dist/interfaces.d.ts.map +1 -1
  108. package/dist/interfaces.js.map +1 -1
  109. package/dist/repository/dashboard-layout.repository.d.ts +12 -0
  110. package/dist/repository/dashboard-layout.repository.d.ts.map +1 -0
  111. package/dist/repository/dashboard-layout.repository.js +34 -0
  112. package/dist/repository/dashboard-layout.repository.js.map +1 -0
  113. package/dist/seeders/module-metadata-seeder.service.js +4 -4
  114. package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
  115. package/dist/seeders/seed-data/solid-core-metadata.json +445 -35
  116. package/dist/services/authentication.service.d.ts.map +1 -1
  117. package/dist/services/authentication.service.js +44 -21
  118. package/dist/services/authentication.service.js.map +1 -1
  119. package/dist/services/chatter-message.service.d.ts.map +1 -1
  120. package/dist/services/chatter-message.service.js +26 -0
  121. package/dist/services/chatter-message.service.js.map +1 -1
  122. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.d.ts.map +1 -1
  123. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js +6 -5
  124. package/dist/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.js.map +1 -1
  125. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.d.ts.map +1 -1
  126. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js +9 -10
  127. package/dist/services/computed-fields/entity/sequence-num-computed-field-provider.js.map +1 -1
  128. package/dist/services/dashboard-layout.service.d.ts +20 -0
  129. package/dist/services/dashboard-layout.service.d.ts.map +1 -0
  130. package/dist/services/dashboard-layout.service.js +120 -0
  131. package/dist/services/dashboard-layout.service.js.map +1 -0
  132. package/dist/services/dashboard-question.service.d.ts +4 -0
  133. package/dist/services/dashboard-question.service.d.ts.map +1 -1
  134. package/dist/services/dashboard-question.service.js +22 -8
  135. package/dist/services/dashboard-question.service.js.map +1 -1
  136. package/dist/services/dashboard.service.d.ts +2 -0
  137. package/dist/services/dashboard.service.d.ts.map +1 -1
  138. package/dist/services/dashboard.service.js +4 -0
  139. package/dist/services/dashboard.service.js.map +1 -1
  140. package/dist/services/model-metadata.service.d.ts +3 -1
  141. package/dist/services/model-metadata.service.d.ts.map +1 -1
  142. package/dist/services/model-metadata.service.js +122 -8
  143. package/dist/services/model-metadata.service.js.map +1 -1
  144. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts +2 -4
  145. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.d.ts.map +1 -1
  146. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js +2 -1
  147. package/dist/services/question-data-providers/chartjs-sql-data-provider.service.js.map +1 -1
  148. package/dist/services/question-data-providers/interfaces.d.ts +1 -0
  149. package/dist/services/question-data-providers/interfaces.d.ts.map +1 -0
  150. package/dist/services/question-data-providers/interfaces.js +1 -0
  151. package/dist/services/question-data-providers/interfaces.js.map +1 -0
  152. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts +2 -5
  153. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.d.ts.map +1 -1
  154. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js +2 -1
  155. package/dist/services/question-data-providers/prime-react-datatable-sql-data-provider.service.js.map +1 -1
  156. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts +2 -5
  157. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.d.ts.map +1 -1
  158. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js +2 -1
  159. package/dist/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.js.map +1 -1
  160. package/dist/services/queues/database-subscriber.service.d.ts +4 -2
  161. package/dist/services/queues/database-subscriber.service.d.ts.map +1 -1
  162. package/dist/services/queues/database-subscriber.service.js +15 -2
  163. package/dist/services/queues/database-subscriber.service.js.map +1 -1
  164. package/dist/services/queues/publisher-factory.service.d.ts.map +1 -1
  165. package/dist/services/queues/publisher-factory.service.js +4 -6
  166. package/dist/services/queues/publisher-factory.service.js.map +1 -1
  167. package/dist/services/queues/rabbitmq-subscriber.service.d.ts +8 -3
  168. package/dist/services/queues/rabbitmq-subscriber.service.d.ts.map +1 -1
  169. package/dist/services/queues/rabbitmq-subscriber.service.js +72 -5
  170. package/dist/services/queues/rabbitmq-subscriber.service.js.map +1 -1
  171. package/dist/services/scheduled-job.service.d.ts +6 -1
  172. package/dist/services/scheduled-job.service.d.ts.map +1 -1
  173. package/dist/services/scheduled-job.service.js +26 -2
  174. package/dist/services/scheduled-job.service.js.map +1 -1
  175. package/dist/services/scheduled-jobs/scheduler.interface.d.ts +2 -0
  176. package/dist/services/scheduled-jobs/scheduler.interface.d.ts.map +1 -1
  177. package/dist/services/scheduled-jobs/scheduler.interface.js.map +1 -1
  178. package/dist/services/scheduled-jobs/scheduler.service.d.ts +6 -2
  179. package/dist/services/scheduled-jobs/scheduler.service.d.ts.map +1 -1
  180. package/dist/services/scheduled-jobs/scheduler.service.js +75 -17
  181. package/dist/services/scheduled-jobs/scheduler.service.js.map +1 -1
  182. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.d.ts.map +1 -1
  183. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js +4 -1
  184. package/dist/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.js.map +1 -1
  185. package/dist/services/solid-ts-morph.service.d.ts +9 -0
  186. package/dist/services/solid-ts-morph.service.d.ts.map +1 -1
  187. package/dist/services/solid-ts-morph.service.js +76 -0
  188. package/dist/services/solid-ts-morph.service.js.map +1 -1
  189. package/dist/solid-core.module.d.ts.map +1 -1
  190. package/dist/solid-core.module.js +8 -0
  191. package/dist/solid-core.module.js.map +1 -1
  192. package/dist/subscribers/computed-entity-field.subscriber.d.ts.map +1 -1
  193. package/dist/subscribers/computed-entity-field.subscriber.js +9 -1
  194. package/dist/subscribers/computed-entity-field.subscriber.js.map +1 -1
  195. package/dist/transformers/typeorm/local-date-time-transformer.d.ts +4 -4
  196. package/dist/transformers/typeorm/local-date-time-transformer.d.ts.map +1 -1
  197. package/dist/transformers/typeorm/local-date-time-transformer.js +25 -28
  198. package/dist/transformers/typeorm/local-date-time-transformer.js.map +1 -1
  199. package/dist-tests/api/authenticate.spec.js +119 -0
  200. package/dist-tests/api/authenticate.spec.js.map +1 -0
  201. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +97 -0
  202. package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +1 -0
  203. package/dist-tests/api/ping.spec.js +21 -0
  204. package/dist-tests/api/ping.spec.js.map +1 -0
  205. package/dist-tests/helpers/auth.js +41 -0
  206. package/dist-tests/helpers/auth.js.map +1 -0
  207. package/dist-tests/helpers/env.js +11 -0
  208. package/dist-tests/helpers/env.js.map +1 -0
  209. package/package.json +1 -1
  210. package/sql/default/mariadb/proc_CleanupModelMetadata.sql +153 -0
  211. package/sql/default/mariadb/proc_CleanupModuleMetadata.sql +56 -0
  212. package/sql/default/mysql/proc_CleanupModelMetadata.sql +153 -0
  213. package/sql/default/mysql/proc_CleanupModuleMetadata.sql +56 -0
  214. package/src/controllers/dashboard-layout.controller.ts +106 -0
  215. package/src/controllers/scheduled-job.controller.ts +6 -0
  216. package/src/dtos/create-dashboard-layout.dto.ts +31 -0
  217. package/src/dtos/create-dashboard-variable.dto.ts +4 -0
  218. package/src/dtos/update-dashboard-layout.dto.ts +30 -0
  219. package/src/dtos/update-dashboard-variable.dto.ts +5 -1
  220. package/src/entities/action-metadata.entity.ts +3 -2
  221. package/src/entities/ai-interaction.entity.ts +5 -4
  222. package/src/entities/chatter-message-details.entity.ts +7 -3
  223. package/src/entities/chatter-message.entity.ts +4 -3
  224. package/src/entities/common.entity.ts +2 -2
  225. package/src/entities/dashboard-layout.entity.ts +18 -0
  226. package/src/entities/dashboard-question-sql-dataset-config.entity.ts +5 -4
  227. package/src/entities/dashboard-question.entity.ts +5 -4
  228. package/src/entities/dashboard-variable.entity.ts +9 -4
  229. package/src/entities/dashboard.entity.ts +7 -2
  230. package/src/entities/email-attachment.entity.ts +2 -1
  231. package/src/entities/email-template.entity.ts +1 -1
  232. package/src/entities/export-transaction.entity.ts +2 -1
  233. package/src/entities/field-metadata.entity.ts +2 -2
  234. package/src/entities/import-transaction-error-log.entity.ts +3 -2
  235. package/src/entities/import-transaction.entity.ts +2 -1
  236. package/src/entities/legacy-common.entity.ts +3 -4
  237. package/src/entities/mq-message.entity.ts +4 -3
  238. package/src/entities/saved-filters.entity.ts +3 -2
  239. package/src/entities/security-rule.entity.ts +2 -1
  240. package/src/entities/sms-template.entity.ts +1 -1
  241. package/src/entities/user-view-metadata.entity.ts +2 -1
  242. package/src/entities/view-metadata.entity.ts +3 -0
  243. package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +9 -9
  244. package/src/helpers/solid-registry.ts +3 -2
  245. package/src/helpers/typeorm-db-helper.ts +26 -0
  246. package/src/index.ts +1 -0
  247. package/src/interfaces.ts +7 -1
  248. package/src/repository/dashboard-layout.repository.ts +17 -0
  249. package/src/seeders/module-metadata-seeder.service.ts +5 -5
  250. package/src/seeders/seed-data/solid-core-metadata.json +446 -36
  251. package/src/services/authentication.service.ts +46 -24
  252. package/src/services/chatter-message.service.ts +26 -0
  253. package/src/services/computed-fields/entity/alpha-num-external-id-computed-field-provider.ts +6 -5
  254. package/src/services/computed-fields/entity/sequence-num-computed-field-provider.ts +17 -22
  255. package/src/services/dashboard-layout.service.ts +111 -0
  256. package/src/services/dashboard-question.service.ts +23 -4
  257. package/src/services/dashboard.service.ts +7 -0
  258. package/src/services/model-metadata.service.ts +131 -50
  259. package/src/services/question-data-providers/chartjs-sql-data-provider.service.ts +3 -7
  260. package/src/services/question-data-providers/interfaces.ts +0 -0
  261. package/src/services/question-data-providers/prime-react-datatable-sql-data-provider.service.ts +4 -8
  262. package/src/services/question-data-providers/prime-react-meter-group-sql-data-provider.service.ts +4 -8
  263. package/src/services/queues/database-subscriber.service.ts +19 -2
  264. package/src/services/queues/publisher-factory.service.ts +8 -6
  265. package/src/services/queues/rabbitmq-subscriber.service.ts +115 -5
  266. package/src/services/scheduled-job.service.ts +31 -2
  267. package/src/services/scheduled-jobs/scheduler.interface.ts +4 -1
  268. package/src/services/scheduled-jobs/scheduler.service.ts +82 -20
  269. package/src/services/selection-providers/list-of-dashboard-question-providers-selection-provider.service.ts +4 -1
  270. package/src/services/solid-ts-morph.service.ts +98 -0
  271. package/src/solid-core.module.ts +12 -0
  272. package/src/subscribers/computed-entity-field.subscriber.ts +9 -3
  273. package/src/transformers/typeorm/local-date-time-transformer.ts +41 -33
  274. package/.claude/settings.local.json +0 -15
  275. package/src/services/1.js +0 -6
@@ -464,10 +464,6 @@ export class AuthenticationService {
464
464
 
465
465
  private async notifyUserOnOtpInitiateRegistration(user: User, registrationValidationSource: string) {
466
466
  const companyLogo = await this.getCompanyLogo();
467
- const dummyOtp = this.getDummyOtpForUser(user);
468
-
469
- if (dummyOtp)
470
- return; // Do nothing if dummy otp is configured.
471
467
  if (registrationValidationSource === PasswordlessLoginValidateWhatSources.EMAIL) {
472
468
  const mailService = this.mailServiceFactory.getMailService();
473
469
  mailService.sendEmailUsingTemplate(
@@ -594,13 +590,12 @@ export class AuthenticationService {
594
590
  return true;
595
591
  }
596
592
 
597
- private async otp(user?: User): Promise<otp> {
593
+ private async otp(): Promise<otp> {
598
594
  const now = new Date();
599
595
  const otpExpiry = this.settingService.getConfigValue<SolidCoreSetting>('otpExpiry');
600
- const dummyOtp = this.getDummyOtpForUser(user);
601
596
  now.setMinutes(now.getMinutes() + otpExpiry);
602
597
  return {
603
- token: dummyOtp ? dummyOtp : randomInt(100000, 999999).toString(),
598
+ token: randomInt(100000, 999999).toString(),
604
599
  expiresAt: now,
605
600
  };
606
601
  }
@@ -692,8 +687,11 @@ export class AuthenticationService {
692
687
 
693
688
  const type = this.resolveLoginType(signInDto);
694
689
  const user = await this.findUserForLogin(type, signInDto.identifier);
695
- await this.assignLoginOtp(user, type);
696
- this.notifyUserOnOtpInititateLogin(user, type);
690
+ const dummyOtp = this.getDummyOtpForUser(user);
691
+ if (!dummyOtp) {
692
+ await this.assignLoginOtp(user, type);
693
+ this.notifyUserOnOtpInititateLogin(user, type);
694
+ }
697
695
  return this.buildLoginOtpResponse(user, type);
698
696
  }
699
697
 
@@ -738,15 +736,22 @@ export class AuthenticationService {
738
736
  }
739
737
 
740
738
  private async assignLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
741
- const { token, expiresAt } = await this.otp(user);
739
+ const { token, expiresAt } = await this.otp();
742
740
  if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
743
741
  user.emailVerificationTokenOnLogin = token;
744
742
  user.emailVerificationTokenOnLoginExpiresAt = expiresAt;
743
+ await this.userRepository.update(user.id, {
744
+ emailVerificationTokenOnLogin: token,
745
+ emailVerificationTokenOnLoginExpiresAt: expiresAt,
746
+ });
745
747
  } else {
746
748
  user.mobileVerificationTokenOnLogin = token;
747
749
  user.mobileVerificationTokenOnLoginExpiresAt = expiresAt;
750
+ await this.userRepository.update(user.id, {
751
+ mobileVerificationTokenOnLogin: token,
752
+ mobileVerificationTokenOnLoginExpiresAt: expiresAt,
753
+ });
748
754
  }
749
- await this.userRepository.save(user);
750
755
  }
751
756
 
752
757
  private buildLoginOtpResponse(user: User, type: PasswordlessLoginValidateWhatSources) {
@@ -815,6 +820,15 @@ export class AuthenticationService {
815
820
 
816
821
  const user = await this.findUserForLogin(type, identifier, { withRoles: true });
817
822
  this.checkAccountBlocked(user);
823
+ const dummyOtp = this.getDummyOtpForUser(user);
824
+
825
+ if (dummyOtp) {
826
+ if (otp !== dummyOtp) {
827
+ throw new UnauthorizedException(ERROR_MESSAGES.INVALID_OTP);
828
+ }
829
+ return this.buildLoginTokenResponse(user);
830
+ }
831
+
818
832
  try {
819
833
  this.validateLoginOtp(user, otp, type);
820
834
  } catch (e) {
@@ -822,14 +836,9 @@ export class AuthenticationService {
822
836
  throw e;
823
837
  }
824
838
 
825
- // we do not need to clear the otp when dummy otp is configured...
826
- const dummyOtp = this.getDummyOtpForUser(user);
827
- if (!dummyOtp)
828
- this.clearLoginOtp(user, type);
829
-
830
- user.failedLoginAttempts = 0;
839
+ await this.clearLoginOtp(user, type);
831
840
  await this.userActivityHistoryService.logEvent('login', user);
832
- await this.userRepository.save(user);
841
+ await this.resetFailedAttempts(user);
833
842
  return this.buildLoginTokenResponse(user);
834
843
  }
835
844
 
@@ -846,15 +855,27 @@ export class AuthenticationService {
846
855
  }
847
856
  }
848
857
 
849
- private clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): void {
858
+ private async clearLoginOtp(user: User, type: PasswordlessLoginValidateWhatSources): Promise<void> {
850
859
  if (type === PasswordlessLoginValidateWhatSources.EMAIL) {
851
- user.emailVerifiedOnLoginAt = new Date();
860
+ const verifiedAt = new Date();
861
+ user.emailVerifiedOnLoginAt = verifiedAt;
852
862
  user.emailVerificationTokenOnLogin = null;
853
863
  user.emailVerificationTokenOnLoginExpiresAt = null;
864
+ await this.userRepository.update(user.id, {
865
+ emailVerifiedOnLoginAt: verifiedAt,
866
+ emailVerificationTokenOnLogin: null,
867
+ emailVerificationTokenOnLoginExpiresAt: null,
868
+ });
854
869
  } else {
855
- user.mobileVerifiedOnLoginAt = new Date();
870
+ const verifiedAt = new Date();
871
+ user.mobileVerifiedOnLoginAt = verifiedAt;
856
872
  user.mobileVerificationTokenOnLogin = null;
857
873
  user.mobileVerificationTokenOnLoginExpiresAt = null;
874
+ await this.userRepository.update(user.id, {
875
+ mobileVerifiedOnLoginAt: verifiedAt,
876
+ mobileVerificationTokenOnLogin: null,
877
+ mobileVerificationTokenOnLoginExpiresAt: null,
878
+ });
858
879
  }
859
880
  }
860
881
 
@@ -1297,14 +1318,15 @@ export class AuthenticationService {
1297
1318
  }
1298
1319
 
1299
1320
  private async incrementFailedAttempts(user: User): Promise<void> {
1300
- user.failedLoginAttempts += 1;
1301
- await this.userRepository.save(user);
1321
+ const nextFailedAttempts = (user.failedLoginAttempts ?? 0) + 1;
1322
+ user.failedLoginAttempts = nextFailedAttempts;
1323
+ await this.userRepository.update(user.id, { failedLoginAttempts: nextFailedAttempts });
1302
1324
  }
1303
1325
 
1304
1326
  private async resetFailedAttempts(user: User): Promise<void> {
1305
1327
  if (user.failedLoginAttempts === 0) return;
1306
1328
  user.failedLoginAttempts = 0;
1307
- await this.userRepository.save(user);
1329
+ await this.userRepository.update(user.id, { failedLoginAttempts: 0 });
1308
1330
  }
1309
1331
 
1310
1332
  //FIXME - Pending implementation
@@ -1,3 +1,4 @@
1
+ import { LocalDateTimeTransformer, serializeDate } from 'src/transformers/typeorm/local-date-time-transformer';
1
2
  import { forwardRef, Inject, Injectable } from '@nestjs/common';
2
3
  import { ModuleRef } from "@nestjs/core";
3
4
  import { InjectEntityManager } from '@nestjs/typeorm';
@@ -141,6 +142,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
141
142
  messageDetail.chatterMessage = savedMessage;
142
143
  messageDetail.fieldName = field.name;
143
144
  messageDetail.fieldDisplayName = field.displayName;
145
+ messageDetail.fieldType = field.type;
144
146
  messageDetail.oldValue = null;
145
147
  messageDetail.oldValueDisplay = null;
146
148
  messageDetail.newValue = this.formatFieldValue(field, fieldValue);
@@ -257,6 +259,7 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
257
259
  messageDetail.chatterMessage = savedMessage;
258
260
  messageDetail.fieldName = field.name;
259
261
  messageDetail.fieldDisplayName = field.displayName;
262
+ messageDetail.fieldType = field.type;
260
263
  messageDetail.oldValue = this.formatFieldValue(field, oldValue);
261
264
  messageDetail.newValue = this.formatFieldValue(field, newValue);
262
265
  messageDetail.oldValueDisplay = await this.formatFieldValueDisplay(field, oldValue);
@@ -320,6 +323,9 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
320
323
  }
321
324
  }
322
325
 
326
+ if (value instanceof Date) {
327
+ return serializeDate(value);
328
+ }
323
329
 
324
330
  return value.toString();
325
331
  }
@@ -333,6 +339,10 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
333
339
  return `${value}`;
334
340
  }
335
341
 
342
+ if (['date', 'datetime', 'time'].includes(field.type)) {
343
+ return null;
344
+ }
345
+
336
346
  if (field.type === 'relation') {
337
347
  if (field.relationType === "many-to-one") {
338
348
  if (value.name) {
@@ -618,6 +628,22 @@ export class ChatterMessageService extends CRUDService<ChatterMessage> {
618
628
  const [entities, count] = await qb.getManyAndCount();
619
629
  this.logHeapUsed('getChatterMessages-entitiesLoaded');
620
630
 
631
+ // Convert date strings in message details to ISO format for consistent handling on the frontend
632
+ const DATE_FIELD_TYPES = ['date', 'datetime', 'time'];
633
+ for (const entity of entities) {
634
+ for (const detail of entity.chatterMessageDetails ?? []) {
635
+ if (!detail.fieldType || !DATE_FIELD_TYPES.includes(detail.fieldType)) continue;
636
+ if (detail.oldValue) {
637
+ const d = LocalDateTimeTransformer.from(detail.oldValue);
638
+ if (d) detail.oldValue = d.toISOString();
639
+ }
640
+ if (detail.newValue) {
641
+ const d = LocalDateTimeTransformer.from(detail.newValue);
642
+ if (d) detail.newValue = d.toISOString();
643
+ }
644
+ }
645
+ }
646
+
621
647
  if (populateMedia && populateMedia.length > 0) {
622
648
  const normalizedPopulateMedia = this.crudHelperService.normalize(populateMedia);
623
649
  this.logHeapUsed('getChatterMessages-beforePopulateMedia');
@@ -31,6 +31,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
31
31
  async preComputeValue(triggerEntity: T, computedFieldMetadata: ComputedFieldMetadata<AlphaNumExternalIdContext>) {
32
32
  const { prefix, length, dynamicFieldPrefix } = computedFieldMetadata.computedFieldValueProviderCtxt;
33
33
  const eventContext = computedFieldMetadata.eventContext;
34
+ const manager = eventContext?.manager ?? this.entityManager;
34
35
  const entityName = eventContext?.metadataName ?? eventContext.databaseEntity?.constructor?.name ?? '';
35
36
 
36
37
  const codeLength = length || 5;
@@ -45,7 +46,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
45
46
  }
46
47
  }
47
48
 
48
- const uniqueCode = await this.generateUniqueExternalId(resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
49
+ const uniqueCode = await this.generateUniqueExternalId(manager, resolvedPrefix, codeLength, computedFieldMetadata.fieldName, entityName);
49
50
  const finalExternalId = resolvedPrefix ? `${resolvedPrefix}-${uniqueCode}` : uniqueCode;
50
51
 
51
52
  triggerEntity[computedFieldMetadata.fieldName] = finalExternalId;
@@ -60,8 +61,8 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
60
61
  return result;
61
62
  }
62
63
 
63
- private async isExternalIdUnique(externalId: string, fieldName: string, entityName: string): Promise<boolean> {
64
- const count = await this.entityManager.count(entityName as any,
64
+ private async isExternalIdUnique(manager: EntityManager, externalId: string, fieldName: string, entityName: string): Promise<boolean> {
65
+ const count = await manager.count(entityName as any,
65
66
  {
66
67
  where: { [fieldName]: externalId },
67
68
  }
@@ -69,7 +70,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
69
70
  return count === 0;
70
71
  }
71
72
 
72
- private async generateUniqueExternalId(resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
73
+ private async generateUniqueExternalId(manager: EntityManager, resolvedPrefix: string, codeLength: number, fieldName: string, entityName: string): Promise<string> {
73
74
  const maxAttempts = 10;
74
75
 
75
76
  for (let attempt = 0; attempt < maxAttempts; attempt++) {
@@ -78,7 +79,7 @@ export class AlphaNumExternalIdComputationProvider<T extends CommonEntity> imple
78
79
 
79
80
  const fullId = resolvedPrefix ? `${resolvedPrefix}-${newId}` : newId;
80
81
 
81
- const isUnique = await this.isExternalIdUnique(fullId, fieldName, entityName);
82
+ const isUnique = await this.isExternalIdUnique(manager, fullId, fieldName, entityName);
82
83
 
83
84
  if (isUnique) {
84
85
  return newId;
@@ -5,7 +5,7 @@ import { CommonEntity } from "src/entities/common.entity";
5
5
  import { ModelSequence } from "src/entities/model-sequence.entity";
6
6
  import { ComputedFieldMetadata } from "src/helpers/solid-registry";
7
7
  import { IEntityPreComputeFieldProvider } from "src/interfaces";
8
- import { DataSource, EntityTarget } from "typeorm";
8
+ import { DataSource, EntityManager } from "typeorm";
9
9
 
10
10
 
11
11
  export interface SequenceNumComputedFieldContext {
@@ -36,11 +36,10 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
36
36
  throw new Error("sequenceName is required for sequence computation");
37
37
  }
38
38
 
39
- await this.dataSource.transaction(async (manager) => {
40
- /**
41
- * 1️⃣ Lock sequence row (prevents race conditions)
42
- */
43
- // 1️⃣ Fetch sequence row
39
+ const contextManager = computedFieldMetadata.eventContext?.manager;
40
+
41
+ const compute = async (manager: EntityManager) => {
42
+ // Lock sequence row to avoid duplicate sequence numbers under concurrency.
44
43
  const modelSequenceRepo = manager.getRepository(ModelSequence)
45
44
  const modelSequence = await modelSequenceRepo.findOne({
46
45
  where: { sequenceName },
@@ -61,26 +60,22 @@ export class SequenceNumComputedFieldProvider<T extends CommonEntity> implements
61
60
 
62
61
  const sequenceString = `${prefix}${separator}${paddedValue}`;
63
62
 
64
- // 3️⃣ Duplicate check on TARGET ENTITY (extra safety)
65
- const entityRepo = manager.getRepository(triggerEntity.constructor as any);
66
-
67
- const existing = await entityRepo.findOne({
68
- where: {
69
- [computedFieldMetadata.fieldName]: sequenceString,
70
- },
71
- });
72
-
73
- if (existing) {
74
- throw new Error(`Duplicate Sequence generated: ${sequenceString}`);
75
- }
76
-
77
- // 4️⃣ set the computed field on the entity
63
+ // Set the computed field on the trigger entity.
78
64
  (triggerEntity as any)[computedFieldMetadata.fieldName] = sequenceString;
79
65
 
80
- // 5️⃣ Persist updated sequence current value
66
+ // Persist updated sequence current value.
81
67
  modelSequence.currentValue = nextValue;
82
68
  await modelSequenceRepo.save(modelSequence);
69
+ };
70
+
71
+ if (contextManager?.queryRunner?.isTransactionActive) {
72
+ await compute(contextManager);
73
+ return;
74
+ }
75
+
76
+ await this.dataSource.transaction(async (manager) => {
77
+ await compute(manager);
83
78
  });
84
79
  }
85
80
 
86
- }
81
+ }
@@ -0,0 +1,111 @@
1
+ import { Injectable, Logger } from '@nestjs/common';
2
+ import { ModuleRef } from "@nestjs/core";
3
+ import { InjectEntityManager } from '@nestjs/typeorm';
4
+ import { EntityManager } from 'typeorm';
5
+
6
+ import { CRUDService } from 'src/services/crud.service';
7
+ import { DashboardLayout } from 'src/entities/dashboard-layout.entity';
8
+ import { DashboardLayoutRepository } from 'src/repository/dashboard-layout.repository';
9
+ import { CreateDashboardLayoutDto } from 'src/dtos/create-dashboard-layout.dto';
10
+ import { RequestContextService } from './request-context.service';
11
+
12
+
13
+ @Injectable()
14
+ export class DashboardLayoutService extends CRUDService<DashboardLayout> {
15
+ private readonly logger = new Logger(this.constructor.name);
16
+ constructor(
17
+ @InjectEntityManager()
18
+ readonly entityManager: EntityManager,
19
+ readonly repo: DashboardLayoutRepository,
20
+ readonly requestContextService: RequestContextService,
21
+ readonly moduleRef: ModuleRef,
22
+ ) {
23
+ super(entityManager, repo, 'dashboardLayout', 'solid-core', moduleRef);
24
+ }
25
+
26
+ async upsertUserDashboardLayout(createDtos: CreateDashboardLayoutDto) {
27
+ const activeUser = this.requestContextService.getActiveUser();
28
+
29
+ if (!activeUser) {
30
+ throw new Error('User not found');
31
+ }
32
+
33
+ let userId = null;
34
+ if (activeUser.roles.includes('Admin')) {
35
+ userId = null;
36
+ } else {
37
+ userId = activeUser?.sub;
38
+ }
39
+ const existingLayout = await this.repo.findOne({
40
+ where: {
41
+ user: { id: userId },
42
+ dashboard: {
43
+ id: createDtos.dashboardId
44
+ }
45
+ },
46
+ relations: {
47
+ user: true,
48
+ dashboard: true,
49
+ }
50
+ });
51
+
52
+ if (existingLayout) {
53
+ return super.update(existingLayout.id, { layout: createDtos.layout }, [], true);
54
+ } else {
55
+ const createDto = {
56
+ layout: createDtos.layout,
57
+ dashboardId: createDtos.dashboardId,
58
+ uesrId: userId
59
+ }
60
+ return super.create(createDto, []);
61
+ }
62
+ }
63
+
64
+ async getUserDashboardLayoutByDashboardId(dashboardId: any) {
65
+ const activeUser = this.requestContextService.getActiveUser();
66
+
67
+ if (!activeUser) {
68
+ throw new Error('User not found');
69
+ }
70
+ const userId = activeUser?.sub;
71
+ const existingUserLayout = await this.repo.findOne({
72
+ where: {
73
+ user: { id: userId },
74
+ dashboard: {
75
+ id: dashboardId
76
+ }
77
+ },
78
+ relations: {
79
+ user: true,
80
+ dashboard: true,
81
+ }
82
+ });
83
+ if (existingUserLayout) {
84
+ // if dahsboard for userid exists
85
+ return existingUserLayout;
86
+ }
87
+
88
+ // if not then check for default dashboard
89
+ const defaultLayout = await this.repo.findOne({
90
+ where: {
91
+ user: { id: null },
92
+ dashboard: {
93
+ id: dashboardId
94
+ }
95
+ },
96
+ relations: {
97
+ user: true,
98
+ dashboard: true,
99
+ }
100
+ });
101
+ if (defaultLayout) {
102
+ // if default layout exists return it
103
+ return defaultLayout;
104
+ } else {
105
+ // if default layout does not exist return empty layout
106
+ return {
107
+ layout: null
108
+ }
109
+ }
110
+ }
111
+ }
@@ -11,15 +11,18 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
11
11
  import { DashboardQuestion } from '../entities/dashboard-question.entity';
12
12
  import { SqlExpression, SqlExpressionOperator } from './question-data-providers/chartjs-sql-data-provider.service';
13
13
  import { DashboardQuestionRepository } from 'src/repository/dashboard-question.repository';
14
+ import { QuestionSqlDataProviderContext } from 'src';
14
15
 
15
16
  enum SOURCE_TYPE {
16
17
  SQL = 'sql',
17
18
  PROVIDER = 'provider',
18
19
  }
19
20
 
20
- const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
21
- const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
22
- const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
21
+ export const CHARTJS_SQL_DATA_PROVIDER_NAME = 'ChartJsSqlDataProvider';
22
+ export const PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME = 'PrimeReactMeterGroupSqlDataProvider';
23
+ export const PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME = 'PrimeReactDatatableSqlDataProvider';
24
+
25
+ export const INBUILT_SQL_DATA_PROVIDERS = [CHARTJS_SQL_DATA_PROVIDER_NAME, PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME, PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME];
23
26
 
24
27
  @Injectable()
25
28
  export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
@@ -50,22 +53,38 @@ export class DashboardQuestionService extends CRUDService<DashboardQuestion> {
50
53
 
51
54
  // Try to resolve the dataProvider based on a combination of sourceType and visualisedAs
52
55
  let dataProvider = null;
56
+ let context = {};
53
57
 
58
+ // Decide which data provider to use based on the question visualisation type if sourceType is SQL.
54
59
  if (question.sourceType === SOURCE_TYPE.SQL && ['bar', 'pie', 'line', 'donut'].includes(question.visualisedAs)) {
55
60
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(CHARTJS_SQL_DATA_PROVIDER_NAME);
61
+ context = {
62
+ expressions,
63
+ } as QuestionSqlDataProviderContext;
56
64
  }
57
65
  if (question.sourceType === SOURCE_TYPE.SQL && ['prime-meter-group'].includes(question.visualisedAs)) {
58
66
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_METER_GROUP_SQL_DATA_PROVIDER_NAME);
67
+ context = {
68
+ expressions,
69
+ } as QuestionSqlDataProviderContext;
59
70
  }
60
71
  if (question.sourceType === SOURCE_TYPE.SQL && ['prime-datatable'].includes(question.visualisedAs)) {
61
72
  dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(PRIME_REACT_DATATABLE_SQL_DATA_PROVIDER_NAME);
73
+ context = {
74
+ expressions,
75
+ } as QuestionSqlDataProviderContext;
76
+ }
77
+
78
+ // If a custom provider is specified, use that one instead
79
+ if (question.sourceType === SOURCE_TYPE.PROVIDER) {
80
+ dataProvider = this.solidRegistry.getDashboardQuestionDataProviderInstance(question.providerName);
62
81
  }
63
82
 
64
83
  if (!dataProvider) {
65
84
  throw new NotImplementedException(`Invalid data source type ${question.sourceType}`);
66
85
  }
67
86
 
68
- return await dataProvider.getData(question, expressions);
87
+ return await dataProvider.getData(question, context);
69
88
 
70
89
  }
71
90
 
@@ -15,6 +15,7 @@ import { SolidRegistry } from 'src/helpers/solid-registry';
15
15
  import { DashboardMapper } from 'src/mappers/dashboard-mapper';
16
16
  import { DashboardRepository } from 'src/repository/dashboard.repository';
17
17
  import { Dashboard } from '../entities/dashboard.entity';
18
+ import { CreateDashboardDto } from 'src/dtos/create-dashboard.dto';
18
19
 
19
20
 
20
21
  export const SQL_DYNAMIC_PROVIDER_NAME = 'DashboardVariableSQLDynamicProvider';
@@ -33,6 +34,12 @@ export class DashboardService extends CRUDService<Dashboard> {
33
34
  super(entityManager, repo, 'dashboard', 'solid-core', moduleRef);
34
35
  }
35
36
 
37
+
38
+ async create(createDto: CreateDashboardDto, files: Express.Multer.File[]) {
39
+ createDto.name = createDto.name.trim().replace(/\s+/g, '-').toLowerCase();
40
+ return super.create(createDto, files);
41
+ }
42
+
36
43
  async getSelectionDynamicValues(query: DashboardVariableSelectionDynamicQueryDto) {
37
44
  // Get the dashboard variable repo
38
45
  const dashboardVariable = await this.loadDashboardVariable(query.variableId);