Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 23 additions & 21 deletions .env.sample
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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='

[email protected] // 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'
Expand Down Expand Up @@ -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
# 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
Comment on lines +192 to +211
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Address dotenv formatting issues.

The new storage provider configuration is functionally correct, but static analysis has identified multiple formatting issues that should be addressed:

  1. Missing quotes: Values should be quoted (e.g., FILE_STORAGE_PROVIDER="minio")
  2. Space characters: Remove spaces around equal signs (e.g., AWS_ACCESS_KEY= not AWS_ACCESS_KEY= )
  3. Missing ending blank line: Add a blank line at the end of the file

Apply these formatting fixes:

 
-# FILE_STORAGE_PROVIDER can be 'aws' or 'minio'
-FILE_STORAGE_PROVIDER=minio
+# 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
+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
+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
+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
+
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# 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
# 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
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 196-196: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 197-197: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 198-198: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 198-198: [UnorderedKey] The AWS_ACCESS_KEY key should go before the AWS_ACCOUNT_ID key

(UnorderedKey)


[warning] 198-198: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 199-199: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 199-199: [UnorderedKey] The AWS_SECRET_KEY key should go before the S3_BUCKET_ARN key

(UnorderedKey)


[warning] 199-199: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 200-200: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 200-200: [UnorderedKey] The AWS_REGION key should go before the AWS_SECRET_KEY key

(UnorderedKey)


[warning] 200-200: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 203-203: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 203-203: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 204-204: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 204-204: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 205-205: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 205-205: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 206-206: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 206-206: [UnorderedKey] The MINIO_ACCESS_KEY key should go before the MINIO_ENDPOINT key

(UnorderedKey)


[warning] 206-206: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 207-207: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 207-207: [UnorderedKey] The MINIO_SECRET_KEY key should go before the MINIO_USE_SSL key

(UnorderedKey)


[warning] 207-207: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 209-209: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 209-209: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 210-210: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 210-210: [UnorderedKey] The FILE_BUCKET key should go before the STORE_OBJECT_BUCKET key

(UnorderedKey)


[warning] 210-210: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)


[warning] 211-211: [EndingBlankLine] No blank line at the end of the file

(EndingBlankLine)


[warning] 211-211: [SpaceCharacter] The line has spaces around equal sign

(SpaceCharacter)


[warning] 211-211: [UnorderedKey] The ORG_LOGO_BUCKET key should go before the STORE_OBJECT_BUCKET key

(UnorderedKey)


[warning] 211-211: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

🤖 Prompt for AI Agents
In .env.sample around lines 192-211, fix dotenv formatting by (1) quoting all
assigned values (e.g., FILE_STORAGE_PROVIDER="minio", AWS_ACCOUNT_ID="xxxxx",
etc.), (2) removing any spaces around the '=' so assignments are like
KEY="value" with no surrounding spaces, (3) move inline comments off assignment
lines to their own comment lines above or below if needed (don’t leave comments
after values), and (4) ensure the file ends with a single trailing newline
(blank line) at EOF.

6 changes: 3 additions & 3 deletions apps/api-gateway/src/authz/guards/user-role.guard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
}
Comment on lines +11 to 17
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Incomplete optional chaining will throw TypeError.

The optional chaining operator ?. only applies to the immediate property access. In user?.realm_access.roles, if user exists but realm_access is undefined, accessing .roles on undefined will throw a TypeError. The same issue exists on line 15 with .includes('holder').

Apply this diff to add proper optional chaining:

