Temporary repo to track my changes on LTS functions app porting
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

229 lines
8.9 KiB

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.Cosmos;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net;
using FromBodyAttribute = Microsoft.Azure.Functions.Worker.Http.FromBodyAttribute;
namespace CDP
{
public class FileRevision
{
private readonly ILogger<FileRevision> _logger;
private static Lazy<CosmosClient> lazyClient = new Lazy<CosmosClient>(InitializeCosmosClient);
private static CosmosClient cosmosClient => lazyClient.Value;
private static string DatabaseName = "CDP";
private static string ContainerName = "RevisionsContainer";
public FileRevision(ILogger<FileRevision> logger)
{
_logger = logger;
}
private static CosmosClient InitializeCosmosClient()
{
// Perform any initialization here
var uri = "https://cdplite.documents.azure.com:443/";
var authKey = "VPbg8RpzyI3XwhC2o0dIUtYFs33ghxORCqZeNAyg8vg4HWUBjM41BUxP0qLFXEvFh6ewQY1uKv52ACDbsEN1AQ==";
return new CosmosClient(uri, authKey);
}
public static async Task<RevisionEntry> GetFileRevisionInternal(string appKey, string fileId)
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
string id = Helpers.HashAndShortenText(appKey + fileId);
PartitionKey key = new PartitionKeyBuilder().Add(appKey).Add(fileId).Build();
var item = await container.ReadItemAsync<RevisionEntry>(id, key);
return item.Resource;
}
static internal async Task<IActionResult> AddRevisionInternal(AddRevisionDocumentDto doc, ILogger _logger)
{
try
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
_logger.LogInformation("container id: ", container);
RevisionDocument document = new RevisionDocument()
{
//AppKey = doc.AppKey,
//FileId = doc.FileId,
RevisionId = doc.RevisionId,
EditedBy = doc.EditedBy,
Comments = doc.Comments,
RevisionDate = doc.RevisionDate
};
string id = Helpers.HashAndShortenText(doc.AppKey + doc.FileId);
PartitionKey partitionKey = new PartitionKeyBuilder()
.Add(doc.AppKey)
.Add(doc.FileId)
.Build();
var res = await AddOrUpdateRevision(container, id, partitionKey, document, doc.AppKey, doc.FileId);
return new OkObjectResult(res);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
return new StatusCodeResult(500);
}
}
public async static Task<string> AddMailBodyRevision(RevisionDocument document, CompoundDocument compoundDocument, string AppKey, string FileId)
{
Container container = cosmosClient.GetContainer(DatabaseName, ContainerName);
List<RevisionDocument> documents = new List<RevisionDocument> { document };
RevisionEntry entry = new RevisionEntry
{
AppKey = AppKey,
FileId = FileId,
FileRevisions = documents,
CompoundDocument = compoundDocument
};
ItemResponse<RevisionEntry> item = await container.CreateItemAsync<RevisionEntry>(entry);
return item.Resource.id;
}
private async static Task<RevisionEntry> AddOrUpdateRevision(Container container, string id, PartitionKey partitionKey, RevisionDocument document, string appKey, string fileId)
{
try
{
ItemResponse<RevisionEntry> item = await container.ReadItemAsync<RevisionEntry>(id, partitionKey);
RevisionEntry revisions = item.Resource;
revisions.FileRevisions.Add(document);
ItemRequestOptions requestOptions = new ItemRequestOptions
{
IfMatchEtag = item.ETag
};
var res = await container.UpsertItemAsync<RevisionEntry>(revisions, partitionKey);
return res.Resource;
}
catch (CosmosException ex)
{
if (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
{
List<RevisionDocument> revisions = new List<RevisionDocument>
{
document
};
RevisionEntry entry = new RevisionEntry()
{
AppKey = appKey,
FileId = fileId,
FileRevisions = revisions
};
ItemResponse<RevisionEntry> item = await container.CreateItemAsync<RevisionEntry>(entry);
return item.Resource;
}
else if (ex.StatusCode == HttpStatusCode.PreconditionFailed)
{
return await AddOrUpdateRevision(container, id, partitionKey, document, appKey, fileId);
}
else
{
throw ex;
}
}
}
#region Versioning Functions
[Function("AddRevisionDocument")]
public async Task<IActionResult> AddRevisionDocument([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req)
{
_logger.LogInformation("C# HTTP trigger function processed a request for update revision");
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
AddRevisionDocumentDto doc;
try
{
doc = JsonConvert.DeserializeObject<AddRevisionDocumentDto>(requestBody);
_logger.LogInformation(doc.RevisionId + doc.AppKey + doc.FileId);
}
catch (Exception ex)
{
_logger.LogError(ex.ToString());
return new BadRequestObjectResult("Invalid request format");
}
return await AddRevisionInternal(doc, _logger);
}
[Function("GetFileRevisions")]
public async Task<IActionResult> GetFileRevisions([HttpTrigger(AuthorizationLevel.Function, "get", "post")] HttpRequestData req, [FromBody] GetRevisionsDto reqDto)
{
_logger.LogInformation("C# HTTP trigger function processed a request for update revision", JsonConvert.SerializeObject(reqDto));
try
{
var item = await GetFileRevisionInternal(reqDto.AppKey, reqDto.FileId);
if (item.CompoundDocument != null)
{
return new OkObjectResult(item);
}
List<RevisionDocument> revisions = item.FileRevisions;
//_logger.LogInformation("docs: {0}", JsonConvert.SerializeObject(revisions));
return new OkObjectResult(revisions);
}
catch (CosmosException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
return new StatusCodeResult(404);
}
}
#endregion
}
public class GetRevisionsDto
{
public required string AppKey { get; set; }
public required string FileId { get; set; }
}
public class AddRevisionDocumentDto
{
public required string AppKey { get; set; }
public required string FileId { get; set; }
public required string RevisionId { get; set; }
public required string EditedBy { get; set; }
public required DateTime RevisionDate { get; set; }
public required string Comments { get; set; }
}
public class RevisionDocument
{
public required string RevisionId { get; set; }
public required string EditedBy { get; set; }
public required DateTime RevisionDate { get; set; }
public required string Comments { get; set; }
}
public class RevisionEntry
{
public string id
{
get
{
string s = Helpers.HashAndShortenText(AppKey + FileId);
return s.Replace('/', '-');
}
}
public required string AppKey { get; set; }
public required string FileId { get; set; }
public List<RevisionDocument> FileRevisions { get; set; }
public CompoundDocument? CompoundDocument { get; set; }
}
public class CompoundDocument
{
public required string Id { get; set; }
public required string AppKey { get; set; }
public required string Contents { get; set; } //can be MailRecord below
public required string DocumentType { get; set; }
}
}