// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT-0
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Threading.Tasks;
using Amazon;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.DataModel;
using Amazon.EventBridge;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Amazon.Util;
using AWS.Lambda.Powertools.Logging;
using AWS.Lambda.Powertools.Metrics;
using AWS.Lambda.Powertools.Tracing;
using DynamoDBContextConfig = Amazon.DynamoDBv2.DataModel.DynamoDBContextConfig;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
// [assembly: LambdaSerializer(typeof(Amazon.Lambda.Serialization.SystemTextJson.DefaultLambdaJsonSerializer))]
namespace Unicorn.Contracts.ContractService
{
public class UpdateContractFunction
{
private readonly IDynamoDBContext _dynamoDbContext;
///
/// Default constructor for CreateContractFunction
///
public UpdateContractFunction()
{
var dynamodbTable = Environment.GetEnvironmentVariable("DYNAMODB_TABLE");
if (string.IsNullOrEmpty(dynamodbTable))
{
throw new Exception("Environment variable DYNAMODB_TABLE is not defined.");
}
AWSConfigsDynamoDB.Context.TypeMappings[typeof(Contract)] =
new TypeMapping(typeof(Contract), dynamodbTable);
var config = new DynamoDBContextConfig { Conversion = DynamoDBEntryConversion.V2 };
_dynamoDbContext = new DynamoDBContext(new AmazonDynamoDBClient(), config);
}
///
///
///
///
///
///
public UpdateContractFunction(IDynamoDBContext dynamoDbContext, AmazonEventBridgeClient eventBridgeClient,
string serviceNamespace)
{
_dynamoDbContext = dynamoDbContext;
}
///
/// Lambda Handler for creating new Contracts.
///
/// API Gateway Lambda Proxy Request that triggers the function.
/// The context for the Lambda function.
/// API Gateway Lambda Proxy Response.
[Tracing]
[Metrics(CaptureColdStart = true)]
[Logging(LogEvent = true, CorrelationIdPath = CorrelationIdPaths.ApiGatewayRest)]
public async Task FunctionHandler(APIGatewayProxyRequest apigProxyEvent,
ILambdaContext context)
{
// Validate request body
var contractUpdateRequest = ValidateEvent(apigProxyEvent);
// check to see if contract exists
var existingContract = await GetExistingContract(contractUpdateRequest.PropertyId).ConfigureAwait(false);
if(existingContract == null)
throw new ContractNotFoundException($"Could not find property with ID: {contractUpdateRequest.PropertyId}");
// Update status
existingContract.ContractLastModifiedOn = DateTime.Now;
existingContract.ContractStatus = ContractStatus.Approved;
// Create entry in DDB for new contract
await UpdateContract(existingContract).ConfigureAwait(false);
// Publish ContractStatusChanged event
var publisher = new Publisher();
await publisher.PublishEvent(existingContract);
// return generated contract ID back to user:
return new APIGatewayProxyResponse
{
Body = JsonSerializer.Serialize(existingContract),
StatusCode = 200,
Headers = new Dictionary { { "Content-Type", "application/json" } }
};
}
///
/// Parse Contract defined in the APIGatewayProxyRequest body.
///
///
///
private UpdateContractRequest ValidateEvent(APIGatewayProxyRequest apigProxyEvent)
{
var options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true
};
try
{
var contract = JsonSerializer.Deserialize(apigProxyEvent.Body, options);
if (contract == null || string.IsNullOrEmpty(contract.PropertyId))
throw new EventValidationException("Unable to convert APIGatewayProxyRequest to Contract.");
return contract;
}
catch (Exception exception)
{
Console.WriteLine(exception);
throw new EventValidationException("Unable to convert APIGatewayProxyRequest to Contract.");
}
}
///
/// Returns Contract for a specified property.
///
/// Property ID
/// Instance of Contract
///
private async Task GetExistingContract(string? propertyId)
{
try
{
Console.WriteLine($"Getting contract {propertyId}");
var contract = await _dynamoDbContext.LoadAsync(propertyId).ConfigureAwait(false);
Console.WriteLine($"Found contact: {contract != null}");
return contract;
}
catch (Exception e)
{
Console.WriteLine($"Error loading contract {propertyId}: {e.Message}");
return null;
}
}
///
///
///
///
///
private async Task UpdateContract(Contract contract)
{
try
{
Console.WriteLine($"Saving contract with id {contract.PropertyId}");
await _dynamoDbContext.SaveAsync(contract).ConfigureAwait(false);
}
catch (AmazonDynamoDBException e)
{
Console.WriteLine(e);
throw;
}
}
}
}