@lilaquadrat/studio 9.20.3 → 10.0.0-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.
- package/lib/{cjs/errors.d.ts → errors.d.ts} +4 -4
- package/lib/errors.js +6 -0
- package/lib/errors.js.map +1 -0
- package/lib/{esm/frontend.d.ts → frontend.d.ts} +8 -7
- package/lib/frontend.js +9 -0
- package/lib/frontend.js.map +1 -0
- package/lib/helpers.d.ts +16 -0
- package/lib/helpers.js +17 -0
- package/lib/helpers.js.map +1 -0
- package/lib/main.d.ts +16 -0
- package/lib/main.js +17 -0
- package/lib/main.js.map +1 -0
- package/lib/models.d.ts +37 -0
- package/lib/models.js +38 -0
- package/lib/models.js.map +1 -0
- package/lib/services.d.ts +36 -0
- package/lib/services.js +45 -0
- package/lib/services.js.map +1 -0
- package/lib/{cjs/src → src}/AzureBlobStorage.share.d.ts +0 -1
- package/lib/{cjs/src → src}/AzureBlobStorage.share.js +22 -29
- package/lib/src/AzureBlobStorage.share.js.map +1 -0
- package/lib/{cjs/src → src}/AzureFileStorage.share.d.ts +1 -2
- package/lib/{cjs/src → src}/AzureFileStorage.share.js +11 -19
- package/lib/src/AzureFileStorage.share.js.map +1 -0
- package/lib/src/AzureVault.js +28 -0
- package/lib/src/AzureVault.js.map +1 -0
- package/lib/{cjs/src → src}/Filesystem.share.d.ts +1 -2
- package/lib/{cjs/src → src}/Filesystem.share.js +9 -15
- package/lib/src/Filesystem.share.js.map +1 -0
- package/lib/{cjs/src → src}/Immutable.class.d.ts +1 -1
- package/lib/{cjs/src → src}/Immutable.class.js +25 -32
- package/lib/src/Immutable.class.js.map +1 -0
- package/lib/{cjs/src → src}/Mock.share.d.ts +1 -2
- package/lib/{cjs/src → src}/Mock.share.js +1 -4
- package/lib/src/Mock.share.js.map +1 -0
- package/lib/{cjs/src → src}/ShareClientFactory.class.d.ts +3 -3
- package/lib/src/ShareClientFactory.class.js +26 -0
- package/lib/src/ShareClientFactory.class.js.map +1 -0
- package/lib/{cjs/src → src}/Timeseries.class.d.ts +2 -2
- package/lib/{cjs/src → src}/Timeseries.class.js +1 -4
- package/lib/src/Timeseries.class.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/childData.aggregation.js +3 -8
- package/lib/src/aggegations/childData.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/genericData.aggregation.js +1 -3
- package/lib/src/aggegations/genericData.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/partial.aggregation.js +1 -3
- package/lib/src/aggegations/partial.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/publishData.aggregation.js +1 -3
- package/lib/src/aggegations/publishData.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/resultData.aggregation.js +1 -3
- package/lib/src/aggegations/resultData.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/structures.aggregation.js +1 -5
- package/lib/src/aggegations/structures.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/aggegations/user.aggregation.js +1 -3
- package/lib/src/aggegations/user.aggregation.js.map +1 -0
- package/lib/{cjs/src → src}/classes/TimeseriesModel.class.d.ts +2 -2
- package/lib/{cjs/src → src}/classes/TimeseriesModel.class.js +4 -10
- package/lib/src/classes/TimeseriesModel.class.js.map +1 -0
- package/lib/{cjs/src → src}/classes/cache.class.d.ts +1 -1
- package/lib/{cjs/src → src}/classes/cache.class.js +5 -10
- package/lib/src/classes/cache.class.js.map +1 -0
- package/lib/src/classes/errors/Agreements.error.js +9 -0
- package/lib/src/classes/errors/Agreements.error.js.map +1 -0
- package/lib/src/classes/errors/Forbidden.error.js +7 -0
- package/lib/src/classes/errors/Forbidden.error.js.map +1 -0
- package/lib/src/classes/errors/History.error.js +9 -0
- package/lib/src/classes/errors/History.error.js.map +1 -0
- package/lib/src/classes/errors/Immutable.error.js +9 -0
- package/lib/src/classes/errors/Immutable.error.js.map +1 -0
- package/lib/src/classes/errors/InvalidId.error.js +9 -0
- package/lib/src/classes/errors/InvalidId.error.js.map +1 -0
- package/lib/{cjs/src → src}/classes/models.class.d.ts +3 -3
- package/lib/src/classes/models.class.js +40 -0
- package/lib/src/classes/models.class.js.map +1 -0
- package/lib/{cjs/src → src}/classes/modelv2.class.d.ts +4 -4
- package/lib/{cjs/src → src}/classes/modelv2.class.js +8 -14
- package/lib/src/classes/modelv2.class.js.map +1 -0
- package/lib/{cjs/src → src}/classes/mongo.class.js +18 -25
- package/lib/src/classes/mongo.class.js.map +1 -0
- package/lib/{cjs/src → src}/dns.challenge.class.js +12 -18
- package/lib/src/dns.challenge.class.js.map +1 -0
- package/lib/{cjs/src → src}/docker-compose.class.js +9 -15
- package/lib/src/docker-compose.class.js.map +1 -0
- package/lib/{cjs/src → src}/filterMergeModules.d.ts +1 -1
- package/lib/{cjs/src → src}/filterMergeModules.js +1 -3
- package/lib/src/filterMergeModules.js.map +1 -0
- package/lib/{cjs/src → src}/functions/handleError.d.ts +3 -3
- package/lib/{cjs/src → src}/functions/handleError.js +10 -16
- package/lib/src/functions/handleError.js.map +1 -0
- package/lib/{cjs/src → src}/functions/optionsHelper.js +1 -3
- package/lib/src/functions/optionsHelper.js.map +1 -0
- package/lib/{cjs/src → src}/functions/respondCode.d.ts +1 -1
- package/lib/src/functions/respondCode.js +3 -0
- package/lib/src/functions/respondCode.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/HttpStatusCode.enum.js +2 -6
- package/lib/src/helpers/HttpStatusCode.enum.js.map +1 -0
- package/lib/src/helpers/batch.d.ts +9 -0
- package/lib/src/helpers/batch.js +35 -0
- package/lib/src/helpers/batch.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/cleanObject.d.ts +1 -1
- package/lib/{cjs/src → src}/helpers/cleanObject.js +2 -3
- package/lib/src/helpers/cleanObject.js.map +1 -0
- package/lib/src/helpers/companyRights.js +13 -0
- package/lib/src/helpers/companyRights.js.map +1 -0
- package/lib/src/helpers/convertCountryISO2.js.map +1 -0
- package/lib/src/helpers/countries.js +8 -0
- package/lib/src/helpers/countries.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/createError.d.ts +1 -1
- package/lib/{cjs/src → src}/helpers/createError.js +1 -3
- package/lib/src/helpers/createError.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/createSasToken.js +8 -11
- package/lib/src/helpers/createSasToken.js.map +1 -0
- package/lib/src/helpers/filenameHelper.d.ts +9 -0
- package/lib/src/helpers/filenameHelper.js +15 -0
- package/lib/src/helpers/filenameHelper.js.map +1 -0
- package/lib/src/helpers/findObjetcsWithKeys.js.map +1 -0
- package/lib/src/helpers/getSecrets.js +15 -0
- package/lib/src/helpers/getSecrets.js.map +1 -0
- package/lib/src/helpers/hardCopy.js.map +1 -0
- package/lib/{esm/src → src}/helpers/isDeepEmpty.js +2 -0
- package/lib/src/helpers/isDeepEmpty.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/isValidObjectId.js +3 -6
- package/lib/src/helpers/isValidObjectId.js.map +1 -0
- package/lib/{cjs/src → src}/helpers/matchSortArray.js +1 -3
- package/lib/src/helpers/matchSortArray.js.map +1 -0
- package/lib/src/helpers/safeObjectId.js +13 -0
- package/lib/src/helpers/safeObjectId.js.map +1 -0
- package/lib/src/helpers/updateMappedId.js +5 -0
- package/lib/src/helpers/updateMappedId.js.map +1 -0
- package/lib/{cjs/src → src}/http.challenge.class.js +6 -12
- package/lib/src/http.challenge.class.js.map +1 -0
- package/lib/src/logger.js +124 -0
- package/lib/src/logger.js.map +1 -0
- package/lib/{cjs/src → src}/models/access.model.d.ts +1 -1
- package/lib/src/models/access.model.js +11 -0
- package/lib/src/models/access.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/app.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/app.model.js +3 -8
- package/lib/src/models/app.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/cache.model.d.ts +1 -1
- package/lib/src/models/cache.model.js +10 -0
- package/lib/src/models/cache.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/cart.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/cart.model.js +3 -8
- package/lib/src/models/cart.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/certificate-action.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/certificate-action.model.js +3 -8
- package/lib/src/models/certificate-action.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/certificate.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/certificate.model.js +3 -8
- package/lib/src/models/certificate.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/company.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/company.model.js +3 -8
- package/lib/src/models/company.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/customers.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/customers.model.js +4 -11
- package/lib/src/models/customers.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/domain.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/domain.model.js +3 -8
- package/lib/src/models/domain.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/editor.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/editor.model.js +3 -8
- package/lib/src/models/editor.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/editorBase.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/editorBase.model.js +3 -8
- package/lib/src/models/editorBase.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/history.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/history.model.js +3 -8
- package/lib/src/models/history.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/hosting.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/hosting.model.js +3 -8
- package/lib/src/models/hosting.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/hostingCommand.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/hostingCommand.model.js +3 -8
- package/lib/src/models/hostingCommand.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/hostingSettings.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/hostingSettings.model.js +3 -8
- package/lib/src/models/hostingSettings.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/id.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/id.model.js +3 -8
- package/lib/src/models/id.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/import.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/import.model.js +3 -8
- package/lib/src/models/import.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/lists.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/lists.model.js +3 -8
- package/lib/src/models/lists.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/listsParticipants.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/listsParticipants.model.js +4 -10
- package/lib/src/models/listsParticipants.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/logging.model.d.ts +1 -1
- package/lib/src/models/logging.model.js +12 -0
- package/lib/src/models/logging.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/mailFrom.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/mailFrom.model.js +3 -8
- package/lib/src/models/mailFrom.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/me.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/me.model.js +3 -8
- package/lib/src/models/me.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/payment-provider.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/payment-provider.model.js +3 -8
- package/lib/src/models/payment-provider.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/payment.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/payment.model.js +3 -8
- package/lib/src/models/payment.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/permissions.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/permissions.model.js +27 -13
- package/lib/src/models/permissions.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/project.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/project.model.js +3 -8
- package/lib/src/models/project.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/publish-method.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/publish-method.model.js +3 -8
- package/lib/src/models/publish-method.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/publish.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/publish.model.js +3 -8
- package/lib/src/models/publish.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/secrets.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/secrets.model.js +3 -8
- package/lib/src/models/secrets.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/settings.model.d.ts +1 -1
- package/lib/src/models/settings.model.js +16 -0
- package/lib/src/models/settings.model.js.map +1 -0
- package/lib/src/models/storage.model.d.ts +4 -0
- package/lib/src/models/storage.model.js +107 -0
- package/lib/src/models/storage.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/structure.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/structure.model.js +3 -8
- package/lib/src/models/structure.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/tracker.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/tracker.model.js +3 -8
- package/lib/src/models/tracker.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/universal.model.d.ts +1 -1
- package/lib/src/models/universal.model.js +4 -0
- package/lib/src/models/universal.model.js.map +1 -0
- package/lib/src/models/upload.model.d.ts +4 -0
- package/lib/src/models/upload.model.js +81 -0
- package/lib/src/models/upload.model.js.map +1 -0
- package/lib/{cjs/src → src}/models/webhook-call.model.d.ts +1 -1
- package/lib/{cjs/src → src}/models/webhook-call.model.js +3 -8
- package/lib/src/models/webhook-call.model.js.map +1 -0
- package/lib/{cjs/src → src}/nginx.class.js +6 -12
- package/lib/src/nginx.class.js.map +1 -0
- package/lib/{cjs/src → src}/prepareContent.d.ts +1 -1
- package/lib/{cjs/src → src}/prepareContent.js +10 -18
- package/lib/src/prepareContent.js.map +1 -0
- package/lib/{cjs/src → src}/prompts/textGeneration.js +1 -4
- package/lib/src/prompts/textGeneration.js.map +1 -0
- package/lib/{cjs/src → src}/prompts/textGenerationMulti.js +1 -4
- package/lib/src/prompts/textGenerationMulti.js.map +1 -0
- package/lib/{cjs/src → src}/services/access.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/access.service.js +11 -17
- package/lib/src/services/access.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/ai.service.d.ts +1 -1
- package/lib/{cjs/src → src}/services/ai.service.js +22 -27
- package/lib/src/services/ai.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/cart.service.d.ts +1 -1
- package/lib/{cjs/src → src}/services/cart.service.js +19 -26
- package/lib/src/services/cart.service.js.map +1 -0
- package/lib/src/services/certificates.service.d.ts +0 -0
- package/lib/src/services/certificates.service.js +199 -0
- package/lib/src/services/certificates.service.js.map +1 -0
- package/lib/src/services/certificatesAction.service.d.ts +0 -0
- package/lib/src/services/certificatesAction.service.js +237 -0
- package/lib/src/services/certificatesAction.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/conf.service.d.ts +1 -2
- package/lib/{cjs/src → src}/services/conf.service.js +16 -23
- package/lib/src/services/conf.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/customers.service.d.ts +3 -3
- package/lib/{cjs/src → src}/services/customers.service.js +36 -67
- package/lib/src/services/customers.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/domains.service.d.ts +8 -15
- package/lib/{cjs/src → src}/services/domains.service.js +89 -70
- package/lib/src/services/domains.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/editor.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/editor.service.js +28 -33
- package/lib/src/services/editor.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/editorBase.service.d.ts +2 -3
- package/lib/{cjs/src → src}/services/editorBase.service.js +25 -27
- package/lib/src/services/editorBase.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/handleFile.service.d.ts +0 -1
- package/lib/{cjs/src → src}/services/handleFile.service.js +10 -17
- package/lib/src/services/handleFile.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/history.service.d.ts +1 -1
- package/lib/{cjs/src → src}/services/history.service.js +14 -20
- package/lib/src/services/history.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/hosting.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/hosting.service.js +39 -44
- package/lib/src/services/hosting.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/hostingAdmin.service.d.ts +2 -2
- package/lib/src/services/hostingAdmin.service.js +16 -0
- package/lib/src/services/hostingAdmin.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/hostingCommands.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/hostingCommands.service.js +5 -10
- package/lib/src/services/hostingCommands.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/id.service.d.ts +1 -1
- package/lib/src/services/id.service.js +18 -0
- package/lib/src/services/id.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/import.service.d.ts +4 -4
- package/lib/{cjs/src → src}/services/import.service.js +17 -22
- package/lib/src/services/import.service.js.map +1 -0
- package/lib/src/services/jetstream.service.d.ts +21 -0
- package/lib/src/services/jetstream.service.js +93 -0
- package/lib/src/services/jetstream.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/listParticipants.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/listParticipants.service.js +68 -75
- package/lib/src/services/listParticipants.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/lists.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/lists.service.js +16 -23
- package/lib/src/services/lists.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/logging.service.d.ts +1 -1
- package/lib/src/services/logging.service.js +15 -0
- package/lib/src/services/logging.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/mailFrom.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/mailFrom.service.js +6 -13
- package/lib/src/services/mailFrom.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/me.service.d.ts +26 -7
- package/lib/{cjs/src → src}/services/me.service.js +78 -36
- package/lib/src/services/me.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/media.service.d.ts +5 -6
- package/lib/{cjs/src → src}/services/media.service.js +26 -30
- package/lib/src/services/media.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/paymentProviders.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/paymentProviders.service.js +5 -12
- package/lib/src/services/paymentProviders.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/payments.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/payments.service.js +12 -19
- package/lib/src/services/payments.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/permissions.service.d.ts +3 -3
- package/lib/{cjs/src → src}/services/permissions.service.js +23 -53
- package/lib/src/services/permissions.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/publish.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/publish.service.js +30 -37
- package/lib/src/services/publish.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/publishData.service.d.ts +3 -3
- package/lib/{cjs/src → src}/services/publishData.service.js +37 -30
- package/lib/src/services/publishData.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/publishMethod.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/publishMethod.service.js +5 -12
- package/lib/src/services/publishMethod.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/secret.service.d.ts +2 -2
- package/lib/src/services/secret.service.js +43 -0
- package/lib/src/services/secret.service.js.map +1 -0
- package/lib/src/services/share.service.d.ts +6 -0
- package/lib/src/services/share.service.js +4 -0
- package/lib/src/services/share.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/spamAnalasys.service.js +6 -13
- package/lib/src/services/spamAnalasys.service.js.map +1 -0
- package/lib/src/services/storage.service.d.ts +191 -0
- package/lib/src/services/storage.service.js +881 -0
- package/lib/src/services/storage.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/structures.service.d.ts +2 -3
- package/lib/{cjs/src → src}/services/structures.service.js +12 -19
- package/lib/src/services/structures.service.js.map +1 -0
- package/lib/src/services/universal.service.d.ts +0 -0
- package/lib/src/services/universal.service.js +167 -0
- package/lib/src/services/universal.service.js.map +1 -0
- package/lib/src/services/upload.service.d.ts +11 -0
- package/lib/src/services/upload.service.js +65 -0
- package/lib/src/services/upload.service.js.map +1 -0
- package/lib/{cjs/src → src}/services/webhooks-calls.service.d.ts +2 -2
- package/lib/{cjs/src → src}/services/webhooks-calls.service.js +8 -15
- package/lib/src/services/webhooks-calls.service.js.map +1 -0
- package/lib/{cjs/tests → tests}/editorService.spec.js +6 -11
- package/lib/tests/editorService.spec.js.map +1 -0
- package/lib/{cjs/tests → tests}/getUnsetObject.spec.js +8 -13
- package/lib/tests/getUnsetObject.spec.js.map +1 -0
- package/package.json +73 -34
- package/lib/cjs/errors.js +0 -15
- package/lib/cjs/errors.js.map +0 -1
- package/lib/cjs/helpers.d.ts +0 -14
- package/lib/cjs/helpers.js +0 -36
- package/lib/cjs/helpers.js.map +0 -1
- package/lib/cjs/main.d.ts +0 -17
- package/lib/cjs/main.js +0 -63
- package/lib/cjs/main.js.map +0 -1
- package/lib/cjs/models.d.ts +0 -36
- package/lib/cjs/models.js +0 -77
- package/lib/cjs/models.js.map +0 -1
- package/lib/cjs/services.d.ts +0 -36
- package/lib/cjs/services.js +0 -101
- package/lib/cjs/services.js.map +0 -1
- package/lib/cjs/src/AzureBlobStorage.share.js.map +0 -1
- package/lib/cjs/src/AzureFileStorage.share.js.map +0 -1
- package/lib/cjs/src/AzureVault.js +0 -30
- package/lib/cjs/src/AzureVault.js.map +0 -1
- package/lib/cjs/src/Filesystem.share.js.map +0 -1
- package/lib/cjs/src/Immutable.class.js.map +0 -1
- package/lib/cjs/src/Mock.share.js.map +0 -1
- package/lib/cjs/src/ShareClientFactory.class.js +0 -34
- package/lib/cjs/src/ShareClientFactory.class.js.map +0 -1
- package/lib/cjs/src/Timeseries.class.js.map +0 -1
- package/lib/cjs/src/aggegations/childData.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/genericData.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/partial.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/publishData.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/resultData.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/structures.aggregation.js.map +0 -1
- package/lib/cjs/src/aggegations/user.aggregation.js.map +0 -1
- package/lib/cjs/src/classes/ControllerBase.class.d.ts +0 -115
- package/lib/cjs/src/classes/ControllerBase.class.js +0 -274
- package/lib/cjs/src/classes/ControllerBase.class.js.map +0 -1
- package/lib/cjs/src/classes/TimeseriesModel.class.js.map +0 -1
- package/lib/cjs/src/classes/cache.class.js.map +0 -1
- package/lib/cjs/src/classes/errors/Agreements.error.js +0 -12
- package/lib/cjs/src/classes/errors/Agreements.error.js.map +0 -1
- package/lib/cjs/src/classes/errors/Forbidden.error.js +0 -10
- package/lib/cjs/src/classes/errors/Forbidden.error.js.map +0 -1
- package/lib/cjs/src/classes/errors/History.error.js +0 -12
- package/lib/cjs/src/classes/errors/History.error.js.map +0 -1
- package/lib/cjs/src/classes/errors/Immutable.error.js +0 -12
- package/lib/cjs/src/classes/errors/Immutable.error.js.map +0 -1
- package/lib/cjs/src/classes/errors/InvalidId.error.js +0 -12
- package/lib/cjs/src/classes/errors/InvalidId.error.js.map +0 -1
- package/lib/cjs/src/classes/models.class.js +0 -46
- package/lib/cjs/src/classes/models.class.js.map +0 -1
- package/lib/cjs/src/classes/modelv2.class.js.map +0 -1
- package/lib/cjs/src/classes/mongo.class.js.map +0 -1
- package/lib/cjs/src/dns.challenge.class.js.map +0 -1
- package/lib/cjs/src/docker-compose.class.js.map +0 -1
- package/lib/cjs/src/filterMergeModules.js.map +0 -1
- package/lib/cjs/src/functions/handleError.js.map +0 -1
- package/lib/cjs/src/functions/optionsHelper.js.map +0 -1
- package/lib/cjs/src/functions/respondCode.js +0 -5
- package/lib/cjs/src/functions/respondCode.js.map +0 -1
- package/lib/cjs/src/helpers/HttpStatusCode.enum.js.map +0 -1
- package/lib/cjs/src/helpers/cleanObject.js.map +0 -1
- package/lib/cjs/src/helpers/companyRights.js +0 -18
- package/lib/cjs/src/helpers/companyRights.js.map +0 -1
- package/lib/cjs/src/helpers/convertCountryISO2.js +0 -248
- package/lib/cjs/src/helpers/convertCountryISO2.js.map +0 -1
- package/lib/cjs/src/helpers/countries.js +0 -14
- package/lib/cjs/src/helpers/countries.js.map +0 -1
- package/lib/cjs/src/helpers/createError.js.map +0 -1
- package/lib/cjs/src/helpers/createSasToken.js.map +0 -1
- package/lib/cjs/src/helpers/findObjetcsWithKeys.js +0 -34
- package/lib/cjs/src/helpers/findObjetcsWithKeys.js.map +0 -1
- package/lib/cjs/src/helpers/getSecrets.js +0 -20
- package/lib/cjs/src/helpers/getSecrets.js.map +0 -1
- package/lib/cjs/src/helpers/hardCopy.js +0 -5
- package/lib/cjs/src/helpers/hardCopy.js.map +0 -1
- package/lib/cjs/src/helpers/isDeepEmpty.js +0 -23
- package/lib/cjs/src/helpers/isDeepEmpty.js.map +0 -1
- package/lib/cjs/src/helpers/isValidObjectId.js.map +0 -1
- package/lib/cjs/src/helpers/matchSortArray.js.map +0 -1
- package/lib/cjs/src/helpers/safeObjectId.js +0 -18
- package/lib/cjs/src/helpers/safeObjectId.js.map +0 -1
- package/lib/cjs/src/helpers/updateMappedId.js +0 -8
- package/lib/cjs/src/helpers/updateMappedId.js.map +0 -1
- package/lib/cjs/src/http.challenge.class.js.map +0 -1
- package/lib/cjs/src/logger.js +0 -45
- package/lib/cjs/src/logger.js.map +0 -1
- package/lib/cjs/src/models/access.model.js +0 -16
- package/lib/cjs/src/models/access.model.js.map +0 -1
- package/lib/cjs/src/models/app.model.js.map +0 -1
- package/lib/cjs/src/models/cache.model.js +0 -15
- package/lib/cjs/src/models/cache.model.js.map +0 -1
- package/lib/cjs/src/models/cart.model.js.map +0 -1
- package/lib/cjs/src/models/certificate-action.model.js.map +0 -1
- package/lib/cjs/src/models/certificate.model.js.map +0 -1
- package/lib/cjs/src/models/company.model.js.map +0 -1
- package/lib/cjs/src/models/customers.model.js.map +0 -1
- package/lib/cjs/src/models/domain.model.js.map +0 -1
- package/lib/cjs/src/models/editor.model.js.map +0 -1
- package/lib/cjs/src/models/editorBase.model.js.map +0 -1
- package/lib/cjs/src/models/history.model.js.map +0 -1
- package/lib/cjs/src/models/hosting.model.js.map +0 -1
- package/lib/cjs/src/models/hostingCommand.model.js.map +0 -1
- package/lib/cjs/src/models/hostingSettings.model.js.map +0 -1
- package/lib/cjs/src/models/id.model.js.map +0 -1
- package/lib/cjs/src/models/import.model.js.map +0 -1
- package/lib/cjs/src/models/lists.model.js.map +0 -1
- package/lib/cjs/src/models/listsParticipants.model.js.map +0 -1
- package/lib/cjs/src/models/logging.model.js +0 -17
- package/lib/cjs/src/models/logging.model.js.map +0 -1
- package/lib/cjs/src/models/mailFrom.model.js.map +0 -1
- package/lib/cjs/src/models/me.model.js.map +0 -1
- package/lib/cjs/src/models/media.model.d.ts +0 -4
- package/lib/cjs/src/models/media.model.js +0 -139
- package/lib/cjs/src/models/media.model.js.map +0 -1
- package/lib/cjs/src/models/payment-provider.model.js.map +0 -1
- package/lib/cjs/src/models/payment.model.js.map +0 -1
- package/lib/cjs/src/models/permissions.model.js.map +0 -1
- package/lib/cjs/src/models/project.model.js.map +0 -1
- package/lib/cjs/src/models/publish-method.model.js.map +0 -1
- package/lib/cjs/src/models/publish.model.js.map +0 -1
- package/lib/cjs/src/models/secrets.model.js.map +0 -1
- package/lib/cjs/src/models/settings.model.js +0 -21
- package/lib/cjs/src/models/settings.model.js.map +0 -1
- package/lib/cjs/src/models/structure.model.js.map +0 -1
- package/lib/cjs/src/models/tracker.model.js.map +0 -1
- package/lib/cjs/src/models/universal.model.js +0 -9
- package/lib/cjs/src/models/universal.model.js.map +0 -1
- package/lib/cjs/src/models/webhook-call.model.js.map +0 -1
- package/lib/cjs/src/nginx.class.js.map +0 -1
- package/lib/cjs/src/prepareContent.js.map +0 -1
- package/lib/cjs/src/prompts/textGeneration.js.map +0 -1
- package/lib/cjs/src/prompts/textGenerationMulti.js.map +0 -1
- package/lib/cjs/src/services/access.service.js.map +0 -1
- package/lib/cjs/src/services/ai.service.js.map +0 -1
- package/lib/cjs/src/services/cart.service.js.map +0 -1
- package/lib/cjs/src/services/certificates.service.d.ts +0 -58
- package/lib/cjs/src/services/certificates.service.js +0 -177
- package/lib/cjs/src/services/certificates.service.js.map +0 -1
- package/lib/cjs/src/services/certificatesAction.service.d.ts +0 -41
- package/lib/cjs/src/services/certificatesAction.service.js +0 -195
- package/lib/cjs/src/services/certificatesAction.service.js.map +0 -1
- package/lib/cjs/src/services/conf.service.js.map +0 -1
- package/lib/cjs/src/services/customers.service.js.map +0 -1
- package/lib/cjs/src/services/domains.service.js.map +0 -1
- package/lib/cjs/src/services/editor.service.js.map +0 -1
- package/lib/cjs/src/services/editorBase.service.js.map +0 -1
- package/lib/cjs/src/services/handleFile.service.js.map +0 -1
- package/lib/cjs/src/services/history.service.js.map +0 -1
- package/lib/cjs/src/services/hosting.service.js.map +0 -1
- package/lib/cjs/src/services/hostingAdmin.service.js +0 -21
- package/lib/cjs/src/services/hostingAdmin.service.js.map +0 -1
- package/lib/cjs/src/services/hostingCommands.service.js.map +0 -1
- package/lib/cjs/src/services/id.service.js +0 -24
- package/lib/cjs/src/services/id.service.js.map +0 -1
- package/lib/cjs/src/services/import.service.js.map +0 -1
- package/lib/cjs/src/services/listParticipants.service.js.map +0 -1
- package/lib/cjs/src/services/lists.service.js.map +0 -1
- package/lib/cjs/src/services/logging.service.js +0 -22
- package/lib/cjs/src/services/logging.service.js.map +0 -1
- package/lib/cjs/src/services/mailFrom.service.js.map +0 -1
- package/lib/cjs/src/services/me.service.js.map +0 -1
- package/lib/cjs/src/services/media.service.js.map +0 -1
- package/lib/cjs/src/services/paymentProviders.service.js.map +0 -1
- package/lib/cjs/src/services/payments.service.js.map +0 -1
- package/lib/cjs/src/services/permissions.service.js.map +0 -1
- package/lib/cjs/src/services/publish.service.js.map +0 -1
- package/lib/cjs/src/services/publishData.service.js.map +0 -1
- package/lib/cjs/src/services/publishMethod.service.js.map +0 -1
- package/lib/cjs/src/services/secret.service.js +0 -50
- package/lib/cjs/src/services/secret.service.js.map +0 -1
- package/lib/cjs/src/services/share.service.d.ts +0 -11
- package/lib/cjs/src/services/share.service.js +0 -24
- package/lib/cjs/src/services/share.service.js.map +0 -1
- package/lib/cjs/src/services/spamAnalasys.service.js.map +0 -1
- package/lib/cjs/src/services/structures.service.js.map +0 -1
- package/lib/cjs/src/services/universal.service.d.ts +0 -17
- package/lib/cjs/src/services/universal.service.js +0 -145
- package/lib/cjs/src/services/universal.service.js.map +0 -1
- package/lib/cjs/src/services/webhooks-calls.service.js.map +0 -1
- package/lib/cjs/tests/editorService.spec.js.map +0 -1
- package/lib/cjs/tests/getUnsetObject.spec.js.map +0 -1
- package/lib/esm/frontend.js +0 -8
- package/lib/esm/frontend.js.map +0 -1
- package/lib/esm/src/filterMergeModules.d.ts +0 -3
- package/lib/esm/src/filterMergeModules.js +0 -29
- package/lib/esm/src/filterMergeModules.js.map +0 -1
- package/lib/esm/src/helpers/convertCountryISO2.d.ts +0 -2
- package/lib/esm/src/helpers/convertCountryISO2.js.map +0 -1
- package/lib/esm/src/helpers/findObjetcsWithKeys.d.ts +0 -13
- package/lib/esm/src/helpers/findObjetcsWithKeys.js.map +0 -1
- package/lib/esm/src/helpers/hardCopy.d.ts +0 -2
- package/lib/esm/src/helpers/hardCopy.js.map +0 -1
- package/lib/esm/src/helpers/isDeepEmpty.d.ts +0 -1
- package/lib/esm/src/helpers/isDeepEmpty.js.map +0 -1
- package/lib/esm/src/prepareContent.d.ts +0 -7
- package/lib/esm/src/prepareContent.js +0 -83
- package/lib/esm/src/prepareContent.js.map +0 -1
- /package/lib/{cjs/src → src}/AzureVault.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/childData.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/genericData.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/partial.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/publishData.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/resultData.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/structures.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/aggegations/user.aggregation.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/errors/Agreements.error.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/errors/Forbidden.error.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/errors/History.error.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/errors/Immutable.error.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/errors/InvalidId.error.d.ts +0 -0
- /package/lib/{cjs/src → src}/classes/mongo.class.d.ts +0 -0
- /package/lib/{cjs/src → src}/dns.challenge.class.d.ts +0 -0
- /package/lib/{cjs/src → src}/docker-compose.class.d.ts +0 -0
- /package/lib/{cjs/src → src}/functions/optionsHelper.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/HttpStatusCode.enum.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/companyRights.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/convertCountryISO2.d.ts +0 -0
- /package/lib/{esm/src → src}/helpers/convertCountryISO2.js +0 -0
- /package/lib/{cjs/src → src}/helpers/countries.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/createSasToken.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/findObjetcsWithKeys.d.ts +0 -0
- /package/lib/{esm/src → src}/helpers/findObjetcsWithKeys.js +0 -0
- /package/lib/{cjs/src → src}/helpers/getSecrets.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/hardCopy.d.ts +0 -0
- /package/lib/{esm/src → src}/helpers/hardCopy.js +0 -0
- /package/lib/{cjs/src → src}/helpers/isDeepEmpty.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/isValidObjectId.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/matchSortArray.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/safeObjectId.d.ts +0 -0
- /package/lib/{cjs/src → src}/helpers/updateMappedId.d.ts +0 -0
- /package/lib/{cjs/src → src}/http.challenge.class.d.ts +0 -0
- /package/lib/{cjs/src → src}/logger.d.ts +0 -0
- /package/lib/{cjs/src → src}/nginx.class.d.ts +0 -0
- /package/lib/{cjs/src → src}/prompts/textGeneration.d.ts +0 -0
- /package/lib/{cjs/src → src}/prompts/textGenerationMulti.d.ts +0 -0
- /package/lib/{cjs/src → src}/services/spamAnalasys.service.d.ts +0 -0
- /package/lib/{cjs/tests → tests}/editorService.spec.d.ts +0 -0
- /package/lib/{cjs/tests → tests}/getUnsetObject.spec.d.ts +0 -0
|
@@ -0,0 +1,881 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import { pipeline } from 'stream/promises';
|
|
3
|
+
import { createHash, createHmac } from 'crypto';
|
|
4
|
+
import { mkdir } from 'fs/promises';
|
|
5
|
+
import { spawn } from 'child_process';
|
|
6
|
+
import Immutable from '../Immutable.class.js';
|
|
7
|
+
import StorageModel from '../models/storage.model.js';
|
|
8
|
+
import JetStreamService from './jetstream.service.js';
|
|
9
|
+
import UploadService from './upload.service.js';
|
|
10
|
+
import filenameHelper from '../helpers/filenameHelper.js';
|
|
11
|
+
export class StorageService extends Immutable {
|
|
12
|
+
constructor(options) {
|
|
13
|
+
super();
|
|
14
|
+
this.buckets = {
|
|
15
|
+
cdn: {
|
|
16
|
+
public: true,
|
|
17
|
+
overwrite: false,
|
|
18
|
+
cache: 31536000,
|
|
19
|
+
},
|
|
20
|
+
hosting: {
|
|
21
|
+
public: false,
|
|
22
|
+
overwrite: true,
|
|
23
|
+
cache: 0,
|
|
24
|
+
},
|
|
25
|
+
secure: {
|
|
26
|
+
public: false,
|
|
27
|
+
overwrite: false,
|
|
28
|
+
cache: 31536000,
|
|
29
|
+
},
|
|
30
|
+
internal: {
|
|
31
|
+
public: false,
|
|
32
|
+
overwrite: false,
|
|
33
|
+
cache: 31536000,
|
|
34
|
+
},
|
|
35
|
+
};
|
|
36
|
+
this.model = StorageModel;
|
|
37
|
+
this.options = options;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Generates a secure, time-limited token for accessing files in secure storage buckets.
|
|
41
|
+
*
|
|
42
|
+
* The token is cryptographically signed using HMAC-SHA256 and base64url-encoded to be
|
|
43
|
+
* non-human readable and URL-safe.
|
|
44
|
+
*
|
|
45
|
+
* @param fileId - The file identifier (ObjectId or string) to grant access to
|
|
46
|
+
* @param expiresIn - Time in seconds until the token expires (default: 3600 = 1 hour)
|
|
47
|
+
* @param limits - Optional restrictions to apply to the token
|
|
48
|
+
* @param limits.company - Restrict token to specific company
|
|
49
|
+
* @param limits.project - Restrict token to specific project
|
|
50
|
+
* @param limits.app - Restrict token to specific app
|
|
51
|
+
* @param limits.url - Restrict token to specific URL path prefix
|
|
52
|
+
* @param limits.prefix - Restrict token to specific file prefix
|
|
53
|
+
*
|
|
54
|
+
* @returns Base64url-encoded token containing: fileId:expires[:limits]:signature
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Generate token valid for 1 hour with no restrictions
|
|
58
|
+
* const { token } = getSecureToken('507f1f77bcf86cd799439011', 3600);
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Generate token limited to specific company and project
|
|
62
|
+
* const { token } = getSecureToken('507f1f77bcf86cd799439011', 3600, {
|
|
63
|
+
* company: 'acme',
|
|
64
|
+
* project: 'website'
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* // Generate token limited to specific URL path
|
|
69
|
+
* const { token } = getSecureToken('507f1f77bcf86cd799439011', 3600, {
|
|
70
|
+
* url: '/company/project/files/'
|
|
71
|
+
* });
|
|
72
|
+
*/
|
|
73
|
+
getSecureToken(fileId, expiresIn = 3600, limits) {
|
|
74
|
+
const secret = process.env.SERVER_SECRET || 'secret';
|
|
75
|
+
const now = Math.floor(Date.now() / 1000);
|
|
76
|
+
const expires = now + expiresIn;
|
|
77
|
+
// Build payload: fileId:expires[:base64(limits)]
|
|
78
|
+
let payload = `${fileId}:${expires}`;
|
|
79
|
+
if (limits && Object.keys(limits).length > 0) {
|
|
80
|
+
// Base64 encode the JSON to avoid : separator conflicts
|
|
81
|
+
const limitsJson = JSON.stringify(limits);
|
|
82
|
+
const limitsBase64 = Buffer.from(limitsJson).toString('base64');
|
|
83
|
+
payload += `:${limitsBase64}`;
|
|
84
|
+
}
|
|
85
|
+
// Sign the payload with HMAC-SHA256
|
|
86
|
+
const signature = createHmac('sha256', secret).update(payload).digest('hex');
|
|
87
|
+
const combined = `${payload}:${signature}`;
|
|
88
|
+
// Encode as base64url for URL-safe, non-human readable format
|
|
89
|
+
const token = Buffer.from(combined).toString('base64url');
|
|
90
|
+
return {
|
|
91
|
+
token,
|
|
92
|
+
expiresIn,
|
|
93
|
+
createdAt: now,
|
|
94
|
+
expiresAt: expires,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Validates a secure token and optionally checks if it matches provided limits.
|
|
99
|
+
*
|
|
100
|
+
* Performs validations:
|
|
101
|
+
* 1. Signature verification using HMAC-SHA256
|
|
102
|
+
* 2. Expiration timestamp check
|
|
103
|
+
* 3. Optional limit validation against provided check values
|
|
104
|
+
*
|
|
105
|
+
* @param token - The base64url-encoded token to validate
|
|
106
|
+
* @param checkLimits - Optional values to verify against token's restrictions
|
|
107
|
+
* @param checkLimits.company - Company to check against token limit
|
|
108
|
+
* @param checkLimits.project - Project to check against token limit
|
|
109
|
+
* @param checkLimits.app - App to check against token limit
|
|
110
|
+
* @param checkLimits.url - URL path to check against token limit
|
|
111
|
+
* @param checkLimits.prefix - File prefix to check against token limit
|
|
112
|
+
*
|
|
113
|
+
* @returns true if token is valid and all checks pass, false otherwise
|
|
114
|
+
*
|
|
115
|
+
* @example
|
|
116
|
+
* // Validate token without checking limits
|
|
117
|
+
* const isValid = validateSecureToken(token);
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* // Validate token and check company/project access
|
|
121
|
+
* const isValid = validateSecureToken(token, {
|
|
122
|
+
* company: 'acme',
|
|
123
|
+
* project: 'website'
|
|
124
|
+
* });
|
|
125
|
+
*/
|
|
126
|
+
validateSecureToken(token, checkLimits) {
|
|
127
|
+
const secret = process.env.SERVER_SECRET || 'secret';
|
|
128
|
+
let decoded;
|
|
129
|
+
// Decode from base64url format
|
|
130
|
+
try {
|
|
131
|
+
decoded = Buffer.from(token, 'base64url').toString('utf-8');
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
// Extract payload and signature (signature is after last colon)
|
|
137
|
+
const lastColonIndex = decoded.lastIndexOf(':');
|
|
138
|
+
if (lastColonIndex === -1)
|
|
139
|
+
return false;
|
|
140
|
+
const payload = decoded.substring(0, lastColonIndex);
|
|
141
|
+
const signature = decoded.substring(lastColonIndex + 1);
|
|
142
|
+
// Verify signature matches expected HMAC
|
|
143
|
+
const expectedSignature = createHmac('sha256', secret).update(payload).digest('hex');
|
|
144
|
+
if (signature !== expectedSignature)
|
|
145
|
+
return false;
|
|
146
|
+
// Parse payload structure: fileId:expires[:base64(limits)]
|
|
147
|
+
const parts = payload.split(':');
|
|
148
|
+
// parts[0] is fileId
|
|
149
|
+
// parts[1] is expires timestamp
|
|
150
|
+
// parts[2] is optional base64-encoded JSON limits object
|
|
151
|
+
if (parts.length < 2)
|
|
152
|
+
return false;
|
|
153
|
+
// Check if token has expired
|
|
154
|
+
const expires = parseInt(parts[1], 10);
|
|
155
|
+
if (Date.now() / 1000 > expires)
|
|
156
|
+
return false;
|
|
157
|
+
// If token has limits, validate against checkLimits
|
|
158
|
+
if (parts.length > 2) {
|
|
159
|
+
let tokenLimits;
|
|
160
|
+
try {
|
|
161
|
+
// Decode from base64 first, then parse JSON
|
|
162
|
+
const limitsJson = Buffer.from(parts[2], 'base64').toString('utf-8');
|
|
163
|
+
tokenLimits = JSON.parse(limitsJson);
|
|
164
|
+
}
|
|
165
|
+
catch {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
// Token has limits but no values provided to check
|
|
169
|
+
if (!checkLimits)
|
|
170
|
+
return false;
|
|
171
|
+
// Validate each limit field if present in token
|
|
172
|
+
if (tokenLimits.company && tokenLimits.company !== checkLimits.company)
|
|
173
|
+
return false;
|
|
174
|
+
if (tokenLimits.project && tokenLimits.project !== checkLimits.project)
|
|
175
|
+
return false;
|
|
176
|
+
if (tokenLimits.app && tokenLimits.app !== checkLimits.app)
|
|
177
|
+
return false;
|
|
178
|
+
if (tokenLimits.prefix && tokenLimits.prefix !== checkLimits.prefix)
|
|
179
|
+
return false;
|
|
180
|
+
// For URL limit, check if requested URL starts with the token's allowed prefix
|
|
181
|
+
if (tokenLimits.url && checkLimits.url && !checkLimits.url.startsWith(tokenLimits.url))
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
else if (checkLimits) {
|
|
185
|
+
return false;
|
|
186
|
+
}
|
|
187
|
+
return true;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Creates a secure download URL with time-limited token for a storage file.
|
|
191
|
+
*
|
|
192
|
+
* @param fileId - The ObjectId of the storage document
|
|
193
|
+
* @param options - Required options containing company, project
|
|
194
|
+
* @param expiresIn - Time in seconds until the token expires (default: 3600 = 1 hour)
|
|
195
|
+
* @param limits - Optional additional restrictions for the token
|
|
196
|
+
*
|
|
197
|
+
* @returns Object containing the full download URL with token and expiration timestamp
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* const download = await createSecureDownload(
|
|
201
|
+
* new ObjectId('507f1f77bcf86cd799439011'),
|
|
202
|
+
* { company: 'acme', project: 'website' },
|
|
203
|
+
* 3600
|
|
204
|
+
* );
|
|
205
|
+
* // Returns: { url: 'https://...?token=...', expiresAt: 1234567890 }
|
|
206
|
+
*/
|
|
207
|
+
async createSecureDownload(fileId, options, expiresIn = 3600, limits) {
|
|
208
|
+
// Fetch storage document to get file details
|
|
209
|
+
const storage = await this.getByInternalId(fileId, options);
|
|
210
|
+
if (!storage)
|
|
211
|
+
throw new Error('STORAGE_FILE_NOT_FOUND');
|
|
212
|
+
// Merge provided limits with storage document context
|
|
213
|
+
const tokenLimits = {
|
|
214
|
+
company: limits?.company || storage.company,
|
|
215
|
+
project: limits?.project || storage.project,
|
|
216
|
+
app: limits?.app || storage.app,
|
|
217
|
+
prefix: limits?.prefix || storage.prefix,
|
|
218
|
+
url: limits?.url,
|
|
219
|
+
};
|
|
220
|
+
// Generate secure token
|
|
221
|
+
const tokenData = this.getSecureToken(fileId, expiresIn, tokenLimits);
|
|
222
|
+
// Construct download URL
|
|
223
|
+
const baseUrl = process.env.SECURE_URL;
|
|
224
|
+
const path = storage.prefix ? `${storage.prefix}/${storage.filename}` : storage.filename;
|
|
225
|
+
const url = `${baseUrl}/${storage.app}/${storage.company}/${storage.project}/${path}?token=${tokenData.token}`;
|
|
226
|
+
return {
|
|
227
|
+
url,
|
|
228
|
+
expiresAt: tokenData.expiresAt,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
async handleFile(uploadInternalId, index, file) {
|
|
232
|
+
if (!file)
|
|
233
|
+
throw new Error('FILE_MISSING');
|
|
234
|
+
/**
|
|
235
|
+
* each uploads needs to be registered with createUpload before uploading an actual file
|
|
236
|
+
*/
|
|
237
|
+
const uploadFile = await UploadService.single(uploadInternalId);
|
|
238
|
+
if (!uploadFile)
|
|
239
|
+
throw new Error('UPLOAD_NOT_FOUND');
|
|
240
|
+
/**
|
|
241
|
+
* write the file to the disk.
|
|
242
|
+
* after writing the stream we can check if the filesize was exceeded und truncated
|
|
243
|
+
*/
|
|
244
|
+
const path = await this.writeFile(file.file, index, uploadInternalId, 'upload');
|
|
245
|
+
if (file.file.truncated) {
|
|
246
|
+
await fs.promises.unlink(path.file);
|
|
247
|
+
throw new Error('FILE_SIZE');
|
|
248
|
+
}
|
|
249
|
+
const updloadState = await UploadService.addPathToUpload(uploadInternalId, index, path.file);
|
|
250
|
+
/**
|
|
251
|
+
* if all chunks are there, complete the file and the upload
|
|
252
|
+
*/
|
|
253
|
+
if (updloadState.chunks === updloadState.paths?.length) {
|
|
254
|
+
await UploadService.setState(updloadState._id, 'waiting');
|
|
255
|
+
await JetStreamService.publish('actions.files.uploaded', updloadState);
|
|
256
|
+
}
|
|
257
|
+
return updloadState;
|
|
258
|
+
}
|
|
259
|
+
complete(upload, options) {
|
|
260
|
+
return this.writeFile(upload.paths, undefined, upload._id, 'file', options);
|
|
261
|
+
}
|
|
262
|
+
async writeFile(data, index, internalId, type, options) {
|
|
263
|
+
const pathAndFile = type === 'upload' && index || index === 0
|
|
264
|
+
? this.uploadPath(internalId.toString(), index)
|
|
265
|
+
: this.fanoutPath(internalId.toString());
|
|
266
|
+
await mkdir(`${pathAndFile.dir}`, { recursive: true });
|
|
267
|
+
if (Array.isArray(data)) {
|
|
268
|
+
if (options?.useNode) {
|
|
269
|
+
await this.concatenateFiles(data, pathAndFile.file);
|
|
270
|
+
}
|
|
271
|
+
else {
|
|
272
|
+
await this.concatenateFilesWithCat(data, pathAndFile.file);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
const writeStream = fs.createWriteStream(pathAndFile.file);
|
|
277
|
+
await pipeline(data, writeStream);
|
|
278
|
+
}
|
|
279
|
+
return pathAndFile;
|
|
280
|
+
}
|
|
281
|
+
async writeFileVersion(data, internalId, version) {
|
|
282
|
+
const pathAndFile = this.fanoutPath(internalId.toString(), version);
|
|
283
|
+
await mkdir(`${pathAndFile.dir}`, { recursive: true });
|
|
284
|
+
await fs.promises.writeFile(pathAndFile.file, Uint8Array.from(data));
|
|
285
|
+
return pathAndFile;
|
|
286
|
+
}
|
|
287
|
+
async concatenateFiles(paths, outputPath) {
|
|
288
|
+
const writeStream = fs.createWriteStream(outputPath);
|
|
289
|
+
const sortedPaths = paths.sort((a, b) => a.index - b.index);
|
|
290
|
+
for (const single of sortedPaths) {
|
|
291
|
+
const readStream = fs.createReadStream(single.path);
|
|
292
|
+
await pipeline(readStream, writeStream, { end: false });
|
|
293
|
+
}
|
|
294
|
+
writeStream.end();
|
|
295
|
+
await new Promise((resolve, reject) => {
|
|
296
|
+
writeStream.on('finish', resolve);
|
|
297
|
+
writeStream.on('error', reject);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
async concatenateFilesWithCat(paths, outputPath) {
|
|
301
|
+
const sortedPaths = paths.sort((a, b) => a.index - b.index);
|
|
302
|
+
const filePaths = sortedPaths.map(single => single.path);
|
|
303
|
+
return new Promise((resolve, reject) => {
|
|
304
|
+
const outputStream = fs.createWriteStream(outputPath);
|
|
305
|
+
const stderrChunks = [];
|
|
306
|
+
const cat = spawn('cat', filePaths, { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
307
|
+
cat.stderr?.on('data', (chunk) => {
|
|
308
|
+
stderrChunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
|
|
309
|
+
});
|
|
310
|
+
cat.stdout.on('error', (error) => {
|
|
311
|
+
outputStream.destroy();
|
|
312
|
+
reject(new Error(`cat stdout error: ${error.message}`));
|
|
313
|
+
});
|
|
314
|
+
cat.on('error', (error) => {
|
|
315
|
+
const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
|
|
316
|
+
const preview = filePaths.slice(0, 5).join(', ');
|
|
317
|
+
outputStream.destroy();
|
|
318
|
+
reject(new Error([
|
|
319
|
+
`cat process error: ${error.message}`,
|
|
320
|
+
error.code ? `code=${error.code}` : undefined,
|
|
321
|
+
stderr ? `stderr="${stderr}"` : undefined,
|
|
322
|
+
`files=${filePaths.length}${filePaths.length ? ` (first: ${preview}${filePaths.length > 5 ? ', ...' : ''})` : ''}`,
|
|
323
|
+
].filter(Boolean).join(' | ')));
|
|
324
|
+
});
|
|
325
|
+
cat.stdout.pipe(outputStream);
|
|
326
|
+
cat.on('close', (code, signal) => {
|
|
327
|
+
const stderr = Buffer.concat(stderrChunks).toString('utf8').trim();
|
|
328
|
+
if (code === 0 && !signal) {
|
|
329
|
+
outputStream.end(() => resolve());
|
|
330
|
+
}
|
|
331
|
+
else {
|
|
332
|
+
const preview = filePaths.slice(0, 5).join(', ');
|
|
333
|
+
outputStream.destroy();
|
|
334
|
+
reject(new Error([
|
|
335
|
+
`cat process exited`,
|
|
336
|
+
`code=${code}`,
|
|
337
|
+
signal ? `signal=${signal}` : undefined,
|
|
338
|
+
stderr ? `stderr="${stderr}"` : undefined,
|
|
339
|
+
`files=${filePaths.length}${filePaths.length ? ` (first: ${preview}${filePaths.length > 5 ? ', ...' : ''})` : ''}`,
|
|
340
|
+
].filter(Boolean).join(' | ')));
|
|
341
|
+
}
|
|
342
|
+
});
|
|
343
|
+
outputStream.on('error', (error) => {
|
|
344
|
+
cat.kill('SIGKILL');
|
|
345
|
+
reject(new Error(`write stream error: ${error.message}`));
|
|
346
|
+
});
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
async removeUploadFiles(upload) {
|
|
350
|
+
const promises = upload.paths?.map(async (single) => {
|
|
351
|
+
try {
|
|
352
|
+
await fs.promises.unlink(single.path);
|
|
353
|
+
}
|
|
354
|
+
catch (error) {
|
|
355
|
+
console.error(`failed to remove ${single.path}:`, error);
|
|
356
|
+
}
|
|
357
|
+
});
|
|
358
|
+
if (promises) {
|
|
359
|
+
await Promise.all(promises);
|
|
360
|
+
await fs.promises.rmdir(`${this.options.uploadFolder}/${upload._id}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
async removeLocalFile(relativePath) {
|
|
364
|
+
const fullPath = `${this.options.dataFolder}/${relativePath}`;
|
|
365
|
+
try {
|
|
366
|
+
await fs.promises.access(fullPath);
|
|
367
|
+
return await fs.promises.unlink(fullPath);
|
|
368
|
+
}
|
|
369
|
+
catch (error) {
|
|
370
|
+
if (error.code === 'ENOENT') {
|
|
371
|
+
console.warn(`File not found: ${fullPath}`);
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
throw error;
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
/**
|
|
378
|
+
* creata directory structure for the given file
|
|
379
|
+
* e.g. ``/b1/f1/68fb87d6db4fb20117bcd3ce.000001``
|
|
380
|
+
*/
|
|
381
|
+
fanoutPath(uploadId, version) {
|
|
382
|
+
const baseFolder = this.options.dataFolder;
|
|
383
|
+
/**
|
|
384
|
+
* upload needs to have the part and index in the filename
|
|
385
|
+
*/
|
|
386
|
+
const filename = uploadId;
|
|
387
|
+
// Stable, uniform fan-out from the id (or use sha256 of expected filename+size)
|
|
388
|
+
const hash = createHash('sha256').update(`${version || ''}${uploadId}`).digest('hex');
|
|
389
|
+
const lvl1 = hash.slice(0, 2);
|
|
390
|
+
const lvl2 = hash.slice(2, 4);
|
|
391
|
+
const dir = [baseFolder, lvl1, lvl2].join('/');
|
|
392
|
+
const file = [dir, filename].join('/');
|
|
393
|
+
const relativePath = [lvl1, lvl2, filename].join('/');
|
|
394
|
+
return { dir, file, relativePath };
|
|
395
|
+
}
|
|
396
|
+
uploadPath(uploadId, index) {
|
|
397
|
+
const baseFolder = `${this.options.uploadFolder}/${uploadId}`;
|
|
398
|
+
const filename = `${uploadId}.${index?.toString().padStart(6, '0')}`;
|
|
399
|
+
const file = [baseFolder, filename].join('/');
|
|
400
|
+
return { dir: baseFolder, file, relativePath: file };
|
|
401
|
+
}
|
|
402
|
+
// async createUpload(filename: string, size: number, chunks: number, mimetype: string, options: UserAppOptionsRequired) {
|
|
403
|
+
// const useFilename = this.sanitizeName(filename);
|
|
404
|
+
// if (await this.exists(options.company, options.project, useFilename)) throw new Error('FILE_EXISTS');
|
|
405
|
+
// if (await UploadService.uploadExists(options.company, options.project, useFilename)) throw new Error('UPLOAD_EXISTS');
|
|
406
|
+
// return UploadService.createUpload(useFilename, size, chunks, mimetype, options);
|
|
407
|
+
// }
|
|
408
|
+
static sanitizeName(name) {
|
|
409
|
+
return name.replace(/[^a-z0-9-_.]/gi, '').toLowerCase();
|
|
410
|
+
}
|
|
411
|
+
getMetadata(upload, metadata) {
|
|
412
|
+
const useMetadata = metadata || {};
|
|
413
|
+
useMetadata.size = upload.size;
|
|
414
|
+
useMetadata.mimetype = upload.mimetype;
|
|
415
|
+
if (upload.mimetype) {
|
|
416
|
+
if (upload.mimetype.match(/^image/)) {
|
|
417
|
+
if (!Array.isArray(useMetadata.tags))
|
|
418
|
+
useMetadata.tags = [];
|
|
419
|
+
useMetadata.tags?.push('image');
|
|
420
|
+
}
|
|
421
|
+
if (upload.mimetype.match(/^video/)) {
|
|
422
|
+
if (!Array.isArray(useMetadata.tags))
|
|
423
|
+
useMetadata.tags = [];
|
|
424
|
+
useMetadata.tags?.push('video');
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return useMetadata;
|
|
428
|
+
}
|
|
429
|
+
get(company, project, app, query, limit) {
|
|
430
|
+
const realQuery = { company, project, app, parent: { $exists: false } };
|
|
431
|
+
let tags;
|
|
432
|
+
if (query.tags) {
|
|
433
|
+
if (!Array.isArray(query.tags)) {
|
|
434
|
+
tags = [query.tags];
|
|
435
|
+
}
|
|
436
|
+
else {
|
|
437
|
+
tags = query.tags;
|
|
438
|
+
}
|
|
439
|
+
realQuery['metadata.tags'] = { $in: tags };
|
|
440
|
+
}
|
|
441
|
+
if (query.search) {
|
|
442
|
+
realQuery.filename = { $regex: query.search, $options: 'i' };
|
|
443
|
+
}
|
|
444
|
+
// If ignorePrefix is given, return all matching files without prefix filtering
|
|
445
|
+
if (query.ignorePrefix) {
|
|
446
|
+
return StorageModel.db.aggregate([
|
|
447
|
+
{
|
|
448
|
+
$match: realQuery,
|
|
449
|
+
},
|
|
450
|
+
{
|
|
451
|
+
$facet: {
|
|
452
|
+
metadata: [{ $count: 'all' }],
|
|
453
|
+
data: [
|
|
454
|
+
{ $sort: { _id: -1 } },
|
|
455
|
+
{ $skip: limit?.skip || 0 },
|
|
456
|
+
{ $limit: limit?.limit || 50 },
|
|
457
|
+
{ $project: { path: 0, bucket: 0 } },
|
|
458
|
+
{ $addFields: { type: 'file' } },
|
|
459
|
+
],
|
|
460
|
+
},
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
$project: {
|
|
464
|
+
all: { $arrayElemAt: ['$metadata.all', 0] },
|
|
465
|
+
data: 1,
|
|
466
|
+
count: { $size: '$data' },
|
|
467
|
+
},
|
|
468
|
+
},
|
|
469
|
+
])
|
|
470
|
+
.toArray()
|
|
471
|
+
.then((result) => result[0] || { all: 0, data: [], count: 0 });
|
|
472
|
+
}
|
|
473
|
+
// If search or tags are given, show only files at the current level (no folders)
|
|
474
|
+
if (query.search || query.tags) {
|
|
475
|
+
const isRootLevel = query.prefix === undefined || query.prefix === '';
|
|
476
|
+
if (isRootLevel) {
|
|
477
|
+
// Root level: only files without prefix
|
|
478
|
+
realQuery.$or = [
|
|
479
|
+
{ prefix: { $exists: false } },
|
|
480
|
+
{ prefix: null },
|
|
481
|
+
{ prefix: '' },
|
|
482
|
+
];
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
// Non-root: only files with exact prefix match
|
|
486
|
+
realQuery.prefix = query.prefix;
|
|
487
|
+
}
|
|
488
|
+
return StorageModel.db.aggregate([
|
|
489
|
+
{
|
|
490
|
+
$match: realQuery,
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
$facet: {
|
|
494
|
+
metadata: [{ $count: 'all' }],
|
|
495
|
+
data: [
|
|
496
|
+
{ $sort: { _id: -1 } },
|
|
497
|
+
{ $skip: limit?.skip || 0 },
|
|
498
|
+
{ $limit: limit?.limit || 50 },
|
|
499
|
+
{ $project: { path: 0, bucket: 0 } },
|
|
500
|
+
{ $addFields: { type: 'file' } },
|
|
501
|
+
],
|
|
502
|
+
},
|
|
503
|
+
},
|
|
504
|
+
{
|
|
505
|
+
$project: {
|
|
506
|
+
all: { $arrayElemAt: ['$metadata.all', 0] },
|
|
507
|
+
data: 1,
|
|
508
|
+
count: { $size: '$data' },
|
|
509
|
+
},
|
|
510
|
+
},
|
|
511
|
+
])
|
|
512
|
+
.toArray()
|
|
513
|
+
.then((result) => result[0] || { all: 0, data: [], count: 0 });
|
|
514
|
+
}
|
|
515
|
+
// Treat undefined prefix same as empty string (root level)
|
|
516
|
+
const isRootLevel = query.prefix === undefined || query.prefix === '';
|
|
517
|
+
if (isRootLevel) {
|
|
518
|
+
// Root level: show files without prefix and extract virtual folders
|
|
519
|
+
return StorageModel.db.aggregate([
|
|
520
|
+
{
|
|
521
|
+
$match: realQuery,
|
|
522
|
+
},
|
|
523
|
+
{
|
|
524
|
+
$addFields: {
|
|
525
|
+
// Extract first segment of prefix for root-level folders
|
|
526
|
+
immediateSubfolder: {
|
|
527
|
+
$cond: {
|
|
528
|
+
if: {
|
|
529
|
+
$or: [
|
|
530
|
+
{ $eq: ['$prefix', null] },
|
|
531
|
+
{ $eq: ['$prefix', ''] },
|
|
532
|
+
{ $eq: [{ $type: '$prefix' }, 'missing'] },
|
|
533
|
+
],
|
|
534
|
+
},
|
|
535
|
+
then: null, // File at root level (no prefix)
|
|
536
|
+
else: {
|
|
537
|
+
// Extract first segment of prefix
|
|
538
|
+
$arrayElemAt: [{ $split: ['$prefix', '/'] }, 0],
|
|
539
|
+
},
|
|
540
|
+
},
|
|
541
|
+
},
|
|
542
|
+
},
|
|
543
|
+
},
|
|
544
|
+
{
|
|
545
|
+
$facet: {
|
|
546
|
+
files: [
|
|
547
|
+
{ $match: { immediateSubfolder: null } }, // Files at root level
|
|
548
|
+
{ $sort: { _id: -1 } },
|
|
549
|
+
{ $skip: limit?.skip || 0 },
|
|
550
|
+
{ $limit: limit?.limit || 50 },
|
|
551
|
+
{ $project: { path: 0, bucket: 0, immediateSubfolder: 0 } },
|
|
552
|
+
{ $addFields: { type: 'file' } },
|
|
553
|
+
],
|
|
554
|
+
folders: [
|
|
555
|
+
{ $match: { immediateSubfolder: { $ne: null } } },
|
|
556
|
+
{ $group: { _id: '$immediateSubfolder' } }, // Unique folder names
|
|
557
|
+
{ $sort: { _id: 1 } },
|
|
558
|
+
{
|
|
559
|
+
$project: {
|
|
560
|
+
_id: 0,
|
|
561
|
+
prefix: '$_id',
|
|
562
|
+
name: '$_id',
|
|
563
|
+
type: { $literal: 'folder' },
|
|
564
|
+
},
|
|
565
|
+
},
|
|
566
|
+
],
|
|
567
|
+
metadata: [
|
|
568
|
+
{ $match: { immediateSubfolder: null } },
|
|
569
|
+
{ $count: 'all' },
|
|
570
|
+
],
|
|
571
|
+
},
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
$project: {
|
|
575
|
+
all: { $arrayElemAt: ['$metadata.all', 0] },
|
|
576
|
+
data: { $concatArrays: ['$folders', '$files'] },
|
|
577
|
+
count: { $add: [{ $size: '$folders' }, { $size: '$files' }] },
|
|
578
|
+
},
|
|
579
|
+
},
|
|
580
|
+
])
|
|
581
|
+
.toArray()
|
|
582
|
+
.then((result) => result[0] || { all: 0, data: [], count: 0 });
|
|
583
|
+
}
|
|
584
|
+
// Non-root: show exact prefix match and extract subfolders
|
|
585
|
+
const prefixWithSlash = query.prefix.endsWith('/') ? query.prefix : `${query.prefix}/`;
|
|
586
|
+
const escapedPrefix = prefixWithSlash.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
587
|
+
// Build non-root query by adding prefix conditions to realQuery
|
|
588
|
+
const nonRootQuery = {
|
|
589
|
+
...realQuery,
|
|
590
|
+
$or: [
|
|
591
|
+
{ prefix: query.prefix }, // Exact match files
|
|
592
|
+
{ prefix: { $regex: `^${escapedPrefix}` } }, // Deeper files for folder extraction
|
|
593
|
+
],
|
|
594
|
+
};
|
|
595
|
+
return StorageModel.db.aggregate([
|
|
596
|
+
{
|
|
597
|
+
$match: nonRootQuery,
|
|
598
|
+
},
|
|
599
|
+
{
|
|
600
|
+
$addFields: {
|
|
601
|
+
// Extract immediate subfolder name after current prefix
|
|
602
|
+
immediateSubfolder: {
|
|
603
|
+
$cond: {
|
|
604
|
+
if: { $eq: ['$prefix', query.prefix] },
|
|
605
|
+
then: null, // File at exact level
|
|
606
|
+
else: {
|
|
607
|
+
// Extract first segment after prefix
|
|
608
|
+
$arrayElemAt: [
|
|
609
|
+
{ $split: [{ $substr: ['$prefix', prefixWithSlash.length, -1] }, '/'] },
|
|
610
|
+
0,
|
|
611
|
+
],
|
|
612
|
+
},
|
|
613
|
+
},
|
|
614
|
+
},
|
|
615
|
+
},
|
|
616
|
+
},
|
|
617
|
+
{
|
|
618
|
+
$facet: {
|
|
619
|
+
files: [
|
|
620
|
+
{ $match: { immediateSubfolder: null } }, // Files at exact level
|
|
621
|
+
{ $sort: { _id: -1 } },
|
|
622
|
+
{ $skip: limit?.skip || 0 },
|
|
623
|
+
{ $limit: limit?.limit || 50 },
|
|
624
|
+
{ $project: { path: 0, bucket: 0, immediateSubfolder: 0 } },
|
|
625
|
+
{ $addFields: { type: 'file' } },
|
|
626
|
+
],
|
|
627
|
+
folders: [
|
|
628
|
+
{ $match: { immediateSubfolder: { $ne: null } } },
|
|
629
|
+
{ $group: { _id: '$immediateSubfolder' } }, // Unique folder names
|
|
630
|
+
{ $sort: { _id: 1 } },
|
|
631
|
+
{
|
|
632
|
+
$project: {
|
|
633
|
+
_id: 0,
|
|
634
|
+
prefix: { $concat: [prefixWithSlash, '$_id'] },
|
|
635
|
+
name: '$_id',
|
|
636
|
+
type: { $literal: 'folder' },
|
|
637
|
+
},
|
|
638
|
+
},
|
|
639
|
+
],
|
|
640
|
+
metadata: [
|
|
641
|
+
{ $match: { immediateSubfolder: null } },
|
|
642
|
+
{ $count: 'all' },
|
|
643
|
+
],
|
|
644
|
+
},
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
$project: {
|
|
648
|
+
all: { $arrayElemAt: ['$metadata.all', 0] },
|
|
649
|
+
data: { $concatArrays: ['$folders', '$files'] },
|
|
650
|
+
count: { $add: [{ $size: '$folders' }, { $size: '$files' }] },
|
|
651
|
+
},
|
|
652
|
+
},
|
|
653
|
+
])
|
|
654
|
+
.toArray()
|
|
655
|
+
.then((result) => result[0] || { all: 0, data: [], count: 0 });
|
|
656
|
+
}
|
|
657
|
+
getTags(company, project, search) {
|
|
658
|
+
let cleanSearch = search.toLowerCase().trim();
|
|
659
|
+
let sortString = cleanSearch;
|
|
660
|
+
let splitSearch = [];
|
|
661
|
+
if (cleanSearch.includes(':')) {
|
|
662
|
+
splitSearch = cleanSearch.split(':');
|
|
663
|
+
cleanSearch = new RegExp(`^${splitSearch[0]}:.*?(${splitSearch[1]})`);
|
|
664
|
+
sortString = cleanSearch[1];
|
|
665
|
+
}
|
|
666
|
+
else {
|
|
667
|
+
cleanSearch = new RegExp(`^(?!([a-z]+):).*(${cleanSearch}).*`);
|
|
668
|
+
}
|
|
669
|
+
return StorageModel.db.find({ company, project, tags: { $regex: cleanSearch, $options: 'i' } }, { projection: { tags: 1 } })
|
|
670
|
+
.toArray()
|
|
671
|
+
.then((matchedDocuments) => this.matchSortTags(matchedDocuments, cleanSearch, sortString));
|
|
672
|
+
}
|
|
673
|
+
single(company, project, filename) {
|
|
674
|
+
return StorageModel.db.aggregate([
|
|
675
|
+
{
|
|
676
|
+
$match: {
|
|
677
|
+
company,
|
|
678
|
+
project,
|
|
679
|
+
id: filename,
|
|
680
|
+
},
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
$lookup: {
|
|
684
|
+
from: 'editor',
|
|
685
|
+
as: 'baseContentData',
|
|
686
|
+
let: {
|
|
687
|
+
pid: '$baseContent.id',
|
|
688
|
+
company: '$company',
|
|
689
|
+
project: '$project',
|
|
690
|
+
},
|
|
691
|
+
pipeline: [
|
|
692
|
+
{
|
|
693
|
+
$match: {
|
|
694
|
+
$and: [
|
|
695
|
+
{
|
|
696
|
+
$expr: { $eq: ['$_id', '$$pid'] },
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
$expr: { $eq: ['$company', '$$company'] },
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
$expr: { $eq: ['$project', '$$project'] },
|
|
703
|
+
},
|
|
704
|
+
],
|
|
705
|
+
},
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
$project: {
|
|
709
|
+
id: 1,
|
|
710
|
+
history: 1,
|
|
711
|
+
},
|
|
712
|
+
},
|
|
713
|
+
],
|
|
714
|
+
},
|
|
715
|
+
},
|
|
716
|
+
{
|
|
717
|
+
$unwind: {
|
|
718
|
+
path: '$baseContentData',
|
|
719
|
+
preserveNullAndEmptyArrays: true,
|
|
720
|
+
},
|
|
721
|
+
},
|
|
722
|
+
{
|
|
723
|
+
$addFields: {
|
|
724
|
+
'baseContent.content': '$baseContentData',
|
|
725
|
+
},
|
|
726
|
+
},
|
|
727
|
+
{
|
|
728
|
+
$project: {
|
|
729
|
+
baseContentData: 0,
|
|
730
|
+
},
|
|
731
|
+
},
|
|
732
|
+
])
|
|
733
|
+
.toArray()
|
|
734
|
+
.then((data) => (data.length ? data[0] : null));
|
|
735
|
+
}
|
|
736
|
+
content(company, project, id) {
|
|
737
|
+
return StorageModel.db.aggregate([
|
|
738
|
+
{
|
|
739
|
+
$match: {
|
|
740
|
+
company,
|
|
741
|
+
project,
|
|
742
|
+
'baseContent.id': id,
|
|
743
|
+
},
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
$setWindowFields: {
|
|
747
|
+
partitionBy: '$baseContent.id',
|
|
748
|
+
sortBy: {
|
|
749
|
+
'baseContent.version': -1,
|
|
750
|
+
},
|
|
751
|
+
output: {
|
|
752
|
+
availableVersions: {
|
|
753
|
+
$count: {},
|
|
754
|
+
window: {
|
|
755
|
+
documents: [
|
|
756
|
+
'unbounded', 'unbounded',
|
|
757
|
+
],
|
|
758
|
+
},
|
|
759
|
+
},
|
|
760
|
+
},
|
|
761
|
+
},
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
$limit: 1,
|
|
765
|
+
},
|
|
766
|
+
])
|
|
767
|
+
.toArray()
|
|
768
|
+
.then((data) => (data.length ? data[0] : null));
|
|
769
|
+
}
|
|
770
|
+
/**
|
|
771
|
+
* checks if the file was already successfully uploaded
|
|
772
|
+
*/
|
|
773
|
+
exists(filename, prefix, app, options) {
|
|
774
|
+
return StorageModel.db.countDocuments({
|
|
775
|
+
company: options.company,
|
|
776
|
+
project: options.project,
|
|
777
|
+
filename,
|
|
778
|
+
prefix,
|
|
779
|
+
app,
|
|
780
|
+
})
|
|
781
|
+
.then((exists) => exists >= 1);
|
|
782
|
+
}
|
|
783
|
+
matchSortTags(documents, search, sort) {
|
|
784
|
+
const mergedArray = [];
|
|
785
|
+
const returnArray = [];
|
|
786
|
+
documents.forEach((document) => {
|
|
787
|
+
document.tags.forEach((tag) => {
|
|
788
|
+
if (mergedArray.find((tagArray) => tagArray.tag === tag))
|
|
789
|
+
return;
|
|
790
|
+
if (!tag.match(search))
|
|
791
|
+
return;
|
|
792
|
+
mergedArray.push({ tag, rating: tag.indexOf(sort) });
|
|
793
|
+
});
|
|
794
|
+
});
|
|
795
|
+
mergedArray.sort((a, b) => (a.rating > b.rating ? 1 : -1));
|
|
796
|
+
mergedArray.forEach((tag) => {
|
|
797
|
+
returnArray.push(tag.tag);
|
|
798
|
+
});
|
|
799
|
+
return returnArray;
|
|
800
|
+
}
|
|
801
|
+
checkAllowedSize(filesize, allowedSize) {
|
|
802
|
+
return filesize < allowedSize;
|
|
803
|
+
}
|
|
804
|
+
stats(company, project) {
|
|
805
|
+
const aggregation = [
|
|
806
|
+
{
|
|
807
|
+
$match: {
|
|
808
|
+
company,
|
|
809
|
+
project,
|
|
810
|
+
parent: { $exists: false },
|
|
811
|
+
},
|
|
812
|
+
},
|
|
813
|
+
{
|
|
814
|
+
$group: {
|
|
815
|
+
_id: null,
|
|
816
|
+
used: {
|
|
817
|
+
$sum: '$metadata.size',
|
|
818
|
+
},
|
|
819
|
+
files: {
|
|
820
|
+
$sum: 1,
|
|
821
|
+
},
|
|
822
|
+
},
|
|
823
|
+
},
|
|
824
|
+
{
|
|
825
|
+
$project: {
|
|
826
|
+
_id: 0,
|
|
827
|
+
used: 1,
|
|
828
|
+
files: 1,
|
|
829
|
+
},
|
|
830
|
+
},
|
|
831
|
+
];
|
|
832
|
+
return StorageModel.db.aggregate(aggregation).toArray()
|
|
833
|
+
.then((value) => value[0] || { files: 0, size: 0 });
|
|
834
|
+
}
|
|
835
|
+
getByInternalId(internalId, options) {
|
|
836
|
+
return StorageModel.db.findOne({ _id: internalId, company: options.company, project: options.project });
|
|
837
|
+
}
|
|
838
|
+
getPathByFilename(filename, app, options) {
|
|
839
|
+
const filenameObject = filenameHelper(filename);
|
|
840
|
+
return StorageModel.db.findOne({
|
|
841
|
+
filename: filenameObject.filename,
|
|
842
|
+
prefix: filenameObject.directory,
|
|
843
|
+
company: options.company,
|
|
844
|
+
project: options.project,
|
|
845
|
+
app,
|
|
846
|
+
}, {
|
|
847
|
+
projection: { path: 1, metadata: 1 },
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
getByFilename(filename, prefix, bucket, options) {
|
|
851
|
+
return StorageModel.db.findOne({
|
|
852
|
+
filename,
|
|
853
|
+
prefix,
|
|
854
|
+
company: options.company,
|
|
855
|
+
project: options.project,
|
|
856
|
+
bucket,
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
async removeBlob(internalId, options) {
|
|
860
|
+
const storage = await this.model.db.findOne({ _id: internalId, company: options.company, project: options.project });
|
|
861
|
+
if (!storage)
|
|
862
|
+
throw new Error('BLOB_NOT_FOUND');
|
|
863
|
+
await fs.promises.unlink(`${this.options.dataFolder}/${storage.path}`);
|
|
864
|
+
await this.removeBlobVersion(internalId, options);
|
|
865
|
+
return this.delete(internalId, options.user, options.app);
|
|
866
|
+
}
|
|
867
|
+
async removeBlobVersion(parentId, options) {
|
|
868
|
+
const versions = await this.model.db.find({ parent: parentId, company: options.company, project: options.project }).toArray();
|
|
869
|
+
if (versions.length) {
|
|
870
|
+
await Promise.allSettled(versions.map(async (single) => {
|
|
871
|
+
await fs.promises.unlink(`${this.options.dataFolder}/${single.path}`);
|
|
872
|
+
return this.delete(single._id, options.user, options.app);
|
|
873
|
+
}));
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
export default new StorageService({
|
|
878
|
+
dataFolder: process.env.MEDIA_FOLDERS_DATA,
|
|
879
|
+
uploadFolder: process.env.MEDIA_FOLDERS_UPLOAD,
|
|
880
|
+
});
|
|
881
|
+
//# sourceMappingURL=storage.service.js.map
|