using Microsoft.Azure.Cosmos; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace CDP { public class CDPDB { //https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections?tabs=csharp#azure-cosmos-db-clients private static Lazy lazyClient = new Lazy(InitializeCosmosClient); private static CosmosClient cosmosClient => lazyClient.Value; private static string DatabaseName = "CDP"; private static string FilesContainerName = "Files"; 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 AddFile(string appKey, string fileId, string userId, string aesKey, AccessPolicy ac) { Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container FileRecord fr = new FileRecord() { AppKey = appKey, FileId = fileId, UserId = userId, Policy = ac }; try { ItemResponse r = await container.CreateItemAsync(fr); // return r; } catch (Exception e) { return null; } } public static async Task UpsertFile(string appKey, string fileId, string fileName, string userId, string aesKey, AccessPolicy ac) { Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container FileRecord fr = new FileRecord() { AppKey = appKey, FileId = fileId, FileName = fileName, UserId = userId, Policy = ac }; try { ItemResponse r = await container.UpsertItemAsync(fr); // return r; } catch (Exception e) { return null; } } public static async Task GetFile(string appKey, string fileId, string userId) { Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container FileRecord dto = new FileRecord() { AppKey = appKey, FileId = fileId, UserId = userId, }; try { // Store the unique identifier string id = dto.id; // Build the full partition key path PartitionKey partitionKey = new PartitionKeyBuilder() .Add(appKey) .Add(fileId) .Add(userId) .Build(); // Perform a point read ItemResponse r = await container.ReadItemAsync(id, partitionKey); return r; } catch (Exception e) { return null; } } public static async Task revokePolicies(string appKey, string userEmail, string contactEmail) { Task> allFilesTask = GetAllOwnerFiles(appKey, userEmail.ToLower()); List allFiles = await allFilesTask; if (allFiles == null) { return; } foreach (FileRecord file in allFiles) { string fileId = file.FileId; string fileName = file.FileName; if (fileId == null) { continue; } string userId = Helpers.HashAndShortenText(contactEmail.ToLower()); AccessPolicy ac = new AccessPolicy() { Access = "None", Email = contactEmail.ToLower(), Group = null, GroupId = "", Key = "" }; string message = string.Format($"{contactEmail} contact deleted by {userEmail} and hence, access is revoked on file having id {fileId}"); string action = "Delete contact"; // await new CDPLite(null).AddAudits(appKey, fileId, userId, "", action, message); await UpsertFile(appKey, fileId, fileName, userId, "", ac); } } public static async Task revokeRegisteredUserPolicies(string appKey, string userEmail, string contactEmail, string registeredAdmin) { Task> allFiles = GetAllOwnerFiles(appKey, userEmail.ToLower()); foreach (FileRecord file in await allFiles) { string fileId = file.FileId; string fileName = file.FileName; if (fileId == null) { continue; } string userId = Helpers.HashAndShortenText(contactEmail.ToLower()); AccessPolicy ac = new AccessPolicy() { Access = "None", Email = contactEmail.ToLower(), Group = null, GroupId = "", Key = "" }; string message = string.Format($"{contactEmail} Registered User deleted by {registeredAdmin} and hence, access is revoked on all the Tenant files having id {fileId}"); string action = "Delete Registered User"; // await new CDPLite(null).AddAudits(appKey, fileId, userId, "", action, message); await UpsertFile(appKey, fileId, fileName, userId, "", ac); } } public static async Task> GetAllOwnerFiles(string appKey, string userId) { Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container var queryText = "SELECT * FROM c WHERE c.AppKey = @appKey AND c.Policy.Email = @userId AND c.Policy.Access = 'Owner'"; var queryDefinition = new QueryDefinition(queryText) .WithParameter("@appKey", appKey) .WithParameter("@userId", userId); var queryResultSetIterator = container.GetItemQueryIterator(queryDefinition); var results = new List(); while (queryResultSetIterator.HasMoreResults) { var response = await queryResultSetIterator.ReadNextAsync(); results.AddRange(response.ToList()); } return results; } public static async Task> GetPoliciesForFile(string appKey, string fileId) { Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container var queryText = "SELECT * FROM c WHERE c.AppKey = @appKey AND c.FileId = @fileId"; var queryDefinition = new QueryDefinition(queryText) .WithParameter("@appKey", appKey) .WithParameter("@fileId", fileId); var queryResultSetIterator = container.GetItemQueryIterator(queryDefinition); var results = new List(); while (queryResultSetIterator.HasMoreResults) { var response = await queryResultSetIterator.ReadNextAsync(); foreach (FileRecord fileRecord in response) { fileRecord.Policy.Key = "nunya"; } results.AddRange(response.ToList()); } return results; } } class AddFileDto { public string AppKey { get; set; } // the customer's AppKey public string Email { get; set; } // This is owner of the file...they will get a manage policy public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries) public string GroupId { get; set; } } class DeleteUserContactsDto { public string AppKey { get; set; } public string UserEmail { get; set; } public string ContactEmail { get; set; } } class DeleteRegisteredUserDto { public string AppKey { get; set; } public string UserEmail { get; set; } public string ContactEmail { get; set; } public string AdminEmail { get; set; } } class AddUserGroupDto { public string AppKey { get; set; } public string EmailId { get; set; } public string GroupName { get; set; } public string GroupDescription { get; set; } public List Contacts { get; set; } } class GetUserGroupDto { public string AppKey { get; set; } public string EmailId { get; set; } } class Contact { public string Name { get; set; } public string Email { get; set; } public string Company { get; set; } public string Phone { get; set; } public string Address { get; set; } } class AddUserContactsDto { public string AppKey { get; set; } public string EmailId { get; set; } public string ContactName { get; set; } public string ContactEmail { get; set; } public string ContactCompany { get; set; } public string ContactPhone { get; set; } public string ContactAddress { get; set; } } class GetContactsDto { public string Email { get; set; } public string AppKey { get; set; } } class AddFileUserDto { public string AppKey { get; set; } // the customer's AppKey public string FileId { get; set; } public string Email { get; set; } // email of user with power to add a user public string EmailToAdd { get; set; } public GroupsRecord Group { get; set; } public string GroupId { get; set; } public string Policy { get; set; } // Manage/Read/Write/etc... public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries) } class GetFileForUserDto { public string AppKey { get; set; } // the customer's AppKey public string FileId { get; set; } public string Email { get; set; } // email of user with power to add a user public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries) } class GetPoliciesForFileDto { public string AppKey { get; set; } // the customer's AppKey public string FileId { get; set; } } class GetFileDto { public string AppKey { get; set; } // the customer's AppKey public string FileId { get; set; } public string Email { get; set; } } class CreateSessionDto { public string AppKey { get; set; } // the customer's AppKey public string CallbackUrl { get; set; } public string Payload { get; set; } public string WebHookUrl { get; set; } } class GetAuditLogForFileDto { public string FileId { get; set; } } class GetAuditLogForUserDto { public string Email { get; set; } } class GetAuditLogForTenantDto { public string AppKey { get; set; } } class AddAccessViolationDto { public String FileId { get; set; } public string AppKey { get; set; } public string FileName { get; set; } } class GetAuditLogForGroupDto { public string GroupId { get; set; } } class GetTenantDto { public string AppKey { get; set; } // the customer's AppKey } class GetGroupDto { public string GroupId { get; set; } } class DeleteGroupDto { public string GroupId { get; set; } public string AppKey { get; set; } public string UserEmail { get; set; } } class UpdateGroupDto { public string AppKey { get; set; } public string UserEmail { get; set; } public string GroupId { get; set; } public string GroupName { get; set; } public string GroupDescription { get; set; } public List Contacts { get; set; } } class CreateClientQRCodeDto { public string SignalRConnectionId { get; set; } public string AppKey { get; set; } // the customer's AppKey public string Payload { get; set; } } class GetJwtsQRCode { public string SignalRConnectionId { get; set; } public List AppKeys { get; set; } } class ClientJwts { public List HashedEmails { get; set; } public List Jwts { get; set; } public ClientJwts() { HashedEmails = new List(); Jwts = new List(); } } public class FileRecord { public string id { get { string s = Helpers.HashAndShortenText(UserId + FileId); // Cosmos db doesn't like '/', '\', '?', '#' and base64 strings can have '/' return s.Replace('/', '-'); } } public string AppKey { get; set; } // the customer's AppKey public string FileId { get; set; } public string FileName { get; set; } public string UserId { get; set; } // This is owner of the file...they will get a manage policy public AccessPolicy Policy { get; set; } } public class AccessPolicy { public string Email { get; set; } // for sanity's sake. The end user will probably want this anyway. public GroupsRecord Group { get; set; } public string GroupId { get; set; } public string Access { get; set; } // Read Only, Manage, Print. CSV...opting for usability over a sexier bit flag. public string Key { get; set; } // encrypted with Constants.PublicKey public Boolean CheckAccess(string accessToCheck) { // Split the input string into an array of entries using commas as the separator string[] entries = Access.Split(','); // Iterate through the entries and check if any match the target string foreach (string entry in entries) { // Use StringComparison.OrdinalIgnoreCase for case-insensitive comparison if (entry.Trim().Equals(accessToCheck, StringComparison.OrdinalIgnoreCase)) { return true; // Found a match } } // No matching entry found return false; } } }