diff --git a/.env.sample b/.env.sample index 4da82816f..e8f6c25c5 100644 --- a/.env.sample +++ b/.env.sample @@ -9,7 +9,7 @@ API_GATEWAY_HOST='0.0.0.0' API_GATEWAY_PORT=5000 API_GATEWAY_PROTOCOL_SECURE=http -## +## Platform Configurations PLATFORM_NAME= // Please specify your paltform name PLATFORM_LOGO= // Please specify your paltform logo url PUBLIC_PLATFORM_SUPPORT_EMAIL= // Please specify your support email @@ -25,34 +25,15 @@ PUBLIC_QA_API_URL= // Please specify your your QA environment api URL PUBLIC_PRODUCTION_API_URL= // Please specify your PRODUCTION environment api URL PUBLIC_SANDBOX_API_URL= // Please specify your sandbox environment URL -SHORTENED_URL_DOMAIN= // Please specify the domain for your bucket responsible for storing shortened url objects e.g. 'https://bucket-name.s3.ap-east-1.amazonaws.com' DEEPLINK_DOMAIN= // Please specify your doamin/subdomain responsible for deeplinking with 'url' as a query param e.g. 'https://your-deeplink-domain?url=' AGENT_HOST=username@0.0.0.0 // Please specify your agent host VM and IP address -AWS_ACCOUNT_ID=xxxxx // Please provide your AWS account Id -S3_BUCKET_ARN=arn:aws:s3:::xxxxx // Please provide your AWS bucket arn API_ENDPOINT=localhost:5000 #Use your local machine IP Address & PORT API_ENDPOINT_PORT=5000 SOCKET_HOST=http://localhost:5000 -AWS_PUBLIC_ACCESS_KEY= // Please provide your aws bucket access key -AWS_PUBLIC_SECRET_KEY= // Please provide your aws secret key -AWS_PUBLIC_REGION= // Please provide your aws region -AWS_PUBLIC_BUCKET_NAME= // Please provide your aws bucket name - -AWS_ORG_LOGO_BUCKET_NAME= // Please provide your aws org bucket name - -AWS_S3_STOREOBJECT_ACCESS_KEY= // Please provide your aws bucket access key -AWS_S3_STOREOBJECT_SECRET_KEY= // Please provide your aws bucket secret key -AWS_S3_STOREOBJECT_REGION= // Please provide your aws region -AWS_S3_STOREOBJECT_BUCKET= // Please provide your aws bucket -AWS_ACCESS_KEY= // Please provide your access key -AWS_SECRET_KEY= // Please provide your secret key -AWS_REGION= // Please provide your aws region -AWS_BUCKET= // Please provide your aws bucket - PLATFORM_ADMIN_EMAIL= // Please provide admin email Id NATS_HOST='0.0.0.0' @@ -206,4 +187,25 @@ AGENT_API_KEY='supersecret-that-too-16chars' # VERIFIER_CLIENT_ALIAS=VERIFIER # VERIFIER_DOMAIN=https://VERIFIER-domain.com # VERIFIER_KEYCLOAK_MANAGEMENT_CLIENT_ID=encryptedKeyCloakClientId -# VERIFIER_KEYCLOAK_MANAGEMENT_CLIENT_SECRET=encryptedKeyCloakClientSecret \ No newline at end of file +# VERIFIER_KEYCLOAK_MANAGEMENT_CLIENT_SECRET=encryptedKeyCloakClientSecret + +# FILE_STORAGE_PROVIDER can be 'aws' or 'minio' +FILE_STORAGE_PROVIDER=minio + +# AWS Configurations +AWS_ACCOUNT_ID=xxxxx // Please provide your AWS account Id +S3_BUCKET_ARN=arn:aws:s3:::xxxxx // Please provide your AWS bucket arn +AWS_ACCESS_KEY= // Please provide your access key +AWS_SECRET_KEY= // Please provide your secret key +AWS_REGION= // Please provide your aws region + +# MinIO Config : Use the same buckets as below three mentioned with AWS S3 config +MINIO_ENDPOINT= // Please provide your minio endpoint +MINIO_PORT= // Please provide your minio port +MINIO_USE_SSL= // Please provide your minio ssl true/false +MINIO_ACCESS_KEY= // Please provide your minio access key +MINIO_SECRET_KEY= // Please provide your minio secret key + +STORE_OBJECT_BUCKET= // Please provide your aws bucket +FILE_BUCKET= // Please provide your aws bucket for file sharing +ORG_LOGO_BUCKET= // Please provide your aws bucket for org logo \ No newline at end of file diff --git a/apps/api-gateway/src/authz/guards/user-role.guard.ts b/apps/api-gateway/src/authz/guards/user-role.guard.ts index 3c3dc4d7a..d6020e1a6 100644 --- a/apps/api-gateway/src/authz/guards/user-role.guard.ts +++ b/apps/api-gateway/src/authz/guards/user-role.guard.ts @@ -8,11 +8,11 @@ export class UserRoleGuard implements CanActivate { const { user } = request; - if (!user?.userRole) { + if (!user?.realm_access.roles) { throw new ForbiddenException('This role is not a holder.'); } - - if (!user?.userRole.includes('holder')) { + + if (!user?.realm_access.roles.includes('holder')) { throw new ForbiddenException('This role is not a holder.'); } diff --git a/apps/api-gateway/src/issuance/issuance.controller.ts b/apps/api-gateway/src/issuance/issuance.controller.ts index 86add6131..656f17975 100644 --- a/apps/api-gateway/src/issuance/issuance.controller.ts +++ b/apps/api-gateway/src/issuance/issuance.controller.ts @@ -69,7 +69,7 @@ import { IssueCredentialType, UploadedFileDetails } from './interfaces'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { FileInterceptor } from '@nestjs/platform-express'; import { v4 as uuidv4 } from 'uuid'; import { RpcException } from '@nestjs/microservices'; @@ -89,7 +89,7 @@ import { NotFoundErrorDto } from '../dtos/not-found-error.dto'; export class IssuanceController { constructor( private readonly issueCredentialService: IssuanceService, - private readonly awsService: AwsService + private readonly storageService: StorageService ) {} private readonly logger = new Logger('IssuanceController'); @@ -372,7 +372,7 @@ export class IssuanceController { if (file) { const fileKey: string = uuidv4(); try { - await this.awsService.uploadCsvFile(fileKey, file?.buffer); + await this.storageService.uploadCsvFile(fileKey, file?.buffer); } catch (error) { throw new RpcException(error.response ? error.response : error); } @@ -525,7 +525,7 @@ export class IssuanceController { if (file && clientDetails?.isSelectiveIssuance) { const fileKey: string = uuidv4(); try { - await this.awsService.uploadCsvFile(fileKey, file.buffer); + await this.storageService.uploadCsvFile(fileKey, file.buffer); } catch (error) { throw new RpcException(error.response ? error.response : error); } diff --git a/apps/api-gateway/src/issuance/issuance.module.ts b/apps/api-gateway/src/issuance/issuance.module.ts index d5f184d16..a7ff31b19 100644 --- a/apps/api-gateway/src/issuance/issuance.module.ts +++ b/apps/api-gateway/src/issuance/issuance.module.ts @@ -5,9 +5,9 @@ import { IssuanceService } from './issuance.service'; import { CommonService } from '@credebl/common'; import { HttpModule } from '@nestjs/axios'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { AwsService } from '@credebl/aws'; import { CommonConstants } from '@credebl/common/common.constant'; import { NATSClient } from '@credebl/common/NATSClient'; +import { StorageService } from '@credebl/storage'; @Module({ imports: [ @@ -21,6 +21,6 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]) ], controllers: [IssuanceController], - providers: [IssuanceService, CommonService, AwsService, NATSClient] + providers: [IssuanceService, CommonService, NATSClient, StorageService] }) export class IssuanceModule {} diff --git a/apps/api-gateway/src/organization/organization.module.ts b/apps/api-gateway/src/organization/organization.module.ts index bc8da3334..89cee6744 100644 --- a/apps/api-gateway/src/organization/organization.module.ts +++ b/apps/api-gateway/src/organization/organization.module.ts @@ -7,7 +7,7 @@ import { Module } from '@nestjs/common'; import { OrganizationController } from './organization.controller'; import { OrganizationService } from './organization.service'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { NATSClient } from '@credebl/common/NATSClient'; @Module({ @@ -24,6 +24,6 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]) ], controllers: [OrganizationController], - providers: [OrganizationService, CommonService, AwsService, NATSClient] + providers: [OrganizationService, CommonService, StorageService, NATSClient] }) export class OrganizationModule {} diff --git a/apps/api-gateway/src/organization/organization.service.ts b/apps/api-gateway/src/organization/organization.service.ts index 72e1c89b4..ce6f6b974 100644 --- a/apps/api-gateway/src/organization/organization.service.ts +++ b/apps/api-gateway/src/organization/organization.service.ts @@ -25,6 +25,7 @@ import { PrimaryDid } from './dtos/set-primary-did.dto'; import { NATSClient } from '@credebl/common/NATSClient'; import { ClientProxy } from '@nestjs/microservices'; import { ClientTokenDto } from './dtos/client-token.dto'; +import { CommonConstants } from '@credebl/common/common.constant'; @Injectable() export class OrganizationService extends BaseService { @@ -236,7 +237,7 @@ export class OrganizationService extends BaseService { getBase64Image(base64Image: string): Buffer { const base64Data = base64Image.replace(/^data:image\/\w+;base64,/, ''); - const imageBuffer = Buffer.from(base64Data, 'base64'); + const imageBuffer = Buffer.from(base64Data, CommonConstants.ENCODING); return imageBuffer; } async generateClientApiToken(clientTokenDto: ClientTokenDto): Promise<{ token: string }> { diff --git a/apps/api-gateway/src/user/user.controller.ts b/apps/api-gateway/src/user/user.controller.ts index 24d4918d4..ba911f5f5 100644 --- a/apps/api-gateway/src/user/user.controller.ts +++ b/apps/api-gateway/src/user/user.controller.ts @@ -47,7 +47,7 @@ import { UpdatePlatformSettingsDto } from './dto/update-platform-settings.dto'; import { Roles } from '../authz/decorators/roles.decorator'; import { OrgRolesGuard } from '../authz/guards/org-roles.guard'; import { OrgRoles } from 'libs/org-roles/enums'; -import { AwsService } from '@credebl/aws/aws.service'; +import { StorageService } from '@credebl/storage'; import { PaginationDto } from '@credebl/common/dtos/pagination.dto'; import { UserAccessGuard } from '../authz/guards/user-access-guard'; import { TrimStringParamPipe } from '@credebl/common/cast.helper'; @@ -61,7 +61,7 @@ export class UserController { constructor( private readonly userService: UserService, private readonly commonService: CommonService, - private readonly awsService: AwsService + private readonly storageService: StorageService ) {} /** diff --git a/apps/api-gateway/src/user/user.module.ts b/apps/api-gateway/src/user/user.module.ts index 02a920ffa..e3b878f9a 100644 --- a/apps/api-gateway/src/user/user.module.ts +++ b/apps/api-gateway/src/user/user.module.ts @@ -6,7 +6,7 @@ import { Module } from '@nestjs/common'; import { UserController } from './user.controller'; import { UserService } from './user.service'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { NATSClient } from '@credebl/common/NATSClient'; @@ -19,11 +19,10 @@ import { NATSClient } from '@credebl/common/NATSClient'; name: 'NATS_CLIENT', transport: Transport.NATS, options: getNatsOptions(CommonConstants.USER_SERVICE, process.env.API_GATEWAY_NKEY_SEED) - } ]) ], controllers: [UserController], - providers: [UserService, CommonService, AwsService, NATSClient] + providers: [UserService, CommonService, StorageService, NATSClient] }) export class UserModule {} diff --git a/apps/api-gateway/src/webhook/webhook.module.ts b/apps/api-gateway/src/webhook/webhook.module.ts index 08433c3f9..218ffcad9 100644 --- a/apps/api-gateway/src/webhook/webhook.module.ts +++ b/apps/api-gateway/src/webhook/webhook.module.ts @@ -5,7 +5,7 @@ import { WebhookService } from './webhook.service'; import { CommonService } from '@credebl/common'; import { HttpModule } from '@nestjs/axios'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { NATSClient } from '@credebl/common/NATSClient'; @@ -21,6 +21,6 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]) ], controllers: [WebhookController], - providers: [WebhookService, CommonService, AwsService, NATSClient] + providers: [WebhookService, CommonService, StorageService, NATSClient] }) -export class WebhookModule { } +export class WebhookModule {} diff --git a/apps/cloud-wallet/src/cloud-wallet.service.ts b/apps/cloud-wallet/src/cloud-wallet.service.ts index 0a396251a..ba96c01fd 100644 --- a/apps/cloud-wallet/src/cloud-wallet.service.ts +++ b/apps/cloud-wallet/src/cloud-wallet.service.ts @@ -176,8 +176,9 @@ export class CloudWalletService { const [baseWalletDetails, decryptedApiKey] = await this._commonCloudWalletInfo(userId); const { agentEndpoint } = baseWalletDetails; - const threadParam = threadId ? `?threadId=${threadId}` : ''; - const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}/${threadParam}}`; + const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}/${ + threadId ? `?threadId=${threadId}` : '' + }`; const getProofById = await this.commonService.httpGet(url, { headers: { authorization: decryptedApiKey } }); return getProofById; } catch (error) { diff --git a/apps/issuance/src/issuance.module.ts b/apps/issuance/src/issuance.module.ts index 76e5cf912..d5b20e617 100644 --- a/apps/issuance/src/issuance.module.ts +++ b/apps/issuance/src/issuance.module.ts @@ -12,7 +12,7 @@ import { EmailDto } from '@credebl/common/dtos/email.dto'; import { BullModule } from '@nestjs/bull'; import { CacheModule } from '@nestjs/cache-manager'; import { BulkIssuanceProcessor } from './issuance.processor'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { UserActivityRepository } from 'libs/user-activity/repositories'; import { CommonConstants, MICRO_SERVICE_NAME } from '@credebl/common/common.constant'; import { LoggerModule } from '@credebl/logger/logger.module'; @@ -57,7 +57,7 @@ import { NATSClient } from '@credebl/common/NATSClient'; OutOfBandIssuance, EmailDto, BulkIssuanceProcessor, - AwsService, + StorageService, NATSClient, { provide: MICRO_SERVICE_NAME, diff --git a/apps/issuance/src/issuance.service.ts b/apps/issuance/src/issuance.service.ts index b89c67a4d..a355a905a 100644 --- a/apps/issuance/src/issuance.service.ts +++ b/apps/issuance/src/issuance.service.ts @@ -66,7 +66,7 @@ import { convertUrlToDeepLinkUrl, getAgentUrl, paginator } from '@credebl/common import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; import { FileUploadStatus, FileUploadType } from 'apps/api-gateway/src/enum'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { io } from 'socket.io-client'; import { IIssuedCredentialSearchParams, IssueCredentialType } from 'apps/api-gateway/src/issuance/interfaces'; import { @@ -89,7 +89,6 @@ import * as pLimit from 'p-limit'; import { UserActivityRepository } from 'libs/user-activity/repositories'; import { validateW3CSchemaAttributes } from '../libs/helpers/attributes.validator'; import { ISchemaDetail } from '@credebl/common/interfaces/schema.interface'; -import ContextStorageService, { ContextStorageServiceKey } from '@credebl/context/contextStorageService.interface'; import { NATSClient } from '@credebl/common/NATSClient'; import { extractAttributeNames, unflattenCsvRow } from '../libs/helpers/attributes.extractor'; import { redisStore } from 'cache-manager-ioredis-yet'; @@ -107,12 +106,10 @@ export class IssuanceService { @Inject(CACHE_MANAGER) private readonly cacheManager: Cache, private readonly outOfBandIssuance: OutOfBandIssuance, private readonly emailData: EmailDto, - private readonly awsService: AwsService, + private readonly storageService: StorageService, @InjectQueue('bulk-issuance') private readonly bulkIssuanceQueue: Queue, // TODO: Remove duplicate, unused variable - @Inject(CACHE_MANAGER) private readonly cacheService: Cache, @Inject(ContextStorageServiceKey) - private readonly contextStorageService: ContextStorageService, private readonly natsClient: NATSClient ) {} @@ -1290,8 +1287,8 @@ export class IssuanceService { credentialPayload.schemaName = credentialDetails.schemaName; } - const getFileDetails = await this.awsService.getFile(importFileDetails.fileKey); - const csvData: string = getFileDetails.Body.toString(); + const getFileDetails = await this.storageService.getFile(importFileDetails.fileKey); + const csvData: string = getFileDetails.toString(); const parsedData = paParse(csvData, { header: true, diff --git a/apps/organization/src/organization.module.ts b/apps/organization/src/organization.module.ts index 37ad1c270..52fbe43ee 100644 --- a/apps/organization/src/organization.module.ts +++ b/apps/organization/src/organization.module.ts @@ -17,8 +17,7 @@ import { CacheModule } from '@nestjs/cache-manager'; import { getNatsOptions } from '@credebl/common/nats.config'; import { ClientRegistrationService } from '@credebl/client-registration'; import { KeycloakUrlService } from '@credebl/keycloak-url'; - -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { GlobalConfigModule } from '@credebl/config/global-config.module'; import { ConfigModule as PlatformConfig } from '@credebl/config/config.module'; @@ -36,19 +35,29 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]), CommonModule, GlobalConfigModule, - LoggerModule, PlatformConfig, ContextInterceptorModule, + LoggerModule, + PlatformConfig, + ContextInterceptorModule, CacheModule.register() ], controllers: [OrganizationController], providers: [ - OrganizationService, OrganizationRepository, PrismaService, - Logger, OrgRolesService, UserOrgRolesService, OrgRolesRepository, UserActivityRepository, - UserActivityRepository, UserOrgRolesRepository, UserRepository, UserActivityService, - ClientRegistrationService, - KeycloakUrlService, - AwsService, - NATSClient - ] - + OrganizationService, + OrganizationRepository, + PrismaService, + Logger, + OrgRolesService, + UserOrgRolesService, + OrgRolesRepository, + UserActivityRepository, + UserActivityRepository, + UserOrgRolesRepository, + UserRepository, + UserActivityService, + ClientRegistrationService, + KeycloakUrlService, + StorageService, + NATSClient + ] }) export class OrganizationModule {} diff --git a/apps/organization/src/organization.service.ts b/apps/organization/src/organization.service.ts index ef570600d..f06ffb5ba 100644 --- a/apps/organization/src/organization.service.ts +++ b/apps/organization/src/organization.service.ts @@ -44,7 +44,7 @@ import { UserActivityService } from '@credebl/user-activity'; import { ClientRegistrationService } from '@credebl/client-registration/client-registration.service'; import { map } from 'rxjs/operators'; import { Cache } from 'cache-manager'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { IOrgCredentials, @@ -66,9 +66,13 @@ import { NATSClient } from '@credebl/common/NATSClient'; import { UserRepository } from 'apps/user/repositories/user.repository'; import * as jwt from 'jsonwebtoken'; import { ClientTokenDto } from '../dtos/client-token.dto'; +import { CommonConstants } from '@credebl/common/common.constant'; @Injectable() export class OrganizationService { + private readonly IMG_EXT = 'png'; + private readonly ORG_LOGO_FOLDER = 'orgLogos'; + private readonly ORG_LOGO_PREFIX = 'orgLogo'; constructor( private readonly prisma: PrismaService, private readonly commonService: CommonService, @@ -76,7 +80,7 @@ export class OrganizationService { private readonly organizationRepository: OrganizationRepository, private readonly orgRoleService: OrgRolesService, private readonly userOrgRoleService: UserOrgRolesService, - private readonly awsService: AwsService, + private readonly storageService: StorageService, private readonly userActivityService: UserActivityService, private readonly logger: Logger, // TODO: Remove duplicate, unused variable @@ -135,7 +139,7 @@ export class OrganizationService { createOrgDto.lastChangedBy = userId; if (await this.isValidBase64(createOrgDto?.logo)) { - const imageUrl = await this.uploadFileToS3(createOrgDto.logo); + const imageUrl = await this.uploadFile(createOrgDto.logo); createOrgDto.logo = imageUrl; } else { createOrgDto.logo = ''; @@ -488,17 +492,17 @@ export class OrganizationService { } } - async uploadFileToS3(orgLogo: string): Promise { + async uploadFile(orgLogo: string): Promise { try { const updatedOrglogo = orgLogo.split(',')[1]; - const imgData = Buffer.from(updatedOrglogo, 'base64'); - const logoUrl = await this.awsService.uploadFileToS3Bucket( + const imgData = Buffer.from(updatedOrglogo, CommonConstants.ENCODING); + const logoUrl = await this.storageService.uploadFileToBucket( imgData, - 'png', - 'orgLogo', - process.env.AWS_ORG_LOGO_BUCKET_NAME, - 'base64', - 'orgLogos' + this.IMG_EXT, + this.ORG_LOGO_PREFIX, + process.env.ORG_LOGO_BUCKET, + CommonConstants.ENCODING, + this.ORG_LOGO_FOLDER ); return logoUrl; } catch (error) { @@ -540,7 +544,7 @@ export class OrganizationService { updateOrgDto.userId = userId; if (await this.isValidBase64(updateOrgDto.logo)) { - const imageUrl = await this.uploadFileToS3(updateOrgDto.logo); + const imageUrl = await this.uploadFile(updateOrgDto.logo); updateOrgDto.logo = imageUrl; } else { delete updateOrgDto.logo; diff --git a/apps/user/src/fido/fido.module.ts b/apps/user/src/fido/fido.module.ts index e3125189a..de737b4fb 100644 --- a/apps/user/src/fido/fido.module.ts +++ b/apps/user/src/fido/fido.module.ts @@ -19,7 +19,7 @@ import { UserOrgRolesRepository } from 'libs/user-org-roles/repositories'; import { UserOrgRolesService } from '@credebl/user-org-roles'; import { UserRepository } from '../../repositories/user.repository'; import { UserService } from '../user.service'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { NATSClient } from '@credebl/common/NATSClient'; @Module({ @@ -35,10 +35,10 @@ import { NATSClient } from '@credebl/common/NATSClient'; ]), HttpModule, CommonModule -], + ], controllers: [FidoController], providers: [ - AwsService, + StorageService, UserService, PrismaService, FidoService, @@ -56,6 +56,6 @@ import { NATSClient } from '@credebl/common/NATSClient'; UserActivityService, UserActivityRepository, NATSClient -] + ] }) -export class FidoModule { } +export class FidoModule {} diff --git a/apps/user/src/user.module.ts b/apps/user/src/user.module.ts index a8e262790..ee338ba2e 100644 --- a/apps/user/src/user.module.ts +++ b/apps/user/src/user.module.ts @@ -18,7 +18,7 @@ import { UserRepository } from '../repositories/user.repository'; import { UserService } from './user.service'; import { UserDevicesRepository } from '../repositories/user-device.repository'; import { getNatsOptions } from '@credebl/common/nats.config'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { GlobalConfigModule } from '@credebl/config/global-config.module'; import { ConfigModule as PlatformConfig } from '@credebl/config/config.module'; @@ -35,16 +35,18 @@ import { NATSClient } from '@credebl/common/NATSClient'; options: getNatsOptions(CommonConstants.USER_SERVICE, process.env.USER_NKEY_SEED) } ]), - + CommonModule, GlobalConfigModule, - LoggerModule, PlatformConfig, ContextInterceptorModule, + LoggerModule, + PlatformConfig, + ContextInterceptorModule, FidoModule, OrgRolesModule -], + ], controllers: [UserController], providers: [ - AwsService, + StorageService, UserService, UserRepository, PrismaService, diff --git a/apps/user/src/user.service.ts b/apps/user/src/user.service.ts index 474dc6752..93d235783 100644 --- a/apps/user/src/user.service.ts +++ b/apps/user/src/user.service.ts @@ -48,12 +48,10 @@ import { import { AcceptRejectInvitationDto } from '../dtos/accept-reject-invitation.dto'; import { UserActivityService } from '@credebl/user-activity'; import { SupabaseService } from '@credebl/supabase'; -import { UserDevicesRepository } from '../repositories/user-device.repository'; import { v4 as uuidv4 } from 'uuid'; import { Invitation, ProviderType, SessionType, TokenType, UserRole } from '@credebl/enum/enum'; import validator from 'validator'; import { DISALLOWED_EMAIL_DOMAIN } from '@credebl/common/common.constant'; -import { AwsService } from '@credebl/aws'; import { IUsersActivity } from 'libs/user-activity/interface'; import { ISendVerificationEmail, @@ -82,8 +80,6 @@ export class UserService { private readonly userOrgRoleService: UserOrgRolesService, private readonly userActivityService: UserActivityService, private readonly userRepository: UserRepository, - private readonly awsService: AwsService, - private readonly userDevicesRepository: UserDevicesRepository, private readonly logger: Logger, @Inject('NATS_CLIENT') private readonly userServiceProxy: ClientProxy, private readonly natsClient: NATSClient diff --git a/apps/utility/src/utilities.module.ts b/apps/utility/src/utilities.module.ts index 2f547234f..4fb5872d6 100644 --- a/apps/utility/src/utilities.module.ts +++ b/apps/utility/src/utilities.module.ts @@ -7,7 +7,7 @@ import { PrismaService } from '@credebl/prisma-service'; import { UtilitiesController } from './utilities.controller'; import { UtilitiesService } from './utilities.service'; import { UtilitiesRepository } from './utilities.repository'; -import { AwsService } from '@credebl/aws'; +import { StorageService } from '@credebl/storage'; import { CommonConstants } from '@credebl/common/common.constant'; import { GlobalConfigModule } from '@credebl/config/global-config.module'; import { ConfigModule as PlatformConfig } from '@credebl/config/config.module'; @@ -25,10 +25,12 @@ import { ContextInterceptorModule } from '@credebl/context/contextInterceptorMod ]), CommonModule, GlobalConfigModule, - LoggerModule, PlatformConfig, ContextInterceptorModule, + LoggerModule, + PlatformConfig, + ContextInterceptorModule, CacheModule.register() ], controllers: [UtilitiesController], - providers: [UtilitiesService, Logger, PrismaService, UtilitiesRepository, AwsService] + providers: [UtilitiesService, Logger, PrismaService, UtilitiesRepository, StorageService] }) -export class UtilitiesModule { } +export class UtilitiesModule {} diff --git a/apps/utility/src/utilities.service.ts b/apps/utility/src/utilities.service.ts index ae299f334..e2e894764 100644 --- a/apps/utility/src/utilities.service.ts +++ b/apps/utility/src/utilities.service.ts @@ -1,63 +1,62 @@ import { Injectable, Logger } from '@nestjs/common'; import { RpcException } from '@nestjs/microservices'; import { UtilitiesRepository } from './utilities.repository'; -import { AwsService } from '@credebl/aws'; -import { S3 } from 'aws-sdk'; +import { StorageService } from '@credebl/storage'; import { v4 as uuidv4 } from 'uuid'; @Injectable() export class UtilitiesService { - constructor( - private readonly logger: Logger, - private readonly utilitiesRepository: UtilitiesRepository, - private readonly awsService: AwsService - ) { } + constructor( + private readonly logger: Logger, + private readonly utilitiesRepository: UtilitiesRepository, + private readonly storageService: StorageService + ) {} - async createAndStoreShorteningUrl(payload): Promise { - try { - const { credentialId, schemaId, credDefId, invitationUrl, attributes } = payload; - const invitationPayload = { - referenceId: credentialId, - invitationPayload: { - schemaId, - credDefId, - invitationUrl, - attributes - } - }; - await this.utilitiesRepository.saveShorteningUrl(invitationPayload); - return `${process.env.API_GATEWAY_PROTOCOL}://${process.env.API_ENDPOINT}/invitation/qr-code/${credentialId}`; - } catch (error) { - this.logger.error(`[createAndStoreShorteningUrl] - error in create shortening url: ${JSON.stringify(error)}`); - throw new RpcException(error); + async createAndStoreShorteningUrl(payload): Promise { + try { + const { credentialId, schemaId, credDefId, invitationUrl, attributes } = payload; + const invitationPayload = { + referenceId: credentialId, + invitationPayload: { + schemaId, + credDefId, + invitationUrl, + attributes } + }; + await this.utilitiesRepository.saveShorteningUrl(invitationPayload); + return `${process.env.API_GATEWAY_PROTOCOL}://${process.env.API_ENDPOINT}/invitation/qr-code/${credentialId}`; + } catch (error) { + this.logger.error(`[createAndStoreShorteningUrl] - error in create shortening url: ${JSON.stringify(error)}`); + throw new RpcException(error); } + } - async getShorteningUrl(referenceId: string): Promise { - try { - const getShorteningUrl = await this.utilitiesRepository.getShorteningUrl(referenceId); + async getShorteningUrl(referenceId: string): Promise { + try { + const getShorteningUrl = await this.utilitiesRepository.getShorteningUrl(referenceId); - const getInvitationUrl = { - referenceId: getShorteningUrl.referenceId, - invitationPayload: getShorteningUrl.invitationPayload - }; - - return getInvitationUrl; - } catch (error) { - this.logger.error(`[getShorteningUrl] - error in get shortening url: ${JSON.stringify(error)}`); - throw new RpcException(error); - } + const getInvitationUrl = { + referenceId: getShorteningUrl.referenceId, + invitationPayload: getShorteningUrl.invitationPayload + }; + + return getInvitationUrl; + } catch (error) { + this.logger.error(`[getShorteningUrl] - error in get shortening url: ${JSON.stringify(error)}`); + throw new RpcException(error); } + } - async storeObject(payload: {persistent: boolean, storeObj: unknown}): Promise { - try { - const uuid = uuidv4(); - const uploadResult:S3.ManagedUpload.SendData = await this.awsService.storeObject(payload.persistent, uuid, payload.storeObj); - const url: string = `${process.env.SHORTENED_URL_DOMAIN}/${uploadResult.Key}`; - return url; - } catch (error) { - this.logger.error(error); - throw new Error('An error occurred while uploading data to S3. Error::::::'); - } + async storeObject(payload: { persistent: boolean; storeObj: unknown }): Promise { + try { + const uuid = uuidv4(); + this.logger.log(`In storeObject in utilityService`); + const uploadResult: string = await this.storageService.storeObject(payload.persistent, uuid, payload.storeObj); + return uploadResult; + } catch (error) { + this.logger.error(error); + throw new Error('An error occurred while uploading data Error::::::'); } + } } diff --git a/libs/aws/src/aws.module.ts b/libs/aws/src/aws.module.ts deleted file mode 100644 index 1a2a90f39..000000000 --- a/libs/aws/src/aws.module.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { Module } from '@nestjs/common'; -import { AwsService } from './aws.service'; - -@Module({ - providers: [AwsService], - exports: [AwsService] -}) -export class AwsModule {} diff --git a/libs/aws/src/aws.service.ts b/libs/aws/src/aws.service.ts deleted file mode 100644 index 19286edea..000000000 --- a/libs/aws/src/aws.service.ts +++ /dev/null @@ -1,115 +0,0 @@ -import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; -import { RpcException } from '@nestjs/microservices'; -import { S3 } from 'aws-sdk'; -import { promisify } from 'util'; - -@Injectable() -export class AwsService { - private s3: S3; - private s4: S3; - private s3StoreObject: S3; - - constructor() { - this.s3 = new S3({ - accessKeyId: process.env.AWS_ACCESS_KEY, - secretAccessKey: process.env.AWS_SECRET_KEY, - region: process.env.AWS_REGION - }); - - this.s4 = new S3({ - accessKeyId: process.env.AWS_PUBLIC_ACCESS_KEY, - secretAccessKey: process.env.AWS_PUBLIC_SECRET_KEY, - region: process.env.AWS_PUBLIC_REGION - }); - - this.s3StoreObject = new S3({ - accessKeyId: process.env.AWS_S3_STOREOBJECT_ACCESS_KEY, - secretAccessKey: process.env.AWS_S3_STOREOBJECT_SECRET_KEY, - region: process.env.AWS_S3_STOREOBJECT_REGION - }); - } - - async uploadFileToS3Bucket( - fileBuffer: Buffer, - ext: string, - filename: string, - bucketName: string, - encoding: string, - pathAWS: string = '' - ): Promise { - const timestamp = Date.now(); - const putObjectAsync = promisify(this.s4.putObject).bind(this.s4); - - try { - await putObjectAsync({ - Bucket: `${bucketName}`, - Key: `${pathAWS}/${encodeURIComponent(filename)}-${timestamp}.${ext}`, - Body: fileBuffer, - ContentEncoding: encoding, - ContentType: `image/png` - }); - - const imageUrl = `https://${bucketName}.s3.${process.env.AWS_PUBLIC_REGION}.amazonaws.com/${pathAWS}/${encodeURIComponent(filename)}-${timestamp}.${ext}`; - return imageUrl; - } catch (error) { - throw new HttpException(error, HttpStatus.SERVICE_UNAVAILABLE); - } - } - - async uploadCsvFile(key: string, body: unknown): Promise { - const params: AWS.S3.PutObjectRequest = { - Bucket: process.env.AWS_BUCKET, - Key: key, - Body: 'string' === typeof body ? body : body.toString() - }; - - try { - await this.s3.upload(params).promise(); - } catch (error) { - throw new RpcException(error.response ? error.response : error); - } - } - - async getFile(key: string): Promise { - const params: AWS.S3.GetObjectRequest = { - Bucket: process.env.AWS_BUCKET, - Key: key - }; - try { - return this.s3.getObject(params).promise(); - } catch (error) { - throw new RpcException(error.response ? error.response : error); - } - } - - async deleteFile(key: string): Promise { - const params: AWS.S3.DeleteObjectRequest = { - Bucket: process.env.AWS_BUCKET, - Key: key - }; - try { - await this.s3.deleteObject(params).promise(); - } catch (error) { - throw new RpcException(error.response ? error.response : error); - } - } - - async storeObject(persistent: boolean, key: string, body: unknown): Promise { - const objKey: string = persistent.valueOf() ? `persist/${key}` : `default/${key}`; - const buf = Buffer.from(JSON.stringify(body)); - const params: AWS.S3.PutObjectRequest = { - Bucket: process.env.AWS_S3_STOREOBJECT_BUCKET, - Body: buf, - Key: objKey, - ContentEncoding: 'base64', - ContentType: 'application/json' - }; - - try { - const receivedData = await this.s3StoreObject.upload(params).promise(); - return receivedData; - } catch (error) { - throw new RpcException(error.response ? error.response : error); - } - } -} diff --git a/libs/aws/src/index.ts b/libs/aws/src/index.ts deleted file mode 100644 index 182a99dc1..000000000 --- a/libs/aws/src/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './aws.module'; -export * from './aws.service'; diff --git a/libs/aws/tsconfig.build.json b/libs/aws/tsconfig.build.json deleted file mode 100644 index 74c2e991f..000000000 --- a/libs/aws/tsconfig.build.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "extends": "../../tsconfig.build.json", - "compilerOptions": { - "outDir": "../../dist/libs/aws" - }, - "include": ["src/**/*"] -} diff --git a/libs/common/src/common.constant.ts b/libs/common/src/common.constant.ts index 02c6efd05..63d363c7d 100644 --- a/libs/common/src/common.constant.ts +++ b/libs/common/src/common.constant.ts @@ -383,7 +383,8 @@ export enum CommonConstants { GET_VERIFIED_PROOF = 'get-verified-proof', GET_QUESTION_ANSWER_RECORD = 'get-question-answer-record', SEND_QUESTION = 'send-question', - SEND_BASIC_MESSAGE = 'send-basic-message' + SEND_BASIC_MESSAGE = 'send-basic-message', + ENCODING = 'base64' } export const MICRO_SERVICE_NAME = Symbol('MICRO_SERVICE_NAME'); export const ATTRIBUTE_NAME_REGEX = /\['(.*?)'\]/; diff --git a/libs/aws/package.json b/libs/storage/package.json similarity index 61% rename from libs/aws/package.json rename to libs/storage/package.json index 56590cbf5..0583ff5fb 100644 --- a/libs/aws/package.json +++ b/libs/storage/package.json @@ -1,5 +1,5 @@ { - "name": "@credebl/aws", + "name": "@credebl/storage", "main": "src/index", "types": "src/index", "version": "0.0.1", @@ -8,15 +8,16 @@ ], "scripts": { "build": "pnpm run clean && pnpm run compile", - "clean": "rimraf ../../dist/libs/aws", + "clean": "rimraf ../../dist/libs/storage", "compile": "tsc -p tsconfig.build.json", "test": "jest" }, "dependencies": { - "@nestjs/common": "catalog:", - "@nestjs/testing": "catalog:", - "@nestjs/microservices": "catalog:", - "aws-sdk": "^2.1510.0" + "@nestjs/common": "^10.2.7", + "@nestjs/testing": "^10.1.3", + "@nestjs/microservices": "^10.1.3", + "aws-sdk": "^2.1510.0", + "minio": "^8.0.6" }, "devDependencies": { "reflect-metadata": "^0.1.13", diff --git a/libs/storage/src/index.ts b/libs/storage/src/index.ts new file mode 100644 index 000000000..5c65021d0 --- /dev/null +++ b/libs/storage/src/index.ts @@ -0,0 +1,2 @@ +export * from './storage.module'; +export * from './storage.service'; diff --git a/libs/storage/src/provider/minio.provider.ts b/libs/storage/src/provider/minio.provider.ts new file mode 100644 index 000000000..42f86b446 --- /dev/null +++ b/libs/storage/src/provider/minio.provider.ts @@ -0,0 +1,57 @@ +import { Client } from 'minio'; +import { FileUploadOptions, IStorageProvider } from '../storage.interface'; +import { CommonConstants } from '@credebl/common/common.constant'; + +export class MinioProvider implements IStorageProvider { + private readonly minioClient: Client; + + constructor() { + const requiredEnvVars = ['MINIO_ENDPOINT', 'MINIO_ACCESS_KEY', 'MINIO_SECRET_KEY', 'MINIO_PORT']; + const missingVars = requiredEnvVars.filter((varName) => !process.env[varName]); + if (0 < missingVars.length) { + throw new Error(`Missing required Minio environment variables: ${missingVars.join(', ')}`); + } + this.minioClient = new Client({ + endPoint: process.env.MINIO_ENDPOINT as string, + port: parseInt(process.env.MINIO_PORT || '9000', 10), + useSSL: 'true' === process.env.MINIO_USE_SSL, + accessKey: process.env.MINIO_ACCESS_KEY as string, + secretKey: process.env.MINIO_SECRET_KEY as string + }); + } + + async uploadFile(bucket: string, key: string, content: Buffer, options: FileUploadOptions): Promise { + await this.minioClient.putObject(bucket, key, content, null, { + 'Content-Type': options.mimeType, + 'Content-Encoding': options.encoding + }); + const protocol = 'true' === process.env.MINIO_USE_SSL ? 'https' : 'http'; + return `${protocol}://${process.env.MINIO_ENDPOINT}:${process.env.MINIO_PORT}/${bucket}/${key}`; + } + + async getFile(bucket: string, key: string): Promise { + const stream = await this.minioClient.getObject(bucket, key); + const chunks: Buffer[] = []; + + for await (const chunk of stream) { + chunks.push(chunk); + } + return Buffer.concat(chunks); + } + + async deleteFile(bucket: string, key: string): Promise { + await this.minioClient.removeObject(bucket, key); + } + + async storeObject(bucket: string, persistent: boolean, key: string, body: unknown): Promise { + const objKey = persistent ? `persist/${key}` : `default/${key}`; + const buffer = Buffer.from(JSON.stringify(body)); + + await this.minioClient.putObject(bucket, objKey, buffer, null, { + ContentType: 'application/json', + ContentEncoding: CommonConstants.ENCODING + }); + const protocol = 'true' === process.env.MINIO_USE_SSL ? 'https' : 'http'; + return `${protocol}://${process.env.MINIO_ENDPOINT}:${process.env.MINIO_PORT}/${bucket}/${objKey}`; + } +} diff --git a/libs/storage/src/provider/s3.provider.ts b/libs/storage/src/provider/s3.provider.ts new file mode 100644 index 000000000..e5ac49bb4 --- /dev/null +++ b/libs/storage/src/provider/s3.provider.ts @@ -0,0 +1,55 @@ +import { S3 } from 'aws-sdk'; +import { FileUploadOptions, IStorageProvider } from '../storage.interface'; +import { CommonConstants } from '@credebl/common/common.constant'; + +export class S3Provider implements IStorageProvider { + private readonly s3: S3; + + constructor() { + this.s3 = new S3({ + accessKeyId: process.env.AWS_ACCESS_KEY, + secretAccessKey: process.env.AWS_SECRET_KEY, + region: process.env.AWS_REGION + }); + } + + async uploadFile(bucket: string, key: string, content: Buffer, options: FileUploadOptions): Promise { + await this.s3 + .putObject({ + Bucket: bucket, + Key: key, + Body: content, + ContentEncoding: options.encoding, + ContentType: options.mimeType + }) + .promise(); + + return `https://${bucket}.s3.${process.env.AWS_REGION}.amazonaws.com/${key}`; + } + + async getFile(bucket: string, key: string): Promise { + const result = await this.s3.getObject({ Bucket: bucket, Key: key }).promise(); + return result.Body as Buffer; + } + + async deleteFile(bucket: string, key: string): Promise { + await this.s3.deleteObject({ Bucket: bucket, Key: key }).promise(); + } + + async storeObject(bucket: string, persistent: boolean, key: string, body: unknown): Promise { + const objKey = persistent ? `persist/${key}` : `default/${key}`; + const buffer = Buffer.from(JSON.stringify(body)); + + await this.s3 + .putObject({ + Bucket: bucket, + Key: objKey, + Body: buffer, + ContentEncoding: CommonConstants.ENCODING.toString(), + ContentType: 'application/json' + }) + .promise(); + + return `https://${bucket}.s3.${process.env.AWS_REGION}.amazonaws.com/${objKey}`; + } +} diff --git a/libs/storage/src/storage.interface.ts b/libs/storage/src/storage.interface.ts new file mode 100644 index 000000000..a9da3d5bd --- /dev/null +++ b/libs/storage/src/storage.interface.ts @@ -0,0 +1,22 @@ +// export interface IStorageProvider { +// uploadFile(buffer: Buffer, key: string, mimeType: string): Promise; +// getFile(key: string): Promise; +// deleteFile(key: string): Promise; +// // eslint-disable-next-line @typescript-eslint/no-explicit-any +// storeObject(key: string, body: any): Promise; +// } + +export interface FileUploadOptions { + readonly encoding?: string; + readonly mimeType: string; +} + +export interface IStorageProvider { + uploadFile(bucket: string, key: string, content: Buffer, options: FileUploadOptions): Promise; + + getFile(bucket: string, key: string): Promise; + + deleteFile(bucket: string, key: string): Promise; + + storeObject(bucket: string, persistent: boolean, key: string, body: unknown): Promise; +} diff --git a/libs/storage/src/storage.module.ts b/libs/storage/src/storage.module.ts new file mode 100644 index 000000000..f22926ec2 --- /dev/null +++ b/libs/storage/src/storage.module.ts @@ -0,0 +1,8 @@ +import { Module } from '@nestjs/common'; +import { StorageService } from './storage.service'; + +@Module({ + providers: [StorageService], + exports: [StorageService] +}) +export class StorageModule {} diff --git a/libs/aws/src/aws.service.spec.ts b/libs/storage/src/storage.service.spec.ts similarity index 54% rename from libs/aws/src/aws.service.spec.ts rename to libs/storage/src/storage.service.spec.ts index f37dab349..b1e34ce70 100644 --- a/libs/aws/src/aws.service.spec.ts +++ b/libs/storage/src/storage.service.spec.ts @@ -1,15 +1,15 @@ import { Test, TestingModule } from '@nestjs/testing'; -import { AwsService } from './aws.service'; +import { StorageService } from './storage.service'; -describe('AwsService', () => { - let service: AwsService; +describe('StorageService', () => { + let service: StorageService; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ - providers: [AwsService] + providers: [StorageService] }).compile(); - service = module.get(AwsService); + service = module.get(StorageService); }); it('should be defined', () => { diff --git a/libs/storage/src/storage.service.ts b/libs/storage/src/storage.service.ts new file mode 100644 index 000000000..95567c47c --- /dev/null +++ b/libs/storage/src/storage.service.ts @@ -0,0 +1,77 @@ +import { HttpException, HttpStatus, Injectable } from '@nestjs/common'; +import { RpcException } from '@nestjs/microservices'; +import { IStorageProvider } from './storage.interface'; +import { S3Provider } from './providers/s3.provider'; +import { MinioProvider } from './providers/minio.provider'; + +@Injectable() +export class StorageService { + private readonly provider: IStorageProvider; + + constructor() { + const fileStorageProvider = process.env.FILE_STORAGE_PROVIDER; + switch (fileStorageProvider) { + case 'minio': + this.provider = new MinioProvider(); + break; + case 's3': + default: + this.provider = new S3Provider(); + break; + } + } + + async uploadFileToBucket( + fileBuffer: Buffer, + ext: string, + filename: string, + bucketName: string, + encoding: string, + filePath = '' + ): Promise { + const timestamp = Date.now(); + const key = `${filePath}/${encodeURIComponent(filename)}-${timestamp}.${ext}`; + try { + return await this.provider.uploadFile(bucketName, key, fileBuffer, { + encoding, + mimeType: 'image/png' + }); + } catch (error) { + throw new HttpException(error, HttpStatus.SERVICE_UNAVAILABLE); + } + } + + async uploadCsvFile(key: string, body: unknown): Promise { + try { + await this.provider.uploadFile(process.env.FILE_BUCKET as string, key, Buffer.from(String(body)), { + mimeType: 'text/csv' + }); + } catch (error) { + throw new RpcException(error.response ? error.response : error); + } + } + + async getFile(key: string): Promise { + try { + return await this.provider.getFile(process.env.FILE_BUCKET as string, key); + } catch (error) { + throw new RpcException(error.response ? error.response : error); + } + } + + async deleteFile(key: string): Promise { + try { + await this.provider.deleteFile(process.env.FILE_BUCKET as string, key); + } catch (error) { + throw new RpcException(error.response ? error.response : error); + } + } + + async storeObject(persistent: boolean, key: string, body: unknown): Promise { + try { + return await this.provider.storeObject(process.env.STORE_OBJECT_BUCKET as string, persistent, key, body); + } catch (error) { + throw new RpcException(error.response ? error.response : error); + } + } +} diff --git a/libs/storage/tsconfig.build.json b/libs/storage/tsconfig.build.json new file mode 100644 index 000000000..b99dca801 --- /dev/null +++ b/libs/storage/tsconfig.build.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "declaration": true, + "outDir": "../../dist/libs/storage" + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist", "test", "**/*spec.ts"] +} diff --git a/libs/aws/tsconfig.json b/libs/storage/tsconfig.json similarity index 100% rename from libs/aws/tsconfig.json rename to libs/storage/tsconfig.json diff --git a/package.json b/package.json index 7bf48a14d..0b1ebe022 100644 --- a/package.json +++ b/package.json @@ -199,7 +199,8 @@ "^credebl/utility(|/.*)$": "/libs/utility/src/$1", "^@credebl/config(|/.*)$": "/libs/config/src/$1", "^@credebl/context(|/.*)$": "/libs/context/src/$1", - "^@credebl/logger(|/.*)$": "/libs/logger/src/$1" + "^@credebl/logger(|/.*)$": "/libs/logger/src/$1", + "^@credebl/storage(|/.*)$": "/libs/storage/src/$1" } }, "packageManager": "pnpm@9.15.3+sha512.1f79bc245a66eb0b07c5d4d83131240774642caaa86ef7d0434ab47c0d16f66b04e21e0c086eb61e62c77efc4d7f7ec071afad3796af64892fae66509173893a", diff --git a/tsconfig.json b/tsconfig.json index 74a5fa904..81c80b375 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -103,6 +103,12 @@ ], "@credebl/context/*": [ "libs/context/src/*" + ], + "@credebl/storage": [ + "libs/storage/src" + ], + "@credebl/storage/*": [ + "libs/storage/src/*" ] } },