diff --git a/.env.demo b/.env.demo index 798d80260..c51b72ae0 100644 --- a/.env.demo +++ b/.env.demo @@ -6,6 +6,8 @@ API_ENDPOINT=your-ip:5000 FRONT_END_URL=http://localhost:3001 +FILE_STORAGE_PROVIDER=minio + MOBILE_APP=ADEYA MOBILE_APP_NAME=ADEYA SSI App MOBILE_APP_DOWNLOAD_URL='https://blockster.global/products/adeya' @@ -13,9 +15,9 @@ PLAY_STORE_DOWNLOAD_LINK=https://play.google.com/store/apps/details?id=id.credeb IOS_DOWNLOAD_LINK=https://apps.apple.com/in/app/adeya-ssi-wallet/id6463845498 PLATFORM_NAME=CREDEBL -POWERED_BY=Blockster Labs Pvt. Ltd. +POWERED_BY=CREDEBL a Series of LF Projects, LLC PLATFORM_WEB_URL=https://credebl.id/ -POWERED_BY_URL=https://blockster.global +POWERED_BY_URL=https://lfprojects.org UPLOAD_LOGO_HOST=devapi.credebl.id BRAND_LOGO=https://credebl.id/images/CREDEBL_LOGO.png PLATFORM_ADMIN_EMAIL=platform.admin@yopmail.com @@ -45,8 +47,7 @@ PUBLIC_DEV_API_URL=https://devapi.credebl.id PUBLIC_QA_API_URL=https://qa-api.credebl.id PUBLIC_PRODUCTION_API_URL=https://api.credebl.id PUBLIC_SANDBOX_API_URL=https://sandboxapi.credebl.id -PUBLIC_PLATFORM_SUPPORT_EMAIL=support@blockster.global - +PUBLIC_PLATFORM_SUPPORT_EMAIL=support@sovio.id AFJ_VERSION=ghcr.io/credebl/credo-controller:latest PLATFORM_WALLET_NAME=platform-admin @@ -58,30 +59,36 @@ PLATFORM_ID=1 POOL_DATABASE_URL="postgresql://postgres:postgres@your-ip:5432/credebl" DATABASE_URL="postgresql://postgres:postgres@your-ip:5432/credebl" +# MinIO Config : Use the same buckets as below three mentioned with AWS S3 config +MINIO_ENDPOINT=localhost +MINIO_PORT=9000 +MINIO_USE_SSL=false +MINIO_ACCESS_KEY= +MINIO_SECRET_KEY= + # Used for Bulk issuance of credential # Optional (Can be skipped if Bulk issuance is not used) AWS_ACCESS_KEY= AWS_SECRET_KEY= AWS_REGION= -AWS_BUCKET= +FILE_BUCKET= # Used for Adding org-logo during org creation and update # Optional (Can be skipped if no image is added during org creation and updation) AWS_PUBLIC_ACCESS_KEY= AWS_PUBLIC_SECRET_KEY= AWS_PUBLIC_REGION= -AWS_ORG_LOGO_BUCKET_NAME= +ORG_LOGO_BUCKET= # Used for storing connection URL generated from Agent and creating shortened URL # Required (As connecting to org requires Shortened url) AWS_S3_STOREOBJECT_ACCESS_KEY= AWS_S3_STOREOBJECT_SECRET_KEY= -AWS_S3_STOREOBJECT_REGION= -AWS_S3_STOREOBJECT_BUCKET= +AWS_S3_STOREOBJECT_REGION= +STORE_OBJECT_BUCKET= # Please refere AWS to determine your bucket url # https://docs.aws.amazon.com/AmazonS3/latest/userguide/VirtualHosting.html#path-style-access -SHORTENED_URL_DOMAIN='https://AWS_S3_STOREOBJECT_REGION.amazonaws.com/AWS_S3_STOREOBJECT_BUCKET' DEEPLINK_DOMAIN='https://link.credebl.id?url=' ENABLE_CORS_IP_LIST=http://localhost:3000,http://localhost:3001,http://localhost:5000,http://localhost:8085 @@ -186,4 +193,4 @@ 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 diff --git a/apps/agent-provisioning/AFJ/scripts/fargate.sh b/apps/agent-provisioning/AFJ/scripts/fargate.sh index bb8ea9b66..6c43ca208 100644 --- a/apps/agent-provisioning/AFJ/scripts/fargate.sh +++ b/apps/agent-provisioning/AFJ/scripts/fargate.sh @@ -1,3 +1,4 @@ + #!/bin/sh START_TIME=$(date +%s) @@ -18,17 +19,62 @@ TENANT=${13} AFJ_VERSION=${14} INDY_LEDGER=${15} INBOUND_ENDPOINT=${16} -SCHEMA_FILE_SERVER_URL=${17} -AGENT_API_KEY=${18} -AWS_ACCOUNT_ID=${19} -S3_BUCKET_ARN=${20} -CLUSTER_NAME=${21} -TASKDEFINITION_FAMILY=${22} -ADMIN_TG_ARN=${23} -INBOUND_TG_ARN=${24} -FILESYSTEMID=${25} -ECS_SUBNET_ID=${26} -ECS_SECURITY_GROUP_ID=${27} +AWS_ACCOUNT_ID=${17} +S3_BUCKET_ARN=${18} +CLUSTER_NAME=${19} +FILESYSTEMID=${20} +ACCESSPOINTID=${21} +VPC_ID=${22} +ECS_SUBNET_ID=${23} +ALB_SUBNET_ID_ONE=${24} +ALB_SUBNET_ID_TWO=${25} +EFS_SECURITY_GROUP_ID=${26} +AWS_PUBLIC_REGION=${27} +STAGE=${28} +AGENT_WEBSOCKET_PROTOCOL=${29} +DB_SECURITY_GROUP_ID=${30} +TESKDEFINITION_FAMILY="${STAGE}_${CONTAINER_NAME}_TASKDEFITION" + + +echo "START_TIME: $START_TIME" +echo "AGENCY: $AGENCY" +echo "EXTERNAL_IP: $EXTERNAL_IP" +echo "WALLET_NAME: $WALLET_NAME" +echo "WALLET_PASSWORD: $WALLET_PASSWORD" +echo "RANDOM_SEED: $RANDOM_SEED" +echo "WEBHOOK_HOST: $WEBHOOK_HOST" +echo "WALLET_STORAGE_HOST: $WALLET_STORAGE_HOST" +echo "WALLET_STORAGE_PORT: $WALLET_STORAGE_PORT" +echo "WALLET_STORAGE_USER: $WALLET_STORAGE_USER" +echo "WALLET_STORAGE_PASSWORD: $WALLET_STORAGE_PASSWORD" +echo "CONTAINER_NAME: $CONTAINER_NAME" +echo "PROTOCOL: $PROTOCOL" +echo "TENANT: $TENANT" +echo "AFJ_VERSION: $AFJ_VERSION" +echo "INDY_LEDGER: $INDY_LEDGER" +echo "INBOUND_ENDPOINT: $INBOUND_ENDPOINT" +echo "AWS_ACCOUNT_ID: $AWS_ACCOUNT_ID" +echo "S3_BUCKET_ARN: $S3_BUCKET_ARN" +echo "CLUSTER_NAME: $CLUSTER_NAME" +echo "TESKDEFINITION_FAMILY: $TESKDEFINITION_FAMILY" +echo "FILESYSTEMID: $FILESYSTEMID" +echo "ACCESSPOINTID: $ACCESSPOINTID" +echo "VPC_ID: $VPC_ID" +echo "ECS_SUBNET_ID: $ECS_SUBNET_ID" +echo "ALB_SUBNET_ID_ONE: $ALB_SUBNET_ID_ONE" +echo "ALB_SUBNET_ID_TWO: $ALB_SUBNET_ID_TWO" +echo "SSL_CRTS: $SSL_CRTS" +echo "EFS_SECURITY_GROUP_ID: $EFS_SECURITY_GROUP_ID" +echo "AGENT_URL: $AGENT_URL" +echo "AWS_PUBLIC_REGION: $AWS_PUBLIC_REGION" +echo "STAGE: $STAGE" +echo "AGENT_WEBSOCKET_PROTOCOL: $AGENT_WEBSOCKET_PROTOCOL" +echo "ALB_SECURITY_GROUP_ID: $ALB_SECURITY_GROUP_ID" +echo "ADMIN_TG_ARN: $ADMIN_TG_ARN" +echo "INBOUND_TG_ARN: $INBOUND_TG_ARN" +echo "AGENT_INBOUND_URL: $AGENT_INBOUND_URL" +echo "DB_SECURITY_GROUP_ID: $DB_SECURITY_GROUP_ID" + DESIRED_COUNT=1 @@ -42,10 +88,12 @@ random_string=$(generate_random_string) # Print the generated random string echo "Random String: $random_string" -SERVICE_NAME="${CONTAINER_NAME}-service" +SERVICE_NAME="${AGENCY}-${CONTAINER_NAME}-service-${random_string}" EXTERNAL_IP=$(echo "$2" | tr -d '[:space:]') ADMIN_PORT_FILE="$PWD/agent-provisioning/AFJ/port-file/last-admin-port.txt" INBOUND_PORT_FILE="$PWD/agent-provisioning/AFJ/port-file/last-inbound-port.txt" +echo "AGENCY: $SERVICE_NAME" +echo "EXTERNAL_IP: $EXTERNAL_IP" ADMIN_PORT=8001 INBOUND_PORT=9001 @@ -96,24 +144,209 @@ echo "Last used admin port: $ADMIN_PORT" echo "Last used inbound port: $INBOUND_PORT" echo "AGENT SPIN-UP STARTED" -# Define a regular expression pattern for IP address -IP_REGEX="^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$" -# Check if INBOUND_ENDPOINT is a domain or IP address -if [[ $INBOUND_ENDPOINT =~ ^https?://[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then - echo "INBOUND_ENDPOINT is a domain: $INBOUND_ENDPOINT" - # Extracting the domain name without the protocol - AGENT_ENDPOINT=$(echo "$INBOUND_ENDPOINT" | sed 's/^https\?:\/\///') -else - # Check if the input is an IP address - if [[ $INBOUND_ENDPOINT =~ $IP_REGEX ]]; then - echo "INBOUND_ENDPOINT is an IP address: $INBOUND_ENDPOINT" - # Adding the protocol to the IP address - AGENT_ENDPOINT="${PROTOCOL}://${INBOUND_ENDPOINT}:${INBOUND_PORT}" - else - echo "Invalid input for INBOUND_ENDPOINT: $INBOUND_ENDPOINT" - fi -fi +#CLUSTER_NAME=$(aws ecs create-cluster --cluster-name ${CONTAINER_NAME}) + +# Create security groups +ALB_SECURITY_GROUP_ID=$(aws ec2 create-security-group --group-name "${STAGE}-${AGENCY}-${random_string}-alb-sg" --description "Security group for ALB" --vpc-id $VPC_ID --output text) +ECS_SECURITY_GROUP_ID=$(aws ec2 create-security-group --group-name "${STAGE}-${AGENCY}-${random_string}-ecs-sg" --description "Security group for ECS Fargate service" --vpc-id $VPC_ID --output text) + +echo "ALB_SECURITY_GROUP_ID:$ALB_SECURITY_GROUP_ID" +echo "ECS_SECURITY_GROUP_ID:$ECS_SECURITY_GROUP_ID" +echo "EFS_SECURITY_GROUP_ID:$SECURITY_GROUP_ID" + +# Allow inbound traffic from the ECS Fargate security group to the EFS security group on NFS port +aws ec2 authorize-security-group-ingress \ + --group-id "$EFS_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port 2049 \ + --source-group "$ECS_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-allow},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize inbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-ingress \ + --group-id "$ECS_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$ADMIN_PORT" \ + --source-group "$ALB_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-alb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + + +# Authorize outbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-egress \ + --group-id "$ECS_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$ADMIN_PORT" \ + --source-group "$ALB_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-alb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + + +# Authorize inbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-ingress \ + --group-id "$ECS_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$INBOUND_PORT" \ + --source-group "$ALB_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-alb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize outbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-egress \ + --group-id "$ECS_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$INBOUND_PORT" \ + --source-group "$ALB_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-alb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize inbound traffic for ECS security group from DB security group +aws ec2 authorize-security-group-ingress \ + --group-id "$DB_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$WALLET_STORAGE_PORT" \ + --source-group "$ECS_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-ecs-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize outbound traffic for ECS security group from DB security group +aws ec2 authorize-security-group-egress \ + --group-id "$DB_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$WALLET_STORAGE_PORT" \ + --source-group "$ECS_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-ecs-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize inbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-ingress \ + --group-id "$ALB_SECURITY_GROUP_ID" \ + --ip-permissions IpProtocol=tcp,FromPort=443,ToPort=443,IpRanges='[{CidrIp=0.0.0.0/0,Description="Allowing 0.0.0.0/0 to the LB port"}]' \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=allow-the-world}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize outbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-egress \ + --group-id "$ALB_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$ADMIN_PORT" \ + --source-group "$ECS_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-adminalb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize inbound traffic for ALB security group from ECS security group +aws ec2 authorize-security-group-ingress \ + --group-id "$ALB_SECURITY_GROUP_ID" \ + --ip-permissions IpProtocol=tcp,FromPort=80,ToPort=80,IpRanges='[{CidrIp=0.0.0.0/0,Description="Allowing 0.0.0.0/0 to the LB port"}]' \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=allow-the-world}]" \ + --region $AWS_PUBLIC_REGION + +# Authorize outbound traffic of ALB security group for ECS security group +aws ec2 authorize-security-group-egress \ + --group-id "$ALB_SECURITY_GROUP_ID" \ + --protocol tcp \ + --port "$INBOUND_PORT" \ + --source-group "$ECS_SECURITY_GROUP_ID" \ + --tag-specifications "ResourceType=security-group-rule,Tags=[{Key=Name,Value=${STAGE}-${AGENCY}-${CONTAINER_NAME}-inboundalb-sg},{Key=ENV,Value=test}]" \ + --region $AWS_PUBLIC_REGION + + +# Create Target Groups for admin port +ADMIN_TG_ARN=$(aws elbv2 create-target-group \ + --name "${STAGE}-${ADMIN_PORT}-tg" \ + --protocol HTTP \ + --port 80 \ + --target-type ip \ + --vpc-id $VPC_ID \ + --health-check-protocol HTTP \ + --health-check-port $ADMIN_PORT \ + --health-check-path /agent \ + --health-check-interval-seconds 120 \ + --query 'TargetGroups[0].TargetGroupArn' \ + --output text) + + +echo "admin-tg-arm: $ADMIN_TG_ARN" + +# Create Target Groups for inbound port +INBOUND_TG_ARN=$(aws elbv2 create-target-group --name "${STAGE}-${INBOUND_PORT}-tg" --protocol HTTP --port 80 --target-type ip --vpc-id $VPC_ID --query 'TargetGroups[0].TargetGroupArn' --output text) + +echo "admin-tg-arm: $INBOUND_TG_ARN" + + +# Create Application Load Balancer +ADMIN_ALB_ARN=$(aws elbv2 create-load-balancer \ +--name $STAGE-$CONTAINER_NAME-${ADMIN_PORT}-alb \ +--subnets $ALB_SUBNET_ID_ONE $ALB_SUBNET_ID_TWO \ +--tags "[{\"Key\":\"Name\", \"Value\":\"${CONTAINER_NAME}-alb\"}]" \ +--type application \ +--scheme internet-facing \ +--security-groups $ALB_SECURITY_GROUP_ID \ +--region $AWS_PUBLIC_REGION \ +--query "LoadBalancers[0].LoadBalancerArn" \ +--output text) + +# Describe the ALB to retrieve its DNS name +ADMIN_ALB_DNS=$(aws elbv2 describe-load-balancers \ +--load-balancer-arns $ADMIN_ALB_ARN \ +--query "LoadBalancers[0].DNSName" \ +--output text) + +echo "ALB DNS: $ADMIN_ALB_DNS" + +# Create HTTP listener +aws elbv2 create-listener \ + --load-balancer-arn "$ADMIN_ALB_ARN" \ + --protocol HTTP \ + --port 80 \ + --default-actions Type=forward,TargetGroupArn="$ADMIN_TG_ARN" \ + --region "$AWS_PUBLIC_REGION" + + + +# Create Application Load Balancer +INBOUND_ALB_ARN=$(aws elbv2 create-load-balancer \ +--name $STAGE-$CONTAINER_NAME-${INBOUND_PORT}-alb \ +--subnets $ALB_SUBNET_ID_ONE $ALB_SUBNET_ID_TWO \ +--tags "[{\"Key\":\"Name\", \"Value\":\"${CONTAINER_NAME}-alb\"}]" \ +--type application \ +--scheme internet-facing \ +--security-groups $ALB_SECURITY_GROUP_ID \ +--region $AWS_PUBLIC_REGION \ +--query "LoadBalancers[0].LoadBalancerArn" \ +--output text) + +# Describe the ALB to retrieve its DNS name +INBOUND_ALB_DNS=$(aws elbv2 describe-load-balancers \ +--load-balancer-arns $INBOUND_ALB_ARN \ +--query "LoadBalancers[0].DNSName" \ +--output text) + +echo "INBOUND_ALB DNS: $INBOUND_ALB_DNS" + +#add listner to inbound +aws elbv2 create-listener \ + --load-balancer-arn $INBOUND_ALB_ARN \ + --protocol HTTP \ + --port 80 \ + --default-actions Type=forward,TargetGroupArn=$INBOUND_TG_ARN \ + --region $AWS_PUBLIC_REGION + + +# modify health check of inboud tg +aws elbv2 modify-target-group \ + --target-group-arn $INBOUND_TG_ARN \ + --health-check-protocol HTTP \ + --health-check-port "traffic-port" \ + --health-check-path "/" \ + --health-check-interval-seconds 30 \ + --healthy-threshold-count 3 \ + --unhealthy-threshold-count 3 \ + --matcher "HttpCode=404" \ + --region $AWS_PUBLIC_REGION + # Generate the agent config JSON cat <$PWD/agent-provisioning/AFJ/agent-config/${AGENCY}_${CONTAINER_NAME}.json @@ -130,7 +363,7 @@ cat <$PWD/agent-provisioning/AFJ/agent-config/${AGENCY}_${CONTAINER_NAME}. "walletScheme": "DatabasePerWallet", "indyLedger": $INDY_LEDGER, "endpoint": [ - "$INBOUND_ENDPOINT" + "http://$INBOUND_ALB_DNS" ], "autoAcceptConnections": true, "autoAcceptCredentials": "contentApproved", @@ -138,18 +371,16 @@ cat <$PWD/agent-provisioning/AFJ/agent-config/${AGENCY}_${CONTAINER_NAME}. "logLevel": 5, "inboundTransport": [ { - "transport": "$PROTOCOL", - "port": $INBOUND_PORT + "transport": "$AGENT_WEBSOCKET_PROTOCOL", + "port": "$INBOUND_PORT" } ], "outboundTransport": [ - "$PROTOCOL" + "$AGENT_WEBSOCKET_PROTOCOL" ], "webhookUrl": "$WEBHOOK_HOST/wh/$AGENCY", "adminPort": $ADMIN_PORT, - "tenancy": $TENANT, - "schemaFileServerURL": "$SCHEMA_FILE_SERVER_URL", - "apiKey": "$AGENT_API_KEY" + "tenancy": $TENANT } EOF @@ -159,9 +390,9 @@ CONTAINER_DEFINITIONS=$( [ { "name": "$CONTAINER_NAME", - "image": "${AFJ_VERSION}", - "cpu": 307, - "memory": 358, + "image": "${AFJ_IMAGE_URL}", + "cpu": 256, + "memory": 512, "portMappings": [ { "containerPort": $ADMIN_PORT, @@ -194,7 +425,7 @@ CONTAINER_DEFINITIONS=$( ], "mountPoints": [ { - "sourceVolume": "config", + "sourceVolume": "AGENT-CONFIG", "containerPath": "/config", "readOnly": true } @@ -203,16 +434,16 @@ CONTAINER_DEFINITIONS=$( "volumesFrom": [], "ulimits": [], "logConfiguration": { - "logDriver": "awslogs", - "options": { - "awslogs-create-group": "true", - "awslogs-group": "/ecs/$TASKDEFINITION_FAMILY", - "awslogs-region": "$AWS_PUBLIC_REGION", - "awslogs-stream-prefix": "ecs" -} - }, - "ulimits": [] -} + "logDriver": "awslogs", + "options": { + "awslogs-create-group": "true", + "awslogs-group": "/ecs/$TESKDEFINITION_FAMILY", + "awslogs-region": "$AWS_PUBLIC_REGION", + "awslogs-stream-prefix": "ecs" + }, + "secretOptions": [] + } + } ] EOF ) @@ -220,27 +451,28 @@ EOF # Define the task definition JSON TASK_DEFINITION=$(cat < task_definition.json TASK_DEFINITION_ARN=$(aws ecs register-task-definition --cli-input-json file://task_definition.json --query 'taskDefinition.taskDefinitionArn' --output text) -SERVICE_JSON=$(cat < service.json +echo "$SERVICE" > service.json # Check if the service file was created successfully -if [ -f "service.json" ]; then - echo "Service file created successfully: service.json" +if [ -f "$SERVICE_FILE" ]; then + echo "Service file created successfully: $SERVICE_FILE" else - echo "Failed to create service file: service.json" + echo "Failed to create service file: $SERVICE_FILE" fi # Create the service aws ecs create-service \ - --cli-input-json file://service.json \ - --region $AWS_PUBLIC_REGION +--service-name $SERVICE_NAME \ +--cli-input-json file://service.json \ +--region $AWS_PUBLIC_REGION # Describe the ECS service and filter by service name service_description=$(aws ecs describe-services --service $SERVICE_NAME --cluster $CLUSTER_NAME --region $AWS_PUBLIC_REGION) @@ -312,28 +552,26 @@ else exit 1 fi -if [ $? -eq 0 ]; then - - n=0 - until [ "$n" -ge 6 ]; do - if netstat -tln | grep ${ADMIN_PORT} >/dev/null; then - - AGENTURL="http://${EXTERNAL_IP}:${ADMIN_PORT}/agent" - agentResponse=$(curl -s -o /dev/null -w "%{http_code}" $AGENTURL) - - if [ "$agentResponse" = "200" ]; then - echo "Agent is running" && break - else +# Wait for the agent to become ready +# You may need to adjust the number of attempts and sleep time according to your requirements +n=0 +max_attempts=15 +sleep_time=10 +AGENT_HEALTHCHECK_URL="http://$ADMIN_ALB_DNS/agent" +echo "--------AGENT_HEALTHCHECK_URL-----$AGENT_URL" +until [ "$n" -ge "$max_attempts" ]; do + agentResponse=$(curl -s -o /dev/null -w "%{http_code}" "$AGENT_HEALTHCHECK_URL") + if [ "$agentResponse" = "200" ]; then + echo "Agent is running" + break + else echo "Agent is not running" n=$((n + 1)) - sleep 10 - fi - else - echo "No response from agent" - n=$((n + 1)) - sleep 10 + sleep "$sleep_time" fi - done +done + + # Describe the ECS service and filter by service name service_description=$(aws ecs describe-services --service $SERVICE_NAME --cluster $CLUSTER_NAME --region $AWS_PUBLIC_REGION) @@ -341,16 +579,12 @@ echo "service_description=$service_description" # Extract Task ID from the service description events -task_id=$(echo "$service_description" | jq -r ' - .services[0].events[] - | select(.message | test("has started 1 tasks")) - | .message - | capture("\\(task (?[^)]+)\\)") - | .id -') +task_id=$(echo "$service_description" | jq -r '.services[0].events[] | select(.message | test("has started 1 tasks")) | .message | capture("\\(task (?[^)]+)\\)") | .id') +#echo "task_id=$task_id" # to fetch log group of container -log_group=/ecs/$TASKDEFINITION_FAMILY +............................................................. +log_group=/ecs/$TESKDEFINITION_FAMILY echo "log_group=$log_group" # Get Log Stream Name @@ -358,6 +592,10 @@ log_stream=ecs/$CONTAINER_NAME/$task_id echo "logstrem=$log_stream" + +# Fetch logs +#echo "$(aws logs get-log-events --log-group-name "/ecs/$TESKDEFINITION_FAMILY/$CONTAINER_NAME" --log-stream-name "$log_stream" --region $AWS_PUBLIC_REGION)" + # Check if the token folder exists, and create it if it doesn't token_folder="$PWD/agent-provisioning/AFJ/token" if [ ! -d "$token_folder" ]; then @@ -367,6 +605,7 @@ fi # Set maximum retry attempts RETRIES=3 +# Loop to attempt retrieving token from logs # Loop to attempt retrieving token from logs for attempt in $(seq 1 $RETRIES); do echo "Attempt $attempt: Checking service logs for token..." @@ -375,13 +614,9 @@ for attempt in $(seq 1 $RETRIES); do token=$(aws logs get-log-events \ --log-group-name "$log_group" \ --log-stream-name "$log_stream" \ - --region $AWS_PUBLIC_REGION \ - --query 'events[*].message' \ - --output text \ - | tr -d '\033' \ - | grep 'API Key:' \ - | sed -E 's/.*API Key:[[:space:]]*([a-zA-Z0-9._:-]*).*/\1/' \ - | head -n 1 + --region ap-southeast-1 \ + | grep -o 'API Token: [^ ]*' \ + | cut -d ' ' -f 3 ) # echo "token=$token" if [ -n "$token" ]; then @@ -399,23 +634,44 @@ for attempt in $(seq 1 $RETRIES); do sleep 10 done - echo "Creating agent config" - cat <${PWD}/agent-provisioning/AFJ/endpoints/${AGENCY}_${CONTAINER_NAME}.json - { - "CONTROLLER_ENDPOINT":"$EXTERNAL_IP" - } -EOF - cat <${PWD}/agent-provisioning/AFJ/token/${AGENCY}_${CONTAINER_NAME}.json - { - "token" : "$token" - } +# Print variable values for debugging +echo "AGENCY: $AGENCY" +echo "CONTAINER_NAME: $CONTAINER_NAME" +echo "AGENT_URL: $AGENT_URL" +echo "AGENT_INBOUND_URL: $AGENT_INBOUND_URL" + +## Construct file path for agent config +config_file="${PWD}/agent-provisioning/AFJ/endpoints/${AGENCY}_${CONTAINER_NAME}.json" + +# Check if the directory exists and create it if it doesn't +config_dir=$(dirname "$config_file") +if [ ! -d "$config_dir" ]; then + mkdir -p "$config_dir" +fi + +# Create agent config +echo "Creating agent config" +cat <"$config_file" +{ + "CONTROLLER_ENDPOINT": "$ADMIN_ALB_DNS", + "AGENT_ENDPOINT": "$INBOUND_ALB_DNS" +} EOF - echo "Agent config created" +# Check if the file was created successfully +if [ -f "$config_file" ]; then + echo "Agent config created successfully: $config_file" else - echo "===============" - echo "ERROR : Failed to spin up the agent!" - echo "===============" && exit 125 + echo "Failed to create agent config: $config_file" fi -echo "Total time elapsed: $(date -ud "@$(($(date +%s) - $START_TIME))" +%T) (HH:MM:SS)" \ No newline at end of file + +# Print available folders in the AFJ directory +echo "Available folders in the AFJ directory:" +ls -d "${PWD}/agent-provisioning/AFJ/"*/ + +# Print the content of the JSON files +echo "Content of endpoint JSON file:" +cat "$config_file" +echo "Content of token JSON file:" + diff --git a/apps/agent-provisioning/src/agent-provisioning.service.ts b/apps/agent-provisioning/src/agent-provisioning.service.ts index 2f2cc5b2e..274a8fafd 100644 --- a/apps/agent-provisioning/src/agent-provisioning.service.ts +++ b/apps/agent-provisioning/src/agent-provisioning.service.ts @@ -39,7 +39,15 @@ export class AgentProvisioningService { } = payload; if (agentType === AgentType.AFJ) { // The wallet provision command is used to invoke a shell script - const walletProvision = `${process.cwd() + process.env.AFJ_AGENT_SPIN_UP} ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${process.env.SCHEMA_FILE_SERVER_URL} ${process.env.AGENT_API_KEY} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${process.env.CLUSTER_NAME} ${process.env.TASKDEFINITION_FAMILY} ${process.env.ADMIN_TG_ARN} ${process.env.INBOUND_TG_ARN} ${process.env.FILESYSTEMID} ${process.env.ECS_SUBNET_ID} ${process.env.ECS_SECURITY_GROUP_ID}`; + const walletProvision = `${ + process.cwd() + process.env.AFJ_AGENT_SPIN_UP + } ${orgId} "${externalIp}" "${walletName}" "${walletPassword}" ${seed} ${webhookEndpoint} ${walletStorageHost} ${walletStoragePort} ${walletStorageUser} ${walletStoragePassword} ${containerName} ${protocol} ${tenant} ${credoImage} "${indyLedger}" ${inboundEndpoint} ${ + process.env.SCHEMA_FILE_SERVER_URL + } ${process.env.AGENT_API_KEY} ${process.env.AWS_ACCOUNT_ID} ${process.env.S3_BUCKET_ARN} ${ + process.env.CLUSTER_NAME + } ${process.env.TASKDEFINITION_FAMILY} ${process.env.ADMIN_TG_ARN} ${process.env.INBOUND_TG_ARN} ${ + process.env.FILESYSTEMID + } ${process.env.ECS_SUBNET_ID} ${process.env.ECS_SECURITY_GROUP_ID}`; const spinUpResponse: object = new Promise(async (resolve) => { await exec(walletProvision, async (err, stdout, stderr) => { this.logger.log(`shell script output: ${stdout}`); @@ -47,7 +55,9 @@ export class AgentProvisioningService { this.logger.log(`shell script error: ${stderr}`); } - const agentEndpointPath = `${process.cwd()}${process.env.AFJ_AGENT_ENDPOINT_PATH}${orgId}_${containerName}.json`; + const agentEndpointPath = `${process.cwd()}${ + process.env.AFJ_AGENT_ENDPOINT_PATH + }${orgId}_${containerName}.json`; const agentTokenPath = `${process.cwd()}${process.env.AFJ_AGENT_TOKEN_PATH}${orgId}_${containerName}.json`; const agentEndPointExists = await this.checkFileExistence(agentEndpointPath); diff --git a/apps/agent-service/src/agent-service.service.ts b/apps/agent-service/src/agent-service.service.ts index ffa860199..53e7ae5fe 100644 --- a/apps/agent-service/src/agent-service.service.ts +++ b/apps/agent-service/src/agent-service.service.ts @@ -317,7 +317,7 @@ export class AgentServiceService { private async getAgentHealthData(agentEndpoint: string, apiKey: string): Promise { try { return await this.commonService - .httpGet(`${agentEndpoint}${CommonConstants.URL_AGENT_STATUS}`, { + .httpGet(`${agentEndpoint}${CommonConstants.URL_AGENT_GET_ENDPOINT}`, { headers: { authorization: apiKey } }) .then((response) => response); @@ -1529,7 +1529,7 @@ export class AgentServiceService { // Invoke an API request from the agent to assess its current status const agentHealthData = await this.commonService - .httpGet(`${orgAgentDetails.agentEndPoint}${CommonConstants.URL_AGENT_STATUS}`, { + .httpGet(`${orgAgentDetails.agentEndPoint}${CommonConstants.URL_AGENT_GET_ENDPOINT}`, { headers: { authorization: agentApiKey } }) .then(async (response) => response); diff --git a/apps/agent-service/src/repositories/agent-service.repository.ts b/apps/agent-service/src/repositories/agent-service.repository.ts index f561694e5..5a7dee67a 100644 --- a/apps/agent-service/src/repositories/agent-service.repository.ts +++ b/apps/agent-service/src/repositories/agent-service.repository.ts @@ -309,7 +309,7 @@ export class AgentServiceRepository { async getLedgerDetails(name: string[] | string): Promise { try { - let whereClause; + let whereClause: { name: string | { in: string[] } }; if (Array.isArray(name)) { whereClause = { @@ -525,6 +525,7 @@ export class AgentServiceRepository { ]; try { + // eslint-disable-next-line @typescript-eslint/no-explicit-any return await this.prisma.$transaction(async (prisma) => { const referenceCounts = await Promise.all( tablesToCheck.map((table) => prisma[table].count({ where: { orgId } })) diff --git a/apps/api-gateway/src/issuance/issuance.controller.ts b/apps/api-gateway/src/issuance/issuance.controller.ts index 86add6131..be5455532 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'); @@ -367,12 +367,13 @@ export class IssuanceController { @Query('schemaType') schemaType: SchemaType = SchemaType.INDY, @Query('isValidateSchema') isValidateSchema: boolean = true ): Promise { + this.logger.debug(`In uploadCSVTemplate controller method`); const { templateId } = query; 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 +526,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..ab8ce1084 100644 --- a/apps/api-gateway/src/issuance/issuance.module.ts +++ b/apps/api-gateway/src/issuance/issuance.module.ts @@ -5,7 +5,7 @@ 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 { 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: [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..d32098efe 100644 --- a/apps/api-gateway/src/organization/organization.service.ts +++ b/apps/api-gateway/src/organization/organization.service.ts @@ -23,6 +23,7 @@ import { IClientRoles } from '@credebl/client-registration/interfaces/client.int import { GetAllOrganizationsDto } from './dtos/get-organizations.dto'; import { PrimaryDid } from './dtos/set-primary-did.dto'; import { NATSClient } from '@credebl/common/NATSClient'; +import { CommonConstants } from '@credebl/common/common.constant'; import { ClientProxy } from '@nestjs/microservices'; import { ClientTokenDto } from './dtos/client-token.dto'; @@ -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 ef458b295..a41393c86 100644 --- a/apps/cloud-wallet/src/cloud-wallet.service.ts +++ b/apps/cloud-wallet/src/cloud-wallet.service.ts @@ -175,8 +175,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/connection/src/connection.repository.ts b/apps/connection/src/connection.repository.ts index ec43c8385..a5aeb174e 100644 --- a/apps/connection/src/connection.repository.ts +++ b/apps/connection/src/connection.repository.ts @@ -90,7 +90,6 @@ export class ConnectionRepository { } } - async getConnectionRecordsCount(orgId: string): Promise { try { const connectionRecordsCount = await this.prisma.connections.count({ @@ -105,7 +104,6 @@ export class ConnectionRepository { } } - /** * Description: Save connection details * @param connectionInvitation @@ -332,8 +330,10 @@ export class ConnectionRepository { .filter(Boolean); if (0 < referencedTables.length) { - let errorMessage = `Organization ID ${orgId} is referenced in the following table(s): ${referencedTables.join(', ')}`; - + let errorMessage = `Organization ID ${orgId} is referenced in the following table(s): ${referencedTables.join( + ', ' + )}`; + if (1 === referencedTables.length) { if (referencedTables.includes(`${PrismaTables.PRESENTATIONS}`)) { errorMessage += `, ${ResponseMessages.verification.error.removeVerificationData}`; @@ -343,34 +343,31 @@ export class ConnectionRepository { } else if (2 === referencedTables.length) { errorMessage += `, ${ResponseMessages.connection.error.removeConnectionReferences}`; } - + throw new ConflictException(errorMessage); } - - const getConnectionRecords = await prisma.connections.findMany( - { - where: { - orgId - }, - select: { - createDateTime: true, - createdBy: true, - connectionId: true, - theirLabel: true, - state: true, - orgId: true - } - }); + const getConnectionRecords = await prisma.connections.findMany({ + where: { + orgId + }, + select: { + createDateTime: true, + createdBy: true, + connectionId: true, + theirLabel: true, + state: true, + orgId: true + } + }); - const deleteConnectionRecords = await prisma.connections.deleteMany( - { - where: { - orgId - } - }); + const deleteConnectionRecords = await prisma.connections.deleteMany({ + where: { + orgId + } + }); - return {getConnectionRecords, deleteConnectionRecords }; + return { getConnectionRecords, deleteConnectionRecords }; }); } catch (error) { this.logger.error(`Error in deleting connection records: ${error.message}`); @@ -378,10 +375,10 @@ export class ConnectionRepository { } } - // eslint-disable-next-line camelcase - async getInvitationDidByOrgId(orgId: string): Promise { + // eslint-disable-next-line camelcase + async getInvitationDidByOrgId(orgId: string): Promise { try { - return this.prisma.agent_invitations.findMany({ + return this.prisma.agent_invitations.findFirst({ where: { orgId }, diff --git a/apps/connection/src/connection.service.ts b/apps/connection/src/connection.service.ts index ad162c96b..4c8636de5 100644 --- a/apps/connection/src/connection.service.ts +++ b/apps/connection/src/connection.service.ts @@ -527,17 +527,13 @@ export class ConnectionService { throw new NotFoundException(ResponseMessages.connection.error.agentEndPointNotFound); } - let legacyinvitationDid; + let legacyInvitationDid; if (IsReuseConnection) { - const data: agent_invitations[] = await this.connectionRepository.getInvitationDidByOrgId(orgId); - if (data && 0 < data.length) { - const [firstElement] = data; - legacyinvitationDid = firstElement?.invitationDid ?? undefined; - - this.logger.log('legacyinvitationDid:', legacyinvitationDid); - } + const data: agent_invitations = await this.connectionRepository.getInvitationDidByOrgId(orgId); + legacyInvitationDid = data.invitationDid ?? undefined; + this.logger.log('legacyInvitationDid:', legacyInvitationDid); } - const connectionInvitationDid = invitationDid ? invitationDid : legacyinvitationDid; + const connectionInvitationDid = invitationDid ? invitationDid : legacyInvitationDid; this.logger.log('connectionInvitationDid:', connectionInvitationDid); diff --git a/apps/issuance/src/issuance.module.ts b/apps/issuance/src/issuance.module.ts index 84886a913..9be0beedb 100644 --- a/apps/issuance/src/issuance.module.ts +++ b/apps/issuance/src/issuance.module.ts @@ -13,7 +13,7 @@ import { BullModule } from '@nestjs/bull'; import { CacheModule } from '@nestjs/cache-manager'; import * as redisStore from 'cache-manager-redis-store'; 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'; @@ -58,7 +58,7 @@ import { NATSClient } from '@credebl/common/NATSClient'; OutOfBandIssuance, EmailDto, BulkIssuanceProcessor, - AwsService, + StorageService, NATSClient, { provide: MICRO_SERVICE_NAME, diff --git a/apps/issuance/src/issuance.repository.ts b/apps/issuance/src/issuance.repository.ts index 8fa95635a..fbe5fedcb 100644 --- a/apps/issuance/src/issuance.repository.ts +++ b/apps/issuance/src/issuance.repository.ts @@ -727,7 +727,9 @@ export class IssuanceRepository { .filter(Boolean); if (0 < referencedTables.length) { - let errorMessage = `Organization ID ${orgId} is referenced in the following table(s): ${referencedTables.join(', ')}`; + let errorMessage = `Organization ID ${orgId} is referenced in the following table(s): ${referencedTables.join( + ', ' + )}`; if (1 === referencedTables.length) { if (referencedTables.includes(`${PrismaTables.PRESENTATIONS}`)) { diff --git a/apps/issuance/src/issuance.service.ts b/apps/issuance/src/issuance.service.ts index d785ae1cb..1e82111ec 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 { @@ -105,7 +105,7 @@ 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, @Inject(CACHE_MANAGER) private readonly cacheService: Cache, @Inject(ContextStorageServiceKey) @@ -486,7 +486,9 @@ export class IssuanceService { return message.response; } catch (error) { this.logger.error( - `[storeIssuanceObjectReturnUrl] [NATS call]- error in storing object and returning url : ${JSON.stringify(error)}` + `[storeIssuanceObjectReturnUrl] [NATS call]- error in storing object and returning url : ${JSON.stringify( + error + )}` ); throw error; } @@ -1257,9 +1259,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/ledger/src/schema/enum/schema.enum.ts b/apps/ledger/src/schema/enum/schema.enum.ts index 1a307a646..478d6133d 100644 --- a/apps/ledger/src/schema/enum/schema.enum.ts +++ b/apps/ledger/src/schema/enum/schema.enum.ts @@ -1,15 +1,13 @@ - - export enum SortFields { - ID = 'id', - CREATED_DATE_TIME = 'createDateTime', - NAME = 'name', - VERSION = 'version', - LEDGER_ID = 'schemaLedgerId', - PUBLISHER_DID = 'publisherDid', - ISSUER_ID = 'issuerId' + ID = 'id', + CREATED_DATE_TIME = 'createDateTime', + NAME = 'name', + VERSION = 'version', + LEDGER_ID = 'schemaLedgerId', + PUBLISHER_DID = 'publisherDid', + ISSUER_ID = 'issuerId' } export enum W3CSchemaVersion { - W3C_SCHEMA_VERSION = 'draft/2020-12' + W3C_SCHEMA_VERSION = 'draft/2020-12' } diff --git a/apps/ledger/src/schema/interfaces/schema-payload.interface.ts b/apps/ledger/src/schema/interfaces/schema-payload.interface.ts index db8d09192..9e7058d9c 100644 --- a/apps/ledger/src/schema/interfaces/schema-payload.interface.ts +++ b/apps/ledger/src/schema/interfaces/schema-payload.interface.ts @@ -2,139 +2,137 @@ import { SchemaType, SortValue } from '@credebl/enum/enum'; import { IUserRequestInterface } from './schema.interface'; export interface ISchema { - schema?: ISchemaPayload; - user?: IUserRequestInterface; - createdBy?: string; - issuerId?: string; - changedBy?: string; - ledgerId?: string; - orgId?: string; - onLedgerStatus?: string; - credDefSortBy?: string; - supportRevocation?: string; - schemaId?: string; - createTransactionForEndorser?: boolean; - transactionId?: string; - endorserWriteTxn?: string; - orgDid?: string; - type?: string; - alias?: string; + schema?: ISchemaPayload; + user?: IUserRequestInterface; + createdBy?: string; + issuerId?: string; + changedBy?: string; + ledgerId?: string; + orgId?: string; + onLedgerStatus?: string; + credDefSortBy?: string; + supportRevocation?: string; + schemaId?: string; + createTransactionForEndorser?: boolean; + transactionId?: string; + endorserWriteTxn?: string; + orgDid?: string; + type?: string; + alias?: string; } export interface IAttributeValue { - isRequired: boolean; - attributeName: string; - schemaDataType: string; - displayName: string; - + isRequired: boolean; + attributeName: string; + schemaDataType: string; + displayName: string; } export interface ISchemaPayload { - schemaVersion: string; - schemaName: string; - orgDid?: string; - attributes: IAttributeValue[]; - issuerId?: string; - onLedgerStatus?: string; - id?: string; - user?: IUserRequestInterface; - page?: number; - searchText?: string - itemsPerPage?: number; - sortValue?: SortValue; - schemaSortBy?: string; + schemaVersion: string; + schemaName: string; + orgDid?: string; + attributes: IAttributeValue[]; + issuerId?: string; + onLedgerStatus?: string; + id?: string; + user?: IUserRequestInterface; + page?: number; + searchText?: string; + itemsPerPage?: number; + sortValue?: SortValue; + schemaSortBy?: string; } export interface ISchemaSearchPayload { - schemaSearchCriteria: ISchemaSearchCriteria, - user: IUserRequestInterface, - orgId: string + schemaSearchCriteria: ISchemaSearchCriteria; + user: IUserRequestInterface; + orgId: string; } export interface ISchemaSearchCriteria { - ledgerId?: string; - pageNumber: number; - pageSize: number; - sortField: string; - sortBy: string; - searchByText?: string; - schemaType?: SchemaType; - user?: IUserRequestInterface - schemaId?: string; - orgId?: string; + ledgerId?: string; + pageNumber: number; + pageSize: number; + sortField: string; + sortBy: string; + searchByText?: string; + schemaType?: SchemaType; + user?: IUserRequestInterface; + schemaId?: string; + orgId?: string; } export interface ISchemaCredDeffSearchInterface { - schemaId: string; - schemaSearchCriteria?: ISchemaSearchCriteria, - user: IUserRequestInterface, + schemaId: string; + schemaSearchCriteria?: ISchemaSearchCriteria; + user: IUserRequestInterface; } export interface ISchemaExist { - schemaName: string; - version: string; + schemaName: string; + version: string; } export interface SchemaPayload { - schemaAttributes: W3CSchemaAttributes [], - schemaName: string, - did: string, - description: string - jsonSchemaType?: string - } + schemaAttributes: W3CSchemaAttributes[]; + schemaName: string; + did: string; + description: string; + jsonSchemaType?: string; +} - export interface W3CSchemaAttributes { - type: string, - title: string, - } - - export interface ISchemaAttributesFormat extends W3CSchemaAttributes{ - order: number, - description: string; - exclusiveMinimum?: number; - multipleOf?: number; - pattern?: string; - minLength?: number; - maxLength?: number; - items?: object[] | string [] | number []; - properties?: object; - format?: string; - minItems?: number; - maxItems?: number; - uniqueItems?: boolean; - } +export interface W3CSchemaAttributes { + type: string; + title: string; +} + +export interface ISchemaAttributesFormat extends W3CSchemaAttributes { + order: number; + description: string; + exclusiveMinimum?: number; + multipleOf?: number; + pattern?: string; + minLength?: number; + maxLength?: number; + items?: object[] | string[] | number[]; + properties?: object; + format?: string; + minItems?: number; + maxItems?: number; + uniqueItems?: boolean; +} export interface W3CSchemaPayload { - schemaPayload: SchemaPayload, - orgId: string, - user: string - } + schemaPayload: SchemaPayload; + orgId: string; + user: string; +} export interface W3CCreateSchema { - url: string, - orgId: string, - schemaRequestPayload: object -} + url: string; + orgId: string; + schemaRequestPayload: object; +} export interface IdAttribute extends W3CSchemaAttributes { - format: string; - order?: string -} - + format: string; + order?: string; +} export interface ISaveSchema { - name: string; - version: string; - attributes: string; - schemaLedgerId: string; - issuerId: string; - createdBy: string; - lastChangedBy: string; - publisherDid: string; - orgId: string; - ledgerId: string; - type?: string; + name: string; + version: string; + attributes: string; + schemaLedgerId: string; + issuerId: string; + createdBy: string; + lastChangedBy: string; + publisherDid: string; + orgId: string; + ledgerId: string; + type?: string; } export interface SaveSchemaPayload { - schemaDetails: ISaveSchema -} \ No newline at end of file + schemaDetails: ISaveSchema; +} diff --git a/apps/ledger/src/schema/repositories/schema.repository.ts b/apps/ledger/src/schema/repositories/schema.repository.ts index f21c0678d..22a97733c 100644 --- a/apps/ledger/src/schema/repositories/schema.repository.ts +++ b/apps/ledger/src/schema/repositories/schema.repository.ts @@ -5,7 +5,6 @@ import { ICredDefWithCount, IPlatformSchemasWithOrg } from '@credebl/common/inte import { ISaveSchema, ISchema, ISchemaExist, ISchemaSearchCriteria } from '../interfaces/schema-payload.interface'; import { Prisma, ledgers, org_agents, org_agents_type, organisation, schema } from '@prisma/client'; import { SchemaType, SortValue } from '@credebl/enum/enum'; - import { ISchemaId } from '../schema.interface'; import { PrismaService } from '@credebl/prisma-service'; import { ResponseMessages } from '@credebl/common/response-messages'; diff --git a/apps/organization/src/organization.module.ts b/apps/organization/src/organization.module.ts index 37ad1c270..5f92e6a8e 100644 --- a/apps/organization/src/organization.module.ts +++ b/apps/organization/src/organization.module.ts @@ -18,7 +18,7 @@ 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 +36,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 51b89b93c..d839863f8 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, @@ -64,11 +64,15 @@ import { DeleteOrgInvitationsEmail } from '../templates/delete-organization-invi import { IOrgRoles } from 'libs/org-roles/interfaces/org-roles.interface'; import { NATSClient } from '@credebl/common/NATSClient'; import { UserRepository } from 'apps/user/repositories/user.repository'; +import { CommonConstants } from '@credebl/common/common.constant'; import * as jwt from 'jsonwebtoken'; import { ClientTokenDto } from '../dtos/client-token.dto'; @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, @Inject(CACHE_MANAGER) private cacheService: Cache, @@ -134,7 +138,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 = ''; @@ -487,17 +491,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) { @@ -539,7 +543,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; @@ -1680,7 +1684,9 @@ export class OrganizationService { deletedOrgInvitationInfo.push(newInvitation); this.logger.log( - `email: ${userDetails.email}, orgName: ${organizationDetails?.name}, orgRoles: ${JSON.stringify(orgRoleNames)}, sendEmail: ${sendEmail}` + `email: ${userDetails.email}, orgName: ${organizationDetails?.name}, orgRoles: ${JSON.stringify( + orgRoleNames + )}, sendEmail: ${sendEmail}` ); }) ); 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..9a15aa34f 100644 --- a/apps/user/src/user.module.ts +++ b/apps/user/src/user.module.ts @@ -18,7 +18,6 @@ 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 { 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 +34,17 @@ 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, UserService, UserRepository, PrismaService, diff --git a/apps/user/src/user.service.ts b/apps/user/src/user.service.ts index 474dc6752..d7f9832bd 100644 --- a/apps/user/src/user.service.ts +++ b/apps/user/src/user.service.ts @@ -53,7 +53,6 @@ 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 +81,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..f2d0c24f9 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 { StorageModule } 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,13 @@ import { ContextInterceptorModule } from '@credebl/context/contextInterceptorMod ]), CommonModule, GlobalConfigModule, - LoggerModule, PlatformConfig, ContextInterceptorModule, - CacheModule.register() + LoggerModule, + PlatformConfig, + ContextInterceptorModule, + CacheModule.register(), + StorageModule ], controllers: [UtilitiesController], - providers: [UtilitiesService, Logger, PrismaService, UtilitiesRepository, AwsService] + providers: [UtilitiesService, Logger, PrismaService, UtilitiesRepository] }) -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/common/src/common.constant.ts b/libs/common/src/common.constant.ts index 02c6efd05..b5deee6b1 100644 --- a/libs/common/src/common.constant.ts +++ b/libs/common/src/common.constant.ts @@ -108,6 +108,7 @@ export enum CommonConstants { URL_SERVER_STATUS = '/status', URL_AGENT_WRITE_DID = '/dids/write', URL_AGENT_GET_DID = '/dids', + // agent status URL_AGENT_GET_ENDPOINT = '/agent', // sign data from agent @@ -150,7 +151,6 @@ export enum CommonConstants { // (Platform) admin permissions PERMISSION_TENANT_MGMT = 'Tenant Management', - PERMISSION_ROLE_MGMT = 'Role Management', PERMISSION_ORG_REPORTS = 'Organization Reports', PERMISSION_TENANT_REPORTS = 'Tenant Reports', @@ -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/storage/package.json b/libs/storage/package.json new file mode 100644 index 000000000..0583ff5fb --- /dev/null +++ b/libs/storage/package.json @@ -0,0 +1,27 @@ +{ + "name": "@credebl/storage", + "main": "src/index", + "types": "src/index", + "version": "0.0.1", + "files": [ + "dist" + ], + "scripts": { + "build": "pnpm run clean && pnpm run compile", + "clean": "rimraf ../../dist/libs/storage", + "compile": "tsc -p tsconfig.build.json", + "test": "jest" + }, + "dependencies": { + "@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", + "rimraf": "^4.4.0", + "typescript": "^5.1.6" + } +} 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/providers/minio.provider.ts b/libs/storage/src/providers/minio.provider.ts new file mode 100644 index 000000000..42f86b446 --- /dev/null +++ b/libs/storage/src/providers/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/providers/s3.provider.ts b/libs/storage/src/providers/s3.provider.ts new file mode 100644 index 000000000..e5ac49bb4 --- /dev/null +++ b/libs/storage/src/providers/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/storage/tsconfig.json b/libs/storage/tsconfig.json new file mode 100644 index 000000000..b29a7b46c --- /dev/null +++ b/libs/storage/tsconfig.json @@ -0,0 +1,4 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": {} +} diff --git a/libs/validations/exclusiveMaximum.ts b/libs/validations/exclusiveMaximum.ts index bc717ff9d..f9772cd00 100644 --- a/libs/validations/exclusiveMaximum.ts +++ b/libs/validations/exclusiveMaximum.ts @@ -1,7 +1,7 @@ import NumberKeyword from './numberKeyword'; export default class ExclusiveMaximum extends NumberKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class ExclusiveMaximum extends NumberKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if ('number' === typeof value) { - this._value = value; - } else { - throw new Error('value must be a number'); - } + this._value = value; + } else { + throw new Error('value must be a number'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/exclusiveMinimum.ts b/libs/validations/exclusiveMinimum.ts index 653c1d1b9..bc0e997bb 100644 --- a/libs/validations/exclusiveMinimum.ts +++ b/libs/validations/exclusiveMinimum.ts @@ -1,7 +1,7 @@ import NumberKeyword from './numberKeyword'; export default class ExclusiveMinimum extends NumberKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class ExclusiveMinimum extends NumberKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if ('number' === typeof value) { - this._value = value; - } else { - throw new Error('value must be a number'); - } + this._value = value; + } else { + throw new Error('value must be a number'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/keyword.ts b/libs/validations/keyword.ts index dc57e4b4c..506a392ba 100644 --- a/libs/validations/keyword.ts +++ b/libs/validations/keyword.ts @@ -1,7 +1,6 @@ export default class Keyword { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - json(context): any { - return context || {}; - } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + json(context): any { + return context || {}; } - \ No newline at end of file +} diff --git a/libs/validations/maxItems.ts b/libs/validations/maxItems.ts index 7329cdd5a..c21b1f421 100644 --- a/libs/validations/maxItems.ts +++ b/libs/validations/maxItems.ts @@ -1,7 +1,7 @@ import ArrayKeyword from './arrayKeyword'; export default class MaxItems extends ArrayKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class MaxItems extends ArrayKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if (0 <= value && Number.isInteger(value)) { - this._value = value; - } else { - throw new Error('value must be an integer and greater than or equal to 0'); - } + this._value = value; + } else { + throw new Error('value must be an integer and greater than or equal to 0'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/maxLength.ts b/libs/validations/maxLength.ts index b935afb60..85f85c422 100644 --- a/libs/validations/maxLength.ts +++ b/libs/validations/maxLength.ts @@ -1,22 +1,21 @@ import StringKeyword from './stringKeyword'; export default class MaxLength extends StringKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); this.value = value; } get value(): number { - return this._value; + return this._value; } set value(value: number) { - if (0 <= value && Number.isInteger(value)) { - this._value = value; + this._value = value; } else { - throw new Error('value must be an integer and greater than or equal to 0'); + throw new Error('value must be an integer and greater than or equal to 0'); } } diff --git a/libs/validations/maximum.ts b/libs/validations/maximum.ts index c871228d2..846b75034 100644 --- a/libs/validations/maximum.ts +++ b/libs/validations/maximum.ts @@ -1,7 +1,7 @@ import NumberKeyword from './numberKeyword'; export default class Maximum extends NumberKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class Maximum extends NumberKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if ('number' === typeof value) { - this._value = value; - } else { - throw new Error('value must be a number'); - } + this._value = value; + } else { + throw new Error('value must be a number'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/minItems.ts b/libs/validations/minItems.ts index 98d4c57bb..67e7ce18e 100644 --- a/libs/validations/minItems.ts +++ b/libs/validations/minItems.ts @@ -1,7 +1,7 @@ import ArrayKeyword from './arrayKeyword'; export default class MinItems extends ArrayKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class MinItems extends ArrayKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if (0 <= value && Number.isInteger(value)) { - this._value = value; - } else { - throw new Error('value must be an integer and greater than or equal to 0'); - } + this._value = value; + } else { + throw new Error('value must be an integer and greater than or equal to 0'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/minLength.ts b/libs/validations/minLength.ts index 2d97bcda2..f7fefacac 100644 --- a/libs/validations/minLength.ts +++ b/libs/validations/minLength.ts @@ -1,7 +1,7 @@ import StringKeyword from './stringKeyword'; export default class MinLength extends StringKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,7 +9,7 @@ export default class MinLength extends StringKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { diff --git a/libs/validations/minimum.ts b/libs/validations/minimum.ts index 05b70ff2a..e36ad23f9 100644 --- a/libs/validations/minimum.ts +++ b/libs/validations/minimum.ts @@ -1,7 +1,7 @@ import NumberKeyword from './numberKeyword'; export default class Minimum extends NumberKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class Minimum extends NumberKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if ('number' === typeof value) { - this._value = value; - } else { - throw new Error('value must be a number'); - } + this._value = value; + } else { + throw new Error('value must be a number'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/multipleOf.ts b/libs/validations/multipleOf.ts index bead8736b..0c0f70442 100644 --- a/libs/validations/multipleOf.ts +++ b/libs/validations/multipleOf.ts @@ -1,7 +1,7 @@ import NumberKeyword from './numberKeyword'; export default class MultipleOf extends NumberKeyword { - private _value: number; + private _value: number; constructor(value: number) { super(); @@ -9,15 +9,15 @@ export default class MultipleOf extends NumberKeyword { } get value(): number { - return this._value; + return this._value; } set value(value: number) { if ('number' === typeof value && 0 < value) { - this._value = value; - } else { - throw new Error('value must be a number greater than 0'); - } + this._value = value; + } else { + throw new Error('value must be a number greater than 0'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/pattern.ts b/libs/validations/pattern.ts index 556a1e535..c4f64419f 100644 --- a/libs/validations/pattern.ts +++ b/libs/validations/pattern.ts @@ -1,7 +1,7 @@ import StringKeyword from './stringKeyword'; export default class Pattern extends StringKeyword { - private _value: string; + private _value: string; constructor(value: string) { super(); @@ -9,20 +9,20 @@ export default class Pattern extends StringKeyword { } get value(): string { - return this._value; + return this._value; } set value(value: string) { if ('string' === typeof value) { - try { - new RegExp(value); - this._value = value; - } catch (e) { - throw new Error('value must be a valid regular expression pattern'); - } - } else { - throw new Error('value must be a string'); + try { + new RegExp(value); + this._value = value; + } catch (e) { + throw new Error('value must be a valid regular expression pattern'); } + } else { + throw new Error('value must be a string'); + } } // eslint-disable-next-line @typescript-eslint/no-explicit-any diff --git a/libs/validations/stringKeyword.ts b/libs/validations/stringKeyword.ts index 0c5fd217f..788e76d87 100644 --- a/libs/validations/stringKeyword.ts +++ b/libs/validations/stringKeyword.ts @@ -1,3 +1,3 @@ import Keyword from './keyword'; -export default class StringKeyword extends Keyword {} \ No newline at end of file +export default class StringKeyword extends Keyword {} diff --git a/package.json b/package.json index 5d3de0b85..47b512a10 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/*" ] } },