@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.
- package/CHANGELOG.md +10107 -0
- package/CLAUDE.md +5 -6
- package/README.md +19 -0
- package/dist/commands/run-tests.command.d.ts +9 -1
- package/dist/commands/run-tests.command.d.ts.map +1 -1
- package/dist/commands/run-tests.command.js +69 -6
- package/dist/commands/run-tests.command.js.map +1 -1
- package/dist/commands/seed.command.d.ts +2 -0
- package/dist/commands/seed.command.d.ts.map +1 -1
- package/dist/commands/seed.command.js +21 -0
- package/dist/commands/seed.command.js.map +1 -1
- package/dist/config/cache.options.d.ts.map +1 -1
- package/dist/config/cache.options.js +2 -2
- package/dist/config/cache.options.js.map +1 -1
- package/dist/constants/chatter-message.constants.d.ts +1 -0
- package/dist/constants/chatter-message.constants.d.ts.map +1 -1
- package/dist/constants/chatter-message.constants.js +3 -1
- package/dist/constants/chatter-message.constants.js.map +1 -1
- package/dist/constants/draft-publish-fields.d.ts +2 -0
- package/dist/constants/draft-publish-fields.d.ts.map +1 -0
- package/dist/constants/draft-publish-fields.js +5 -0
- package/dist/constants/draft-publish-fields.js.map +1 -0
- package/dist/constants/error-messages.d.ts +7 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +7 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/constants/media-file-types.d.ts +12 -0
- package/dist/constants/media-file-types.d.ts.map +1 -1
- package/dist/constants/media-file-types.js +66 -1
- package/dist/constants/media-file-types.js.map +1 -1
- package/dist/constants/success-messages.d.ts +3 -0
- package/dist/constants/success-messages.d.ts.map +1 -1
- package/dist/constants/success-messages.js +3 -0
- package/dist/constants/success-messages.js.map +1 -1
- package/dist/constants/user.constants.d.ts +2 -0
- package/dist/constants/user.constants.d.ts.map +1 -0
- package/dist/constants/user.constants.js +5 -0
- package/dist/constants/user.constants.js.map +1 -0
- package/dist/controllers/action-metadata.controller.d.ts +1 -1
- package/dist/controllers/action-metadata.controller.js +1 -1
- package/dist/controllers/agent-event.controller.d.ts +1 -1
- package/dist/controllers/agent-event.controller.js +1 -1
- package/dist/controllers/agent-session.controller.d.ts +1 -1
- package/dist/controllers/agent-session.controller.js +1 -1
- package/dist/controllers/authentication.controller.d.ts +1 -1
- package/dist/controllers/authentication.controller.d.ts.map +1 -1
- package/dist/controllers/authentication.controller.js +4 -3
- package/dist/controllers/authentication.controller.js.map +1 -1
- package/dist/controllers/chatter-message.controller.d.ts +5 -0
- package/dist/controllers/chatter-message.controller.d.ts.map +1 -1
- package/dist/controllers/chatter-message.controller.js +14 -0
- package/dist/controllers/chatter-message.controller.js.map +1 -1
- package/dist/controllers/dashboard-user-layout.controller.d.ts +1 -1
- package/dist/controllers/dashboard-user-layout.controller.js +1 -1
- package/dist/controllers/email-template.controller.d.ts +1 -1
- package/dist/controllers/email-template.controller.js +1 -1
- package/dist/controllers/export-template.controller.d.ts +1 -1
- package/dist/controllers/export-template.controller.d.ts.map +1 -1
- package/dist/controllers/export-template.controller.js +6 -4
- package/dist/controllers/export-template.controller.js.map +1 -1
- package/dist/controllers/export-transaction.controller.d.ts +1 -1
- package/dist/controllers/export-transaction.controller.js +1 -1
- package/dist/controllers/field-metadata.controller.d.ts +2 -2
- package/dist/controllers/import-transaction-error-log.controller.d.ts +1 -1
- package/dist/controllers/import-transaction-error-log.controller.js +1 -1
- package/dist/controllers/import-transaction.controller.d.ts +1 -1
- package/dist/controllers/import-transaction.controller.d.ts.map +1 -1
- package/dist/controllers/import-transaction.controller.js +7 -7
- package/dist/controllers/import-transaction.controller.js.map +1 -1
- package/dist/controllers/list-of-values.controller.d.ts +1 -1
- package/dist/controllers/list-of-values.controller.js +1 -1
- package/dist/controllers/locale.controller.d.ts +1 -1
- package/dist/controllers/locale.controller.js +1 -1
- package/dist/controllers/mcp-audit-log.controller.d.ts +1 -1
- package/dist/controllers/mcp-audit-log.controller.js +1 -1
- package/dist/controllers/media.controller.d.ts +2 -2
- package/dist/controllers/media.controller.d.ts.map +1 -1
- package/dist/controllers/media.controller.js +13 -8
- package/dist/controllers/media.controller.js.map +1 -1
- package/dist/controllers/menu-item-metadata.controller.d.ts +1 -1
- package/dist/controllers/menu-item-metadata.controller.js +1 -1
- package/dist/controllers/model-sequence.controller.d.ts +1 -1
- package/dist/controllers/model-sequence.controller.js +1 -1
- package/dist/controllers/module-package.controller.d.ts.map +1 -1
- package/dist/controllers/module-package.controller.js +2 -3
- package/dist/controllers/module-package.controller.js.map +1 -1
- package/dist/controllers/mpin-authentication.controller.d.ts +44 -0
- package/dist/controllers/mpin-authentication.controller.d.ts.map +1 -0
- package/dist/controllers/mpin-authentication.controller.js +102 -0
- package/dist/controllers/mpin-authentication.controller.js.map +1 -0
- package/dist/controllers/mq-message-queue.controller.d.ts +1 -1
- package/dist/controllers/mq-message-queue.controller.js +1 -1
- package/dist/controllers/mq-message.controller.d.ts +1 -1
- package/dist/controllers/mq-message.controller.js +1 -1
- package/dist/controllers/permission-metadata.controller.d.ts +1 -1
- package/dist/controllers/permission-metadata.controller.js +1 -1
- package/dist/controllers/role-metadata.controller.d.ts +1 -1
- package/dist/controllers/role-metadata.controller.js +1 -1
- package/dist/controllers/saved-filters.controller.d.ts +1 -1
- package/dist/controllers/saved-filters.controller.js +1 -1
- package/dist/controllers/scheduled-job.controller.d.ts +1 -1
- package/dist/controllers/scheduled-job.controller.js +1 -1
- package/dist/controllers/security-rule.controller.d.ts +1 -1
- package/dist/controllers/security-rule.controller.js +1 -1
- package/dist/controllers/sms-template.controller.d.ts +1 -1
- package/dist/controllers/sms-template.controller.js +1 -1
- package/dist/controllers/user-activity-history.controller.d.ts +1 -1
- package/dist/controllers/user-activity-history.controller.js +1 -1
- package/dist/controllers/user-view-metadata.controller.d.ts +1 -1
- package/dist/controllers/user-view-metadata.controller.js +1 -1
- package/dist/controllers/user.controller.d.ts +2 -2
- package/dist/controllers/user.controller.js +2 -2
- package/dist/controllers/view-metadata.controller.d.ts +2 -2
- package/dist/controllers/view-metadata.controller.js +1 -1
- package/dist/controllers/workflow-definition.controller.d.ts +1 -1
- package/dist/controllers/workflow-definition.controller.js +1 -1
- package/dist/controllers/workflow-execution-artifact.controller.d.ts +1 -1
- package/dist/controllers/workflow-execution-artifact.controller.js +1 -1
- package/dist/controllers/workflow-execution-log.controller.d.ts +1 -1
- package/dist/controllers/workflow-execution-log.controller.js +1 -1
- package/dist/controllers/workflow-execution.controller.d.ts +1 -1
- package/dist/controllers/workflow-execution.controller.js +1 -1
- package/dist/controllers/workflow-secret.controller.d.ts +1 -1
- package/dist/controllers/workflow-secret.controller.js +1 -1
- package/dist/controllers/workflow-step-execution.controller.d.ts +1 -1
- package/dist/controllers/workflow-step-execution.controller.js +1 -1
- package/dist/controllers/workflow-trigger-execution.controller.d.ts +1 -1
- package/dist/controllers/workflow-trigger-execution.controller.js +1 -1
- package/dist/dtos/basic-filters.dto.d.ts +0 -1
- package/dist/dtos/basic-filters.dto.d.ts.map +1 -1
- package/dist/dtos/basic-filters.dto.js +1 -6
- package/dist/dtos/basic-filters.dto.js.map +1 -1
- package/dist/dtos/change-mpin.dto.d.ts +6 -0
- package/dist/dtos/change-mpin.dto.d.ts.map +1 -0
- package/dist/dtos/change-mpin.dto.js +39 -0
- package/dist/dtos/change-mpin.dto.js.map +1 -0
- package/dist/dtos/create-field-metadata.dto.d.ts +3 -6
- package/dist/dtos/create-field-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-field-metadata.dto.js +15 -10
- package/dist/dtos/create-field-metadata.dto.js.map +1 -1
- package/dist/dtos/create-model-sequence.dto.d.ts +1 -1
- package/dist/dtos/create-model-sequence.dto.d.ts.map +1 -1
- package/dist/dtos/create-model-sequence.dto.js +1 -1
- package/dist/dtos/create-model-sequence.dto.js.map +1 -1
- package/dist/dtos/mpin-login.dto.d.ts +5 -0
- package/dist/dtos/mpin-login.dto.d.ts.map +1 -0
- package/dist/dtos/mpin-login.dto.js +33 -0
- package/dist/dtos/mpin-login.dto.js.map +1 -0
- package/dist/dtos/setup-mpin.dto.d.ts +7 -0
- package/dist/dtos/setup-mpin.dto.d.ts.map +1 -0
- package/dist/dtos/setup-mpin.dto.js +47 -0
- package/dist/dtos/setup-mpin.dto.js.map +1 -0
- package/dist/entities/common.entity.d.ts +4 -0
- package/dist/entities/common.entity.d.ts.map +1 -1
- package/dist/entities/common.entity.js +25 -1
- package/dist/entities/common.entity.js.map +1 -1
- package/dist/entities/dashboard-user-layout.entity.js +2 -2
- package/dist/entities/dashboard-user-layout.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.d.ts +1 -0
- package/dist/entities/field-metadata.entity.d.ts.map +1 -1
- package/dist/entities/field-metadata.entity.js +5 -1
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/saved-filters.entity.js +3 -3
- package/dist/entities/saved-filters.entity.js.map +1 -1
- package/dist/entities/user-device-credential.entity.d.ts +18 -0
- package/dist/entities/user-device-credential.entity.d.ts.map +1 -0
- package/dist/entities/user-device-credential.entity.js +91 -0
- package/dist/entities/user-device-credential.entity.js.map +1 -0
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +36 -0
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/entities/workflow-execution-artifact.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution-artifact.entity.js +4 -3
- package/dist/entities/workflow-execution-artifact.entity.js.map +1 -1
- package/dist/entities/workflow-execution-log.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution-log.entity.js +4 -3
- package/dist/entities/workflow-execution-log.entity.js.map +1 -1
- package/dist/entities/workflow-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-execution.entity.js +3 -2
- package/dist/entities/workflow-execution.entity.js.map +1 -1
- package/dist/entities/workflow-secret.entity.d.ts.map +1 -1
- package/dist/entities/workflow-secret.entity.js +3 -2
- package/dist/entities/workflow-secret.entity.js.map +1 -1
- package/dist/entities/workflow-step-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-step-execution.entity.js +3 -2
- package/dist/entities/workflow-step-execution.entity.js.map +1 -1
- package/dist/entities/workflow-trigger-execution.entity.d.ts.map +1 -1
- package/dist/entities/workflow-trigger-execution.entity.js +7 -6
- package/dist/entities/workflow-trigger-execution.entity.js.map +1 -1
- package/dist/factories/mail.factory.d.ts.map +1 -1
- package/dist/factories/mail.factory.js +4 -0
- package/dist/factories/mail.factory.js.map +1 -1
- package/dist/filters/http-exception.filter.d.ts.map +1 -1
- package/dist/filters/http-exception.filter.js +5 -1
- package/dist/filters/http-exception.filter.js.map +1 -1
- package/dist/helpers/bootstrap.helper.d.ts +5 -2
- package/dist/helpers/bootstrap.helper.d.ts.map +1 -1
- package/dist/helpers/bootstrap.helper.js +7 -3
- package/dist/helpers/bootstrap.helper.js.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts +7 -0
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.d.ts.map +1 -1
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js +66 -32
- package/dist/helpers/field-crud-managers/MediaFieldCrudManager.js.map +1 -1
- package/dist/helpers/file-download.helper.d.ts +9 -0
- package/dist/helpers/file-download.helper.d.ts.map +1 -0
- package/dist/helpers/file-download.helper.js +19 -0
- package/dist/helpers/file-download.helper.js.map +1 -0
- package/dist/helpers/model-metadata-helper.service.d.ts.map +1 -1
- package/dist/helpers/model-metadata-helper.service.js +30 -1
- package/dist/helpers/model-metadata-helper.service.js.map +1 -1
- package/dist/helpers/security.helper.d.ts +5 -1
- package/dist/helpers/security.helper.d.ts.map +1 -1
- package/dist/helpers/security.helper.js +15 -4
- package/dist/helpers/security.helper.js.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.d.ts.map +1 -1
- package/dist/helpers/solid-core-error-codes-provider.service.js +45 -0
- package/dist/helpers/solid-core-error-codes-provider.service.js.map +1 -1
- package/dist/helpers/solid-microservice-adapter.service.d.ts.map +1 -1
- package/dist/helpers/solid-microservice-adapter.service.js +1 -1
- package/dist/helpers/solid-microservice-adapter.service.js.map +1 -1
- package/dist/helpers/solid-registry.js +1 -1
- package/dist/helpers/solid-registry.js.map +1 -1
- package/dist/helpers/typeorm-db-helper.d.ts.map +1 -1
- package/dist/helpers/typeorm-db-helper.js +9 -0
- package/dist/helpers/typeorm-db-helper.js.map +1 -1
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/interfaces/active-user-data.interface.d.ts +1 -0
- package/dist/interfaces/active-user-data.interface.d.ts.map +1 -1
- package/dist/interfaces/active-user-data.interface.js.map +1 -1
- package/dist/interfaces.d.ts +1 -0
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/repository/user-device-credential.repository.d.ts +12 -0
- package/dist/repository/user-device-credential.repository.d.ts.map +1 -0
- package/dist/repository/user-device-credential.repository.js +34 -0
- package/dist/repository/user-device-credential.repository.js.map +1 -0
- package/dist/seeders/module-metadata-seeder.service.d.ts.map +1 -1
- package/dist/seeders/module-metadata-seeder.service.js +51 -30
- package/dist/seeders/module-metadata-seeder.service.js.map +1 -1
- package/dist/seeders/module-test-data.service.d.ts +3 -1
- package/dist/seeders/module-test-data.service.d.ts.map +1 -1
- package/dist/seeders/module-test-data.service.js +8 -2
- package/dist/seeders/module-test-data.service.js.map +1 -1
- package/dist/seeders/seed-data/solid-core-metadata.json +290 -78
- package/dist/services/api-key.service.d.ts.map +1 -1
- package/dist/services/api-key.service.js +1 -1
- package/dist/services/api-key.service.js.map +1 -1
- package/dist/services/authentication.service.d.ts +9 -5
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +102 -23
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/chatter-message.service.d.ts +16 -1
- package/dist/services/chatter-message.service.d.ts.map +1 -1
- package/dist/services/chatter-message.service.js +100 -16
- package/dist/services/chatter-message.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts +6 -4
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +32 -48
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/crud.service.d.ts +13 -1
- package/dist/services/crud.service.d.ts.map +1 -1
- package/dist/services/crud.service.js +94 -68
- package/dist/services/crud.service.js.map +1 -1
- package/dist/services/datasource-introspection.service.d.ts.map +1 -1
- package/dist/services/datasource-introspection.service.js.map +1 -1
- package/dist/services/draft-publish-helper.service.d.ts +53 -0
- package/dist/services/draft-publish-helper.service.d.ts.map +1 -0
- package/dist/services/draft-publish-helper.service.js +402 -0
- package/dist/services/draft-publish-helper.service.js.map +1 -0
- package/dist/services/field-metadata.service.d.ts +2 -2
- package/dist/services/field-metadata.service.d.ts.map +1 -1
- package/dist/services/field-metadata.service.js +4 -1
- package/dist/services/field-metadata.service.js.map +1 -1
- package/dist/services/internationalisation-helper.service.d.ts +19 -0
- package/dist/services/internationalisation-helper.service.d.ts.map +1 -0
- package/dist/services/internationalisation-helper.service.js +107 -0
- package/dist/services/internationalisation-helper.service.js.map +1 -0
- package/dist/services/locale.service.d.ts +1 -1
- package/dist/services/media-storage.utils.d.ts +1 -0
- package/dist/services/media-storage.utils.d.ts.map +1 -1
- package/dist/services/media-storage.utils.js +12 -1
- package/dist/services/media-storage.utils.js.map +1 -1
- package/dist/services/media.service.d.ts +3 -2
- package/dist/services/media.service.d.ts.map +1 -1
- package/dist/services/media.service.js +45 -29
- package/dist/services/media.service.js.map +1 -1
- package/dist/services/metadata-validation.service.d.ts +7 -0
- package/dist/services/metadata-validation.service.d.ts.map +1 -0
- package/dist/services/metadata-validation.service.js +42 -0
- package/dist/services/metadata-validation.service.js.map +1 -0
- package/dist/services/model-metadata.service.d.ts.map +1 -1
- package/dist/services/model-metadata.service.js +2 -1
- package/dist/services/model-metadata.service.js.map +1 -1
- package/dist/services/module-metadata.service.d.ts.map +1 -1
- package/dist/services/module-metadata.service.js +9 -1
- package/dist/services/module-metadata.service.js.map +1 -1
- package/dist/services/mpin.service.d.ts +67 -0
- package/dist/services/mpin.service.d.ts.map +1 -0
- package/dist/services/mpin.service.js +282 -0
- package/dist/services/mpin.service.js.map +1 -0
- package/dist/services/object.utils.d.ts +2 -0
- package/dist/services/object.utils.d.ts.map +1 -0
- package/dist/services/object.utils.js +11 -0
- package/dist/services/object.utils.js.map +1 -0
- package/dist/services/refresh-token-ids-storage.service.d.ts +25 -6
- package/dist/services/refresh-token-ids-storage.service.d.ts.map +1 -1
- package/dist/services/refresh-token-ids-storage.service.js +80 -42
- package/dist/services/refresh-token-ids-storage.service.js.map +1 -1
- package/dist/services/setting.service.d.ts.map +1 -1
- package/dist/services/setting.service.js +6 -1
- package/dist/services/setting.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +248 -12
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +143 -6
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/user.service.d.ts +2 -2
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +9 -3
- package/dist/services/user.service.js.map +1 -1
- package/dist/services/view-metadata.service.d.ts +1 -2
- package/dist/services/view-metadata.service.d.ts.map +1 -1
- package/dist/services/view-metadata.service.js +3 -55
- package/dist/services/view-metadata.service.js.map +1 -1
- package/dist/services/workflow/nodes/execution-fail.node.d.ts +6 -0
- package/dist/services/workflow/nodes/execution-fail.node.d.ts.map +1 -0
- package/dist/services/workflow/nodes/execution-fail.node.js +81 -0
- package/dist/services/workflow/nodes/execution-fail.node.js.map +1 -0
- package/dist/services/workflow/nodes/for-each.node.d.ts +2 -0
- package/dist/services/workflow/nodes/for-each.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/for-each.node.js +114 -5
- package/dist/services/workflow/nodes/for-each.node.js.map +1 -1
- package/dist/services/workflow/nodes/if.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/if.node.js +7 -0
- package/dist/services/workflow/nodes/if.node.js.map +1 -1
- package/dist/services/workflow/nodes/log-write.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/log-write.node.js +2 -0
- package/dist/services/workflow/nodes/log-write.node.js.map +1 -1
- package/dist/services/workflow/nodes/loop-until.node.d.ts +12 -0
- package/dist/services/workflow/nodes/loop-until.node.d.ts.map +1 -0
- package/dist/services/workflow/nodes/loop-until.node.js +281 -0
- package/dist/services/workflow/nodes/loop-until.node.js.map +1 -0
- package/dist/services/workflow/nodes/parallel.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/parallel.node.js +7 -0
- package/dist/services/workflow/nodes/parallel.node.js.map +1 -1
- package/dist/services/workflow/nodes/sequential.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/sequential.node.js +7 -0
- package/dist/services/workflow/nodes/sequential.node.js.map +1 -1
- package/dist/services/workflow/nodes/switch.node.d.ts.map +1 -1
- package/dist/services/workflow/nodes/switch.node.js +7 -0
- package/dist/services/workflow/nodes/switch.node.js.map +1 -1
- package/dist/services/workflow/workflow-definition-validator.service.d.ts.map +1 -1
- package/dist/services/workflow/workflow-definition-validator.service.js +5 -2
- package/dist/services/workflow/workflow-definition-validator.service.js.map +1 -1
- package/dist/services/workflow/workflow-expression.service.d.ts.map +1 -1
- package/dist/services/workflow/workflow-expression.service.js +5 -0
- package/dist/services/workflow/workflow-expression.service.js.map +1 -1
- package/dist/services/workflow/workflow-node-registry.service.d.ts +2 -1
- package/dist/services/workflow/workflow-node-registry.service.d.ts.map +1 -1
- package/dist/services/workflow/workflow-node-registry.service.js +7 -0
- package/dist/services/workflow/workflow-node-registry.service.js.map +1 -1
- package/dist/services/workflow/workflow-runtime.service.d.ts +8 -0
- package/dist/services/workflow/workflow-runtime.service.d.ts.map +1 -1
- package/dist/services/workflow/workflow-runtime.service.js +197 -32
- package/dist/services/workflow/workflow-runtime.service.js.map +1 -1
- package/dist/services/workflow-definition.service.d.ts +1 -1
- package/dist/solid-core.module.d.ts +1 -3
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +28 -40
- package/dist/solid-core.module.js.map +1 -1
- package/dist/testing/adapters/ui/playwright-adapter.d.ts +5 -0
- package/dist/testing/adapters/ui/playwright-adapter.d.ts.map +1 -1
- package/dist/testing/adapters/ui/playwright-adapter.js +17 -1
- package/dist/testing/adapters/ui/playwright-adapter.js.map +1 -1
- package/dist/testing/adapters/ui/ui.types.d.ts +2 -0
- package/dist/testing/adapters/ui/ui.types.d.ts.map +1 -1
- package/dist/testing/adapters/ui/ui.types.js.map +1 -1
- package/dist/testing/reporter/console-reporter.d.ts +3 -0
- package/dist/testing/reporter/console-reporter.d.ts.map +1 -1
- package/dist/testing/reporter/console-reporter.js +2 -0
- package/dist/testing/reporter/console-reporter.js.map +1 -1
- package/dist/testing/reporter/progress-reporter.d.ts +64 -0
- package/dist/testing/reporter/progress-reporter.d.ts.map +1 -0
- package/dist/testing/reporter/progress-reporter.js +224 -0
- package/dist/testing/reporter/progress-reporter.js.map +1 -0
- package/dist/testing/reporter/reporter.types.d.ts +3 -0
- package/dist/testing/reporter/reporter.types.d.ts.map +1 -1
- package/dist/testing/reporter/reporter.types.js.map +1 -1
- package/dist/testing/runner/run-from-metadata.d.ts.map +1 -1
- package/dist/testing/runner/run-from-metadata.js +1 -0
- package/dist/testing/runner/run-from-metadata.js.map +1 -1
- package/dist/testing/steps/ui/actions.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/actions.step.js +6 -2
- package/dist/testing/steps/ui/actions.step.js.map +1 -1
- package/dist/testing/steps/ui/assertions.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/assertions.step.js +11 -3
- package/dist/testing/steps/ui/assertions.step.js.map +1 -1
- package/dist/testing/steps/ui/form.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/form.step.js +9 -3
- package/dist/testing/steps/ui/form.step.js.map +1 -1
- package/dist/testing/steps/ui/manual.step.js +1 -1
- package/dist/testing/steps/ui/manual.step.js.map +1 -1
- package/dist/testing/steps/ui/navigation.step.d.ts.map +1 -1
- package/dist/testing/steps/ui/navigation.step.js +3 -1
- package/dist/testing/steps/ui/navigation.step.js.map +1 -1
- package/dist/theme/theme-registry.d.ts +14 -0
- package/dist/theme/theme-registry.d.ts.map +1 -0
- package/dist/theme/theme-registry.js +147 -0
- package/dist/theme/theme-registry.js.map +1 -0
- package/dist/types/workflow-dsl.types.d.ts +14 -0
- package/dist/types/workflow-dsl.types.d.ts.map +1 -1
- package/dist/types/workflow-dsl.types.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/run-tests.command.ts +64 -4
- package/src/commands/seed.command.ts +19 -0
- package/src/config/cache.options.ts +9 -1
- package/src/constants/chatter-message.constants.ts +12 -0
- package/src/constants/draft-publish-fields.ts +5 -0
- package/src/constants/error-messages.ts +14 -0
- package/src/constants/media-file-types.ts +128 -0
- package/src/constants/success-messages.ts +5 -0
- package/src/constants/user.constants.ts +13 -0
- package/src/controllers/authentication.controller.ts +5 -2
- package/src/controllers/chatter-message.controller.ts +8 -0
- package/src/controllers/export-template.controller.ts +5 -3
- package/src/controllers/import-transaction.controller.ts +6 -6
- package/src/controllers/media.controller.ts +17 -6
- package/src/controllers/module-package.controller.ts +2 -3
- package/src/controllers/mpin-authentication.controller.ts +67 -0
- package/src/dtos/basic-filters.dto.ts +0 -4
- package/src/dtos/change-mpin.dto.ts +18 -0
- package/src/dtos/create-field-metadata.dto.ts +17 -9
- package/src/dtos/create-model-sequence.dto.ts +1 -1
- package/src/dtos/mpin-login.dto.ts +24 -0
- package/src/dtos/setup-mpin.dto.ts +51 -0
- package/src/entities/common.entity.ts +24 -0
- package/src/entities/dashboard-user-layout.entity.ts +2 -2
- package/src/entities/field-metadata.entity.ts +3 -0
- package/src/entities/saved-filters.entity.ts +3 -3
- package/src/entities/user-device-credential.entity.ts +130 -0
- package/src/entities/user.entity.ts +53 -36
- package/src/entities/view-metadata.entity.ts +2 -2
- package/src/entities/workflow-execution-artifact.entity.ts +4 -3
- package/src/entities/workflow-execution-log.entity.ts +4 -3
- package/src/entities/workflow-execution.entity.ts +3 -2
- package/src/entities/workflow-secret.entity.ts +3 -2
- package/src/entities/workflow-step-execution.entity.ts +3 -2
- package/src/entities/workflow-trigger-execution.entity.ts +7 -6
- package/src/factories/mail.factory.ts +7 -1
- package/src/filters/http-exception.filter.ts +11 -1
- package/src/helpers/bootstrap.helper.ts +43 -6
- package/src/helpers/field-crud-managers/MediaFieldCrudManager.ts +90 -37
- package/src/helpers/file-download.helper.ts +45 -0
- package/src/helpers/model-metadata-helper.service.ts +32 -1
- package/src/helpers/security.helper.ts +35 -8
- package/src/helpers/solid-core-error-codes-provider.service.ts +53 -0
- package/src/helpers/solid-microservice-adapter.service.ts +6 -1
- package/src/helpers/solid-registry.ts +1 -1
- package/src/helpers/typeorm-db-helper.ts +12 -1
- package/src/index.ts +10 -0
- package/src/interfaces/active-user-data.interface.ts +9 -0
- package/src/interfaces.ts +1 -0
- package/src/repository/user-device-credential.repository.ts +17 -0
- package/src/seeders/module-metadata-seeder.service.ts +61 -39
- package/src/seeders/module-test-data.service.ts +6 -0
- package/src/seeders/seed-data/solid-core-metadata.json +290 -78
- package/src/services/api-key.service.ts +13 -1
- package/src/services/authentication.service.ts +203 -41
- package/src/services/chatter-message.service.ts +180 -19
- package/src/services/crud-helper.service.ts +35 -50
- package/src/services/crud.service.ts +132 -105
- package/src/services/datasource-introspection.service.ts +5 -0
- package/src/services/draft-publish-helper.service.ts +581 -0
- package/src/services/field-metadata.service.ts +5 -2
- package/src/services/internationalisation-helper.service.ts +148 -0
- package/src/services/media-storage.utils.ts +26 -1
- package/src/services/media.service.ts +68 -36
- package/src/services/metadata-validation.service.ts +39 -0
- package/src/services/model-metadata.service.ts +4 -1
- package/src/services/module-metadata.service.ts +10 -1
- package/src/services/mpin.service.ts +447 -0
- package/src/services/object.utils.ts +10 -0
- package/src/services/refresh-token-ids-storage.service.ts +229 -90
- package/src/services/setting.service.ts +8 -1
- package/src/services/settings/default-settings-provider.service.ts +154 -6
- package/src/services/user.service.ts +18 -3
- package/src/services/view-metadata.service.ts +5 -145
- package/src/services/workflow/nodes/execution-fail.node.ts +82 -0
- package/src/services/workflow/nodes/for-each.node.ts +140 -6
- package/src/services/workflow/nodes/if.node.ts +7 -0
- package/src/services/workflow/nodes/log-write.node.ts +2 -0
- package/src/services/workflow/nodes/loop-until.node.ts +343 -0
- package/src/services/workflow/nodes/parallel.node.ts +7 -0
- package/src/services/workflow/nodes/sequential.node.ts +7 -0
- package/src/services/workflow/nodes/switch.node.ts +7 -0
- package/src/services/workflow/workflow-definition-validator.service.ts +5 -2
- package/src/services/workflow/workflow-expression.service.ts +5 -0
- package/src/services/workflow/workflow-node-registry.service.ts +11 -0
- package/src/services/workflow/workflow-runtime.service.ts +274 -39
- package/src/solid-core.module.ts +46 -15
- package/src/testing/README.md +75 -3
- package/src/testing/adapters/ui/playwright-adapter.ts +25 -0
- package/src/testing/adapters/ui/ui.types.ts +2 -0
- package/src/testing/reporter/console-reporter.ts +4 -0
- package/src/testing/reporter/progress-reporter.ts +251 -0
- package/src/testing/reporter/reporter.types.ts +3 -0
- package/src/testing/runner/run-from-metadata.ts +1 -0
- package/src/testing/steps/ui/actions.step.ts +8 -4
- package/src/testing/steps/ui/assertions.step.ts +18 -5
- package/src/testing/steps/ui/form.step.ts +16 -6
- package/src/testing/steps/ui/manual.step.ts +1 -1
- package/src/testing/steps/ui/navigation.step.ts +4 -2
- package/src/theme/theme-registry.ts +181 -0
- package/src/types/workflow-dsl.types.ts +43 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { Logger } from "@nestjs/common";
|
|
2
|
+
import { EntityManager, In } from "typeorm";
|
|
3
|
+
import { CommonEntity } from "../entities/common.entity";
|
|
4
|
+
import { Locale } from "../entities/locale.entity";
|
|
5
|
+
import { ModelMetadata } from "../entities/model-metadata.entity";
|
|
6
|
+
import { classify } from "../helpers/string.helper";
|
|
7
|
+
import { SolidRegistry } from "../helpers/solid-registry";
|
|
8
|
+
import { SolidBaseRepository } from "../repository/solid-base.repository";
|
|
9
|
+
|
|
10
|
+
export class InternationalisationHelperService {
|
|
11
|
+
private readonly logger = new Logger(InternationalisationHelperService.name);
|
|
12
|
+
|
|
13
|
+
isInternationalisationEnabled(model: ModelMetadata): boolean {
|
|
14
|
+
return model?.internationalisation === true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/** Defaults `localeName` on a create DTO for internationalised models, so new records stay visible to the default-locale filter in `find()`. */
|
|
18
|
+
applyCreateDefaults(model: ModelMetadata, createDto: any, solidRegistry: SolidRegistry): void {
|
|
19
|
+
if (!this.isInternationalisationEnabled(model) || createDto.localeName) return;
|
|
20
|
+
createDto.localeName = this.resolveDefaultLocaleName(solidRegistry);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async deleteChildLocaleEntities<T extends CommonEntity>(
|
|
24
|
+
repo: SolidBaseRepository<T>,
|
|
25
|
+
model: ModelMetadata,
|
|
26
|
+
entityIds: number[],
|
|
27
|
+
): Promise<void> {
|
|
28
|
+
if (!this.isInternationalisationEnabled(model) || entityIds.length === 0) return;
|
|
29
|
+
|
|
30
|
+
const childEntities = await repo.find({
|
|
31
|
+
where: { defaultEntityLocaleId: In(entityIds) } as any,
|
|
32
|
+
});
|
|
33
|
+
if (childEntities.length === 0) return;
|
|
34
|
+
|
|
35
|
+
if (model.enableSoftDelete === true) {
|
|
36
|
+
await repo.softRemove(childEntities);
|
|
37
|
+
} else {
|
|
38
|
+
await repo.remove(childEntities);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
pickCurrentLocaleRecord(records: any[], localeName: string, draftPublishEnabled: boolean): any | null {
|
|
43
|
+
const localeRecords = records.filter(record => record.localeName === localeName);
|
|
44
|
+
if (localeRecords.length === 0) return null;
|
|
45
|
+
|
|
46
|
+
return localeRecords.sort((a, b) => {
|
|
47
|
+
// isLatest only exists on draft/publish-enabled models (legacy tables lack the column)
|
|
48
|
+
if (draftPublishEnabled && Boolean(a.isLatest) !== Boolean(b.isLatest)) return a.isLatest ? -1 : 1;
|
|
49
|
+
|
|
50
|
+
return Number(b.id ?? 0) - Number(a.id ?? 0);
|
|
51
|
+
})[0];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Resolves the locale name to filter/tag records by: explicit locale, else the registry default, else 'en'. */
|
|
55
|
+
resolveDefaultLocaleName(solidRegistry: SolidRegistry): string {
|
|
56
|
+
const defaultLocale = solidRegistry.getDefaultLocale();
|
|
57
|
+
return defaultLocale?.locale ?? 'en';
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async getEntityRecordsInAllLocales(
|
|
61
|
+
entityManager: EntityManager,
|
|
62
|
+
modelName: string,
|
|
63
|
+
id: string,
|
|
64
|
+
defaultEntityLocaleIdFromQuery: string | undefined,
|
|
65
|
+
draftPublishEnabled: boolean,
|
|
66
|
+
): Promise<{ records: any[], defaultEntityLocaleId: string | null }> {
|
|
67
|
+
const currentEntityRepository = entityManager.getRepository(classify(modelName));
|
|
68
|
+
|
|
69
|
+
// Case 1: Creating a new record with no defaultEntityLocaleId to clone
|
|
70
|
+
if (id === 'new' && !defaultEntityLocaleIdFromQuery) {
|
|
71
|
+
this.logger.debug(`Creating new record without cloning from any defaultEntityLocaleId.`);
|
|
72
|
+
return { records: [], defaultEntityLocaleId: null };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Case 2: Creating a new record and cloning from an existing defaultEntityLocaleId
|
|
76
|
+
if (id === 'new' && defaultEntityLocaleIdFromQuery) {
|
|
77
|
+
this.logger.debug(`Creating new record by cloning translations from defaultEntityLocaleId: ${defaultEntityLocaleIdFromQuery}`);
|
|
78
|
+
|
|
79
|
+
const records = await currentEntityRepository.find({
|
|
80
|
+
where: [
|
|
81
|
+
{ defaultEntityLocaleId: defaultEntityLocaleIdFromQuery },
|
|
82
|
+
{ id: defaultEntityLocaleIdFromQuery },
|
|
83
|
+
// initialEntityVersionId only exists on draft/publish-enabled models (legacy tables lack the column)
|
|
84
|
+
...(draftPublishEnabled ? [{ initialEntityVersionId: defaultEntityLocaleIdFromQuery }] : []),
|
|
85
|
+
]
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
this.logger.debug(`Found ${records.length} cloned records for new entity.`);
|
|
89
|
+
return { records, defaultEntityLocaleId: defaultEntityLocaleIdFromQuery };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Case 3: Editing an existing entity
|
|
93
|
+
const entityRecord = await currentEntityRepository.findOne({ where: { id } });
|
|
94
|
+
|
|
95
|
+
if (!entityRecord) {
|
|
96
|
+
this.logger.warn(`No entity found for id ${id}`);
|
|
97
|
+
return { records: [], defaultEntityLocaleId: null };
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const defaultEntityLocaleId = entityRecord.defaultEntityLocaleId
|
|
101
|
+
|| (draftPublishEnabled ? entityRecord.initialEntityVersionId : null)
|
|
102
|
+
|| entityRecord.id;
|
|
103
|
+
if (entityRecord.defaultEntityLocaleId) {
|
|
104
|
+
this.logger.debug(`Editing translated locale record. Translation root id: ${defaultEntityLocaleId}`);
|
|
105
|
+
} else {
|
|
106
|
+
this.logger.debug(`Editing translation root record with id ${defaultEntityLocaleId}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const records = await currentEntityRepository.find({
|
|
110
|
+
where: [
|
|
111
|
+
{ defaultEntityLocaleId: defaultEntityLocaleId },
|
|
112
|
+
{ id: defaultEntityLocaleId },
|
|
113
|
+
...(draftPublishEnabled ? [{ initialEntityVersionId: defaultEntityLocaleId }] : []),
|
|
114
|
+
]
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
this.logger.debug(`Found ${records.length} records in all locales for existing entity.`);
|
|
118
|
+
|
|
119
|
+
return { records, defaultEntityLocaleId };
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Builds the `applicableLocales` shape for a view layout: one entry per registered locale,
|
|
124
|
+
* with the matching translation record's id (if any) resolved via pickCurrentLocaleRecord.
|
|
125
|
+
*/
|
|
126
|
+
async buildApplicableLocales(
|
|
127
|
+
entityManager: EntityManager,
|
|
128
|
+
modelName: string,
|
|
129
|
+
id: string,
|
|
130
|
+
defaultEntityLocaleIdFromQuery: string | undefined,
|
|
131
|
+
draftPublishEnabled: boolean,
|
|
132
|
+
): Promise<any[]> {
|
|
133
|
+
const { records: entityRecordsInAllLocales, defaultEntityLocaleId } =
|
|
134
|
+
await this.getEntityRecordsInAllLocales(entityManager, modelName, id, defaultEntityLocaleIdFromQuery, draftPublishEnabled);
|
|
135
|
+
const allLocales = await entityManager.getRepository(Locale).find({});
|
|
136
|
+
|
|
137
|
+
return allLocales.map(locale => {
|
|
138
|
+
const matchingRecord = this.pickCurrentLocaleRecord(entityRecordsInAllLocales, locale.locale, draftPublishEnabled);
|
|
139
|
+
return {
|
|
140
|
+
locale: locale.locale,
|
|
141
|
+
displayName: locale.displayName,
|
|
142
|
+
isDefault: locale.isDefault ? 'yes' : 'no',
|
|
143
|
+
defaultEntityLocaleId,
|
|
144
|
+
entityId: matchingRecord ? matchingRecord.id : null,
|
|
145
|
+
};
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -5,6 +5,11 @@ import { MediaStorageProviderMetadata } from 'src/entities/media-storage-provide
|
|
|
5
5
|
import { SettingService } from 'src/services/setting.service';
|
|
6
6
|
import { DEFAULT_MEDIA_FILE_STORAGE_DIR } from 'src/services/settings/default-settings-provider.service';
|
|
7
7
|
import type { SolidCoreSetting } from 'src/services/settings/default-settings-provider.service';
|
|
8
|
+
import { normalizeUploadedFileName } from 'src/constants/media-file-types';
|
|
9
|
+
|
|
10
|
+
// Keeps the joined path well clear of filesystem NAME_MAX (255 on ext4/APFS) once the
|
|
11
|
+
// multer hash prefix and separator are added.
|
|
12
|
+
const MAX_STORED_FILE_NAME_LENGTH = 150;
|
|
8
13
|
|
|
9
14
|
|
|
10
15
|
export interface MediaRecordCreateInput {
|
|
@@ -18,9 +23,29 @@ export interface MediaRecordCreateInput {
|
|
|
18
23
|
originalFileName?: string;
|
|
19
24
|
}
|
|
20
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Reduces a client-supplied name to something safe to interpolate into a filesystem path.
|
|
28
|
+
* `originalname` is fully attacker-controlled, so without this a name like
|
|
29
|
+
* `../../../../tmp/pwned.png` escapes the media storage directory entirely - the multer hash
|
|
30
|
+
* prefix does not contain it, because the leading `..` simply cancels the prefix segment.
|
|
31
|
+
*
|
|
32
|
+
* Everything outside a conservative allowlist becomes `_`; the result can never contain a
|
|
33
|
+
* path separator, so the joined path always stays inside the storage root.
|
|
34
|
+
*/
|
|
35
|
+
export function sanitizeStoredMediaFileName(originalName?: string | null): string {
|
|
36
|
+
const sanitized = normalizeUploadedFileName(originalName)
|
|
37
|
+
.replace(/[^A-Za-z0-9._-]/g, '_')
|
|
38
|
+
// Collapse any run of dots so no `..` segment can survive.
|
|
39
|
+
.replace(/\.{2,}/g, '.')
|
|
40
|
+
.replace(/^[._-]+/, '')
|
|
41
|
+
.slice(0, MAX_STORED_FILE_NAME_LENGTH);
|
|
42
|
+
|
|
43
|
+
return sanitized || 'file';
|
|
44
|
+
}
|
|
45
|
+
|
|
21
46
|
// Builds the stored file name format shared by media storage implementations.
|
|
22
47
|
export function buildStoredMediaFileName(file: Pick<Express.Multer.File, 'filename' | 'originalname'>): string {
|
|
23
|
-
return `${file.filename}-${file.originalname}`;
|
|
48
|
+
return `${file.filename}-${sanitizeStoredMediaFileName(file.originalname)}`;
|
|
24
49
|
}
|
|
25
50
|
|
|
26
51
|
// Resolves the on-disk path for a media file based on settings and provider visibility.
|
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
|
1
|
+
import { BadRequestException, forwardRef, Inject, Injectable, Logger, NotFoundException } from '@nestjs/common';
|
|
2
2
|
import { ModuleRef } from "@nestjs/core";
|
|
3
3
|
import { InjectEntityManager } from '@nestjs/typeorm';
|
|
4
|
-
import { EntityManager, In } from 'typeorm';
|
|
4
|
+
import { EntityManager, In, Not } from 'typeorm';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { Readable } from 'stream';
|
|
7
7
|
|
|
8
8
|
import { ConfigService } from '@nestjs/config';
|
|
9
9
|
import { CRUDService } from 'src/services/crud.service';
|
|
10
10
|
import { DiskFileService, S3FileService } from 'src/services/file';
|
|
11
|
+
import { classify } from 'src/helpers/string.helper';
|
|
11
12
|
import { MediaDownloadUrlService } from 'src/services/media-download-url.service';
|
|
12
13
|
|
|
13
14
|
|
|
@@ -16,11 +17,12 @@ import { BasicFilterDto } from 'src/dtos/basic-filters.dto';
|
|
|
16
17
|
import { MediaStorageProviderType } from 'src/dtos/create-media-storage-provider-metadata.dto';
|
|
17
18
|
import { Media } from 'src/entities/media.entity';
|
|
18
19
|
import { MediaStorageProviderMetadata } from 'src/entities/media-storage-provider-metadata.entity';
|
|
20
|
+
import { MediaFieldCrudManager, SolidMediaType } from 'src/helpers/field-crud-managers/MediaFieldCrudManager';
|
|
19
21
|
import { FieldMetadataRepository } from 'src/repository/field-metadata.repository';
|
|
20
22
|
import { MediaStorageProviderMetadataRepository } from 'src/repository/media-storage-provider-metadata.repository';
|
|
21
23
|
import { MediaRepository } from 'src/repository/media.repository';
|
|
22
24
|
import { ModelMetadataRepository } from 'src/repository/model-metadata.repository';
|
|
23
|
-
import { buildDiskMediaPath,
|
|
25
|
+
import { buildDiskMediaPath, getEffectiveS3Region, resolveMediaIsPublic, } from 'src/services/media-storage.utils';
|
|
24
26
|
import { getMediaStorageProvider } from "./mediaStorageProviders";
|
|
25
27
|
|
|
26
28
|
@Injectable()
|
|
@@ -103,40 +105,26 @@ export class MediaService extends CRUDService<Media> {
|
|
|
103
105
|
throw new NotFoundException('Media storage provider metadata not found');
|
|
104
106
|
}
|
|
105
107
|
|
|
106
|
-
|
|
107
|
-
for (let i = 0; i < files.length; i++) {
|
|
108
|
-
const file = files[i];
|
|
109
|
-
const storageProvider = createDto.mediaStorageProviderMetadata as MediaStorageProviderMetadata;
|
|
110
|
-
const fileName = buildStoredMediaFileName(file);
|
|
108
|
+
createDto['fieldMetadata'].mediaStorageProvider = createDto['mediaStorageProviderMetadata'];
|
|
111
109
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
110
|
+
const validator = new MediaFieldCrudManager({
|
|
111
|
+
type: createDto['fieldMetadata']?.type as SolidMediaType,
|
|
112
|
+
required: true,
|
|
113
|
+
fieldName: 'files',
|
|
114
|
+
mediaMaxSizeKb: createDto['fieldMetadata']?.mediaMaxSizeKb,
|
|
115
|
+
mediaTypes: createDto['fieldMetadata']?.mediaTypes || [],
|
|
116
|
+
mediaAllowedExtensions: createDto['fieldMetadata']?.mediaAllowedExtensions || [],
|
|
117
|
+
isUpdate: false,
|
|
118
|
+
});
|
|
119
|
+
const validationErrors = validator.validate(createDto, files);
|
|
120
|
+
if (validationErrors.length > 0) {
|
|
121
|
+
throw new BadRequestException(validationErrors.map(error => error.error).join(', '));
|
|
122
|
+
}
|
|
125
123
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
default:
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
// Delete temp file from disk
|
|
132
|
-
await this.diskFileService.delete(file.path);
|
|
124
|
+
const storageProviderType = createDto['mediaStorageProviderMetadata'].type as MediaStorageProviderType;
|
|
125
|
+
const storageProvider = await getMediaStorageProvider(this.moduleRef, storageProviderType);
|
|
133
126
|
|
|
134
|
-
|
|
135
|
-
const media = this.repo.create(createDto as Partial<Media>) as Media;
|
|
136
|
-
const savedMedia = await this.repo.save(media);
|
|
137
|
-
savedMedias.push(savedMedia)
|
|
138
|
-
}
|
|
139
|
-
return savedMedias
|
|
127
|
+
return storageProvider.store(files, { id: Number(createDto['entityId']) }, createDto['fieldMetadata']);
|
|
140
128
|
}
|
|
141
129
|
|
|
142
130
|
async remove(id: number) {
|
|
@@ -190,9 +178,13 @@ export class MediaService extends CRUDService<Media> {
|
|
|
190
178
|
async delete(id: number, solidRequestContext: any = {}) {
|
|
191
179
|
const media = await this.repo.findOne({
|
|
192
180
|
where: { id },
|
|
193
|
-
relations: ['mediaStorageProviderMetadata'],
|
|
181
|
+
relations: ['mediaStorageProviderMetadata', 'modelMetadata'],
|
|
194
182
|
});
|
|
195
183
|
|
|
184
|
+
if (media) {
|
|
185
|
+
await this.assertMediaDeletable([media]);
|
|
186
|
+
}
|
|
187
|
+
|
|
196
188
|
const result = await super.delete(id, solidRequestContext);
|
|
197
189
|
|
|
198
190
|
if (media) {
|
|
@@ -207,9 +199,11 @@ export class MediaService extends CRUDService<Media> {
|
|
|
207
199
|
where: {
|
|
208
200
|
id: In(ids),
|
|
209
201
|
},
|
|
210
|
-
relations: ['mediaStorageProviderMetadata'],
|
|
202
|
+
relations: ['mediaStorageProviderMetadata', 'modelMetadata'],
|
|
211
203
|
});
|
|
212
204
|
|
|
205
|
+
await this.assertMediaDeletable(mediaRecords);
|
|
206
|
+
|
|
213
207
|
const result = await super.deleteMany(ids, solidRequestContext);
|
|
214
208
|
|
|
215
209
|
for (const media of mediaRecords) {
|
|
@@ -219,6 +213,33 @@ export class MediaService extends CRUDService<Media> {
|
|
|
219
213
|
return result;
|
|
220
214
|
}
|
|
221
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Media belonging to a published draft/publish-enabled record must survive edits made to
|
|
218
|
+
* later drafts (see DraftPublishHelperService.cloneMediaForVersion) - deleting it directly
|
|
219
|
+
* would strip the published version's media out from under it. Mirrors the equivalent
|
|
220
|
+
* entity-level guard in DraftPublishHelperService.assertDraftPublishDeleteAllowed.
|
|
221
|
+
*/
|
|
222
|
+
private async assertMediaDeletable(mediaRecords: Media[]): Promise<void> {
|
|
223
|
+
const blockedIds: number[] = [];
|
|
224
|
+
|
|
225
|
+
for (const media of mediaRecords) {
|
|
226
|
+
if (!media.modelMetadata?.draftPublishWorkflow) continue;
|
|
227
|
+
|
|
228
|
+
const entityRepository = this.entityManager.getRepository(classify(media.modelMetadata.singularName));
|
|
229
|
+
const owningEntity = await entityRepository.findOne({ where: { id: media.entityId } as any });
|
|
230
|
+
|
|
231
|
+
if (owningEntity && (owningEntity as any).isPublished === true) {
|
|
232
|
+
blockedIds.push(media.id);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
if (blockedIds.length > 0) {
|
|
237
|
+
throw new BadRequestException(
|
|
238
|
+
'Media belonging to a published record cannot be deleted. Edit the record to create a draft first'
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
222
243
|
private async decorateMediaRecords(medias: Media[]): Promise<void> {
|
|
223
244
|
for (const media of medias) {
|
|
224
245
|
await this.decorateMediaRecord(media);
|
|
@@ -258,6 +279,17 @@ export class MediaService extends CRUDService<Media> {
|
|
|
258
279
|
}
|
|
259
280
|
|
|
260
281
|
try {
|
|
282
|
+
// Draft/publish versioning may clone a Media row that reuses the same
|
|
283
|
+
// relativeUri (see DraftPublishHelperService.cloneMediaForVersion) instead of
|
|
284
|
+
// duplicating the underlying file. Skip the physical delete if another row
|
|
285
|
+
// still references it.
|
|
286
|
+
const stillReferenced = await this.repo.exists({
|
|
287
|
+
where: { relativeUri: media.relativeUri, id: Not(media.id) },
|
|
288
|
+
});
|
|
289
|
+
if (stillReferenced) {
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
261
293
|
const mediaStorageProvider = await this.resolveMediaStorageProvider(media);
|
|
262
294
|
if (!mediaStorageProvider) {
|
|
263
295
|
return;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { BadRequestException, Injectable } from "@nestjs/common";
|
|
2
|
+
import { isNotEmpty, matches } from "class-validator";
|
|
3
|
+
import { ModelMetadataService } from "./model-metadata.service";
|
|
4
|
+
|
|
5
|
+
@Injectable()
|
|
6
|
+
export class MetadataValidationService {
|
|
7
|
+
constructor(
|
|
8
|
+
private readonly modelMetadataService: ModelMetadataService,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
async validateCreateDto(
|
|
12
|
+
modelName: string,
|
|
13
|
+
dto: object,
|
|
14
|
+
): Promise<void> {
|
|
15
|
+
const model = await this.modelMetadataService.findOneBySingularName(
|
|
16
|
+
modelName,
|
|
17
|
+
{ fields: true },
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
for (const field of model.fields ?? []) {
|
|
21
|
+
const value = (dto as Record<string, unknown>)[field.name];
|
|
22
|
+
|
|
23
|
+
if (!isNotEmpty(value) || typeof value !== "string") {
|
|
24
|
+
continue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
if (!isNotEmpty(field.regexPattern)) {
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (!matches(value, new RegExp(field.regexPattern))) {
|
|
32
|
+
throw new BadRequestException(
|
|
33
|
+
field.regexPatternNotMatchingErrorMsg ||
|
|
34
|
+
`Validation errors in ${field.name} is invalid i.e Field regex pattern is invalid`,
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -1729,7 +1729,10 @@ export class ModelMetadataService {
|
|
|
1729
1729
|
// --------------------
|
|
1730
1730
|
// Find record index in page
|
|
1731
1731
|
// --------------------
|
|
1732
|
-
const index = records.findIndex(r =>
|
|
1732
|
+
const index = records.findIndex(r =>
|
|
1733
|
+
String(r.id) === String(recordId) ||
|
|
1734
|
+
(r.initialEntityVersionId && String(r.initialEntityVersionId) === String(recordId))
|
|
1735
|
+
);
|
|
1733
1736
|
|
|
1734
1737
|
if (index === -1) {
|
|
1735
1738
|
throw new BadRequestException(`Record not found in current page`);
|
|
@@ -13,11 +13,13 @@ import { ConfigService } from '@nestjs/config';
|
|
|
13
13
|
import * as fs from 'fs/promises'; // Use the Promise-based version of fs for async/await
|
|
14
14
|
import * as path from 'path'; // To handle file paths
|
|
15
15
|
import { ERROR_MESSAGES } from 'src/constants/error-messages';
|
|
16
|
+
import { isDangerousMediaFile } from 'src/constants/media-file-types';
|
|
16
17
|
import { DisallowInProduction } from 'src/decorators/disallow-in-production.decorator';
|
|
17
18
|
import { ModuleMetadataHelperService } from 'src/helpers/module-metadata-helper.service';
|
|
18
19
|
import { ModuleMetadataRepository } from 'src/repository/module-metadata.repository';
|
|
19
20
|
import { PermissionMetadataSeederService } from 'src/seeders/permission-metadata-seeder.service';
|
|
20
21
|
import { DiskFileService } from 'src/services/file';
|
|
22
|
+
import { sanitizeStoredMediaFileName } from 'src/services/media-storage.utils';
|
|
21
23
|
import { BasicFilterDto } from '../dtos/basic-filters.dto';
|
|
22
24
|
import { UpdateModuleMetadataDto } from '../dtos/update-module-metadata.dto';
|
|
23
25
|
import {
|
|
@@ -136,6 +138,9 @@ export class ModuleMetadataService {
|
|
|
136
138
|
|
|
137
139
|
async createInDB(manager: EntityManager, createDto: CreateModuleMetadataDto, files: Express.Multer.File[] = []) {
|
|
138
140
|
if (files.length > 0) {
|
|
141
|
+
if (isDangerousMediaFile(files[0])) {
|
|
142
|
+
throw new BadRequestException('Dangerous file types are not allowed for the menu icon.');
|
|
143
|
+
}
|
|
139
144
|
const fileStoragePath = this.getFullFilePathForDisk(this.getFileName(files[0]));
|
|
140
145
|
this.fileService.copy(files[0].path, fileStoragePath);
|
|
141
146
|
this.fileService.delete(files[0].path);
|
|
@@ -240,6 +245,9 @@ export class ModuleMetadataService {
|
|
|
240
245
|
throw new NotFoundException(ERROR_MESSAGES.MODULE_ID_NOT_FOUND(id));
|
|
241
246
|
}
|
|
242
247
|
if (files.length > 0) {
|
|
248
|
+
if (isDangerousMediaFile(files[0])) {
|
|
249
|
+
throw new BadRequestException('Dangerous file types are not allowed for the menu icon.');
|
|
250
|
+
}
|
|
243
251
|
|
|
244
252
|
const fileStoragePath = this.getFullFilePathForDisk(this.getFileName(files[0]));
|
|
245
253
|
this.fileService.copy(files[0].path, fileStoragePath);
|
|
@@ -609,7 +617,8 @@ export class ModuleMetadataService {
|
|
|
609
617
|
}
|
|
610
618
|
|
|
611
619
|
private getFileName(file: Express.Multer.File): string {
|
|
612
|
-
|
|
620
|
+
// originalname is attacker-controlled and feeds straight into a storage path.
|
|
621
|
+
return `${file.filename}-${sanitizeStoredMediaFileName(file.originalname)}`;
|
|
613
622
|
}
|
|
614
623
|
|
|
615
624
|
}
|