-    if (!user?.realm_access.roles) {
-      throw new ForbiddenException('This role is not a holder.');
+    if (!user?.realm_access?.roles) {
+      throw new ForbiddenException('User roles not found.');
     }
 
-    if (!user?.realm_access.roles.includes('holder')) {
+    if (!user.realm_access.roles.includes('holder')) {
       throw new ForbiddenException('This role is not a holder.');
     }

Note: Line 15 no longer needs optional chaining after line 11's validation confirms the path exists.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
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.');
}
if (!user?.realm_access?.roles) {
throw new ForbiddenException('User roles not found.');
}
if (!user.realm_access.roles.includes('holder')) {
throw new ForbiddenException('This role is not a holder.');
}
🤖 Prompt for AI Agents
In apps/api-gateway/src/authz/guards/user-role.guard.ts around lines 11 to 17,
the optional chaining is incomplete and may throw if realm_access is undefined;
change the existence check to guard the whole path (e.g., verify
user?.realm_access?.roles) and after that extract roles into a local const and
use roles.includes('holder') (no optional chaining) to perform the membership
check, throwing the same ForbiddenException when the path or the role is
missing.


Expand Down
8 changes: 4 additions & 4 deletions apps/api-gateway/src/issuance/issuance.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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');

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down
4 changes: 2 additions & 2 deletions apps/api-gateway/src/issuance/issuance.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: [
Expand All @@ -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 {}
4 changes: 2 additions & 2 deletions apps/api-gateway/src/organization/organization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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({
Expand All @@ -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 {}
3 changes: 2 additions & 1 deletion apps/api-gateway/src/organization/organization.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 }> {
Expand Down
4 changes: 2 additions & 2 deletions apps/api-gateway/src/user/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -61,7 +61,7 @@ export class UserController {
constructor(
private readonly userService: UserService,
private readonly commonService: CommonService,
private readonly awsService: AwsService
private readonly storageService: StorageService
) {}

/**
Expand Down
5 changes: 2 additions & 3 deletions apps/api-gateway/src/user/user.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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 {}
6 changes: 3 additions & 3 deletions apps/api-gateway/src/webhook/webhook.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand All @@ -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 {}
5 changes: 3 additions & 2 deletions apps/cloud-wallet/src/cloud-wallet.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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}` : ''
}`;
Comment on lines +179 to +181
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix the URL construction to remove the trailing slash before the query parameter.

The URL construction includes a hardcoded / before the query parameter, resulting in malformed URLs:

  • With threadId: .../proof-request/?threadId=xyz (extra / before ?)
  • Without threadId: .../proof-request/ (trailing /)

Standard REST URL format should not have a trailing slash before query parameters: .../proof-request?threadId=xyz

Apply this diff to fix the URL construction:

-      const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}/${
-        threadId ? `?threadId=${threadId}` : ''
-      }`;
+      const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}${
+        threadId ? `?threadId=${threadId}` : ''
+      }`;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}/${
threadId ? `?threadId=${threadId}` : ''
}`;
const url = `${agentEndpoint}${CommonConstants.CLOUD_WALLET_GET_PROOF_REQUEST}${
threadId ? `?threadId=${threadId}` : ''
}`;
🤖 Prompt for AI Agents
In apps/cloud-wallet/src/cloud-wallet.service.ts around lines 179 to 181, the
URL is built with a hardcoded slash before the query string causing either an
extra slash before `?` or a trailing slash; remove the trailing `/` from the
base path and concatenate the query parameter only when present (e.g. build URL
as agentEndpoint + CLOUD_WALLET_GET_PROOF_REQUEST followed by `?threadId=...`
only if threadId exists), ensuring no extra `/` remains before the `?` and no
trailing slash is left when threadId is absent.

const getProofById = await this.commonService.httpGet(url, { headers: { authorization: decryptedApiKey } });
return getProofById;
} catch (error) {
Expand Down
4 changes: 2 additions & 2 deletions apps/issuance/src/issuance.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -57,7 +57,7 @@ import { NATSClient } from '@credebl/common/NATSClient';
OutOfBandIssuance,
EmailDto,
BulkIssuanceProcessor,
AwsService,
StorageService,
NATSClient,
{
provide: MICRO_SERVICE_NAME,
Expand Down
11 changes: 4 additions & 7 deletions apps/issuance/src/issuance.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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';
Expand All @@ -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
) {}
Comment on lines +109 to 114
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Constructor injection still references removed provider

ContextStorageServiceKey and natsClient remain injected even though the corresponding provider was removed with the AWS service refactor. Keeping this stale dependency will break DI at runtime because Nest can no longer resolve ContextStorageServiceKey. Please drop the injection (and related property) or ensure the token is still registered.

🤖 Prompt for AI Agents
In apps/issuance/src/issuance.service.ts around lines 109 to 114, the
constructor still injects @Inject(ContextStorageServiceKey) private readonly
natsClient: NATSClient even though that provider was removed; remove the
injection parameter and the natsClient property from the constructor (and delete
or update any usages of this.natsClient in the class), or if the dependency must
remain, re-register the ContextStorageServiceKey provider and ensure its token
matches the refactored AWS service; pick one approach and apply it consistently
so Nest DI can resolve the constructor.


Expand Down Expand Up @@ -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();

Comment on lines +1290 to 1292
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

StorageService.getFile() returns buffers

The new storage service resolves files to Buffer instances. Calling toString() without passing the expected encoding will use UTF‑8 implicitly, which corrupts binary CSVs uploaded with base64 encoding. Capture and honor the encoding (e.g., pass CommonConstants.ENCODING) when converting, or make StorageService.getFile return the decoded string directly.

🤖 Prompt for AI Agents
In apps/issuance/src/issuance.service.ts around lines 1290-1292, the code calls
toString() on the Buffer returned by StorageService.getFile which implicitly
uses UTF-8 and can corrupt CSVs uploaded as base64; update the call to decode
the buffer with the expected encoding (e.g., csvData =
getFileDetails.toString(CommonConstants.ENCODING)) or change
StorageService.getFile to return the decoded string directly so callers receive
the correctly decoded CSV content.

const parsedData = paParse(csvData, {
header: true,
Expand Down
33 changes: 21 additions & 12 deletions apps/organization/src/organization.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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 {}
Loading