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.

427 lines
15 KiB

  1. using Microsoft.Azure.Cosmos;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace CDP
  8. {
  9. public class CDPDB
  10. {
  11. //https://learn.microsoft.com/en-us/azure/azure-functions/manage-connections?tabs=csharp#azure-cosmos-db-clients
  12. private static Lazy<CosmosClient> lazyClient = new Lazy<CosmosClient>(InitializeCosmosClient);
  13. private static CosmosClient cosmosClient => lazyClient.Value;
  14. private static string DatabaseName = "CDP";
  15. private static string FilesContainerName = "Files";
  16. private static CosmosClient InitializeCosmosClient()
  17. {
  18. // Perform any initialization here
  19. var uri = "https://cdplite.documents.azure.com:443/";
  20. var authKey = "VPbg8RpzyI3XwhC2o0dIUtYFs33ghxORCqZeNAyg8vg4HWUBjM41BUxP0qLFXEvFh6ewQY1uKv52ACDbsEN1AQ==";
  21. return new CosmosClient(uri, authKey);
  22. }
  23. public static async Task<FileRecord> AddFile(string appKey, string fileId, string userId, string aesKey, AccessPolicy ac)
  24. {
  25. Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container
  26. FileRecord fr = new FileRecord()
  27. {
  28. AppKey = appKey,
  29. FileId = fileId,
  30. UserId = userId,
  31. Policy = ac
  32. };
  33. try
  34. {
  35. ItemResponse<FileRecord> r = await container.CreateItemAsync(fr); //
  36. return r;
  37. }
  38. catch (Exception e)
  39. {
  40. return null;
  41. }
  42. }
  43. public static async Task<FileRecord> UpsertFile(string appKey, string fileId, string fileName, string userId, string aesKey, AccessPolicy ac)
  44. {
  45. Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container
  46. FileRecord fr = new FileRecord()
  47. {
  48. AppKey = appKey,
  49. FileId = fileId,
  50. FileName = fileName,
  51. UserId = userId,
  52. Policy = ac
  53. };
  54. try
  55. {
  56. ItemResponse<FileRecord> r = await container.UpsertItemAsync(fr); //
  57. return r;
  58. }
  59. catch (Exception e)
  60. {
  61. return null;
  62. }
  63. }
  64. public static async Task<FileRecord> GetFile(string appKey, string fileId, string userId)
  65. {
  66. Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container
  67. FileRecord dto = new FileRecord()
  68. {
  69. AppKey = appKey,
  70. FileId = fileId,
  71. UserId = userId,
  72. };
  73. try
  74. {
  75. // Store the unique identifier
  76. string id = dto.id;
  77. // Build the full partition key path
  78. PartitionKey partitionKey = new PartitionKeyBuilder()
  79. .Add(appKey)
  80. .Add(fileId)
  81. .Add(userId)
  82. .Build();
  83. // Perform a point read
  84. ItemResponse<FileRecord> r = await container.ReadItemAsync<FileRecord>(id, partitionKey);
  85. return r;
  86. }
  87. catch (Exception e)
  88. {
  89. return null;
  90. }
  91. }
  92. public static async Task revokePolicies(string appKey, string userEmail, string contactEmail)
  93. {
  94. Task<List<FileRecord>> allFilesTask = GetAllOwnerFiles(appKey, userEmail.ToLower());
  95. List<FileRecord> allFiles = await allFilesTask;
  96. if (allFiles == null)
  97. {
  98. return;
  99. }
  100. foreach (FileRecord file in allFiles)
  101. {
  102. string fileId = file.FileId;
  103. string fileName = file.FileName;
  104. if (fileId == null) { continue; }
  105. string userId = Helpers.HashAndShortenText(contactEmail.ToLower());
  106. AccessPolicy ac = new AccessPolicy()
  107. {
  108. Access = "None",
  109. Email = contactEmail.ToLower(),
  110. Group = null,
  111. GroupId = "",
  112. Key = ""
  113. };
  114. string message = string.Format($"{contactEmail} contact deleted by {userEmail} and hence, access is revoked on file having id {fileId}");
  115. string action = "Delete contact";
  116. // await new CDPLite(null).AddAudits(appKey, fileId, userId, "", action, message);
  117. await UpsertFile(appKey, fileId, fileName, userId, "", ac);
  118. }
  119. }
  120. public static async Task revokeRegisteredUserPolicies(string appKey, string userEmail, string contactEmail, string registeredAdmin)
  121. {
  122. Task<List<FileRecord>> allFiles = GetAllOwnerFiles(appKey, userEmail.ToLower());
  123. foreach (FileRecord file in await allFiles)
  124. {
  125. string fileId = file.FileId;
  126. string fileName = file.FileName;
  127. if (fileId == null)
  128. { continue; }
  129. string userId = Helpers.HashAndShortenText(contactEmail.ToLower());
  130. AccessPolicy ac = new AccessPolicy()
  131. {
  132. Access = "None",
  133. Email = contactEmail.ToLower(),
  134. Group = null,
  135. GroupId = "",
  136. Key = ""
  137. };
  138. string message = string.Format($"{contactEmail} Registered User deleted by {registeredAdmin} and hence, access is revoked on all the Tenant files having id {fileId}");
  139. string action = "Delete Registered User";
  140. // await new CDPLite(null).AddAudits(appKey, fileId, userId, "", action, message);
  141. await UpsertFile(appKey, fileId, fileName, userId, "", ac);
  142. }
  143. }
  144. public static async Task<List<FileRecord>> GetAllOwnerFiles(string appKey, string userId)
  145. {
  146. Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container
  147. var queryText = "SELECT * FROM c WHERE c.AppKey = @appKey AND c.Policy.Email = @userId AND c.Policy.Access = 'Owner'";
  148. var queryDefinition = new QueryDefinition(queryText)
  149. .WithParameter("@appKey", appKey)
  150. .WithParameter("@userId", userId);
  151. var queryResultSetIterator = container.GetItemQueryIterator<FileRecord>(queryDefinition);
  152. var results = new List<FileRecord>();
  153. while (queryResultSetIterator.HasMoreResults)
  154. {
  155. var response = await queryResultSetIterator.ReadNextAsync();
  156. results.AddRange(response.ToList());
  157. }
  158. return results;
  159. }
  160. public static async Task<List<FileRecord>> GetPoliciesForFile(string appKey, string fileId)
  161. {
  162. Container container = cosmosClient.GetContainer(DatabaseName, FilesContainerName); // get the Files Container
  163. var queryText = "SELECT * FROM c WHERE c.AppKey = @appKey AND c.FileId = @fileId";
  164. var queryDefinition = new QueryDefinition(queryText)
  165. .WithParameter("@appKey", appKey)
  166. .WithParameter("@fileId", fileId);
  167. var queryResultSetIterator = container.GetItemQueryIterator<FileRecord>(queryDefinition);
  168. var results = new List<FileRecord>();
  169. while (queryResultSetIterator.HasMoreResults)
  170. {
  171. var response = await queryResultSetIterator.ReadNextAsync();
  172. foreach (FileRecord fileRecord in response)
  173. {
  174. fileRecord.Policy.Key = "nunya";
  175. }
  176. results.AddRange(response.ToList());
  177. }
  178. return results;
  179. }
  180. }
  181. class AddFileDto
  182. {
  183. public string AppKey { get; set; } // the customer's AppKey
  184. public string Email { get; set; } // This is owner of the file...they will get a manage policy
  185. public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries)
  186. public string GroupId { get; set; }
  187. }
  188. class DeleteUserContactsDto
  189. {
  190. public string AppKey { get; set; }
  191. public string UserEmail { get; set; }
  192. public string ContactEmail { get; set; }
  193. }
  194. class DeleteRegisteredUserDto
  195. {
  196. public string AppKey { get; set; }
  197. public string UserEmail { get; set; }
  198. public string ContactEmail { get; set; }
  199. public string AdminEmail { get; set; }
  200. }
  201. class AddUserGroupDto
  202. {
  203. public string AppKey { get; set; }
  204. public string EmailId { get; set; }
  205. public string GroupName { get; set; }
  206. public string GroupDescription { get; set; }
  207. public List<Contact> Contacts { get; set; }
  208. }
  209. class GetUserGroupDto
  210. {
  211. public string AppKey { get; set; }
  212. public string EmailId { get; set; }
  213. }
  214. class Contact
  215. {
  216. public string Name { get; set; }
  217. public string Email { get; set; }
  218. public string Company { get; set; }
  219. public string Phone { get; set; }
  220. public string Address { get; set; }
  221. }
  222. class AddUserContactsDto
  223. {
  224. public string AppKey { get; set; }
  225. public string EmailId { get; set; }
  226. public string ContactName { get; set; }
  227. public string ContactEmail { get; set; }
  228. public string ContactCompany { get; set; }
  229. public string ContactPhone { get; set; }
  230. public string ContactAddress { get; set; }
  231. }
  232. class GetContactsDto
  233. {
  234. public string Email { get; set; }
  235. public string AppKey { get; set; }
  236. }
  237. class AddFileUserDto
  238. {
  239. public string AppKey { get; set; } // the customer's AppKey
  240. public string FileId { get; set; }
  241. public string Email { get; set; } // email of user with power to add a user
  242. public string EmailToAdd { get; set; }
  243. public GroupsRecord Group { get; set; }
  244. public string GroupId { get; set; }
  245. public string Policy { get; set; } // Manage/Read/Write/etc...
  246. public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries)
  247. }
  248. class GetFileForUserDto
  249. {
  250. public string AppKey { get; set; } // the customer's AppKey
  251. public string FileId { get; set; }
  252. public string Email { get; set; } // email of user with power to add a user
  253. public string FileName { get; set; } // user and group auditing is pretty worthless without this (less we do gobs of queries)
  254. }
  255. class GetPoliciesForFileDto
  256. {
  257. public string AppKey { get; set; } // the customer's AppKey
  258. public string FileId { get; set; }
  259. }
  260. class GetFileDto
  261. {
  262. public string AppKey { get; set; } // the customer's AppKey
  263. public string FileId { get; set; }
  264. public string Email { get; set; }
  265. }
  266. class CreateSessionDto
  267. {
  268. public string AppKey { get; set; } // the customer's AppKey
  269. public string CallbackUrl { get; set; }
  270. public string Payload { get; set; }
  271. public string WebHookUrl { get; set; }
  272. }
  273. class GetAuditLogForFileDto
  274. {
  275. public string FileId { get; set; }
  276. }
  277. class GetAuditLogForUserDto
  278. {
  279. public string Email { get; set; }
  280. }
  281. class GetAuditLogForTenantDto
  282. {
  283. public string AppKey { get; set; }
  284. }
  285. class AddAccessViolationDto
  286. {
  287. public String FileId { get; set; }
  288. public string AppKey { get; set; }
  289. public string FileName { get; set; }
  290. }
  291. class GetAuditLogForGroupDto
  292. {
  293. public string GroupId { get; set; }
  294. }
  295. class GetTenantDto
  296. {
  297. public string AppKey { get; set; } // the customer's AppKey
  298. }
  299. class GetGroupDto
  300. {
  301. public string GroupId { get; set; }
  302. }
  303. class DeleteGroupDto
  304. {
  305. public string GroupId { get; set; }
  306. public string AppKey { get; set; }
  307. public string UserEmail { get; set; }
  308. }
  309. class UpdateGroupDto
  310. {
  311. public string AppKey { get; set; }
  312. public string UserEmail { get; set; }
  313. public string GroupId { get; set; }
  314. public string GroupName { get; set; }
  315. public string GroupDescription { get; set; }
  316. public List<Contact> Contacts { get; set; }
  317. }
  318. class CreateClientQRCodeDto
  319. {
  320. public string SignalRConnectionId { get; set; }
  321. public string AppKey { get; set; } // the customer's AppKey
  322. public string Payload { get; set; }
  323. }
  324. class GetJwtsQRCode
  325. {
  326. public string SignalRConnectionId { get; set; }
  327. public List<string> AppKeys { get; set; }
  328. }
  329. class ClientJwts
  330. {
  331. public List<string> HashedEmails { get; set; }
  332. public List<string> Jwts { get; set; }
  333. public ClientJwts()
  334. {
  335. HashedEmails = new List<string>();
  336. Jwts = new List<string>();
  337. }
  338. }
  339. public class FileRecord
  340. {
  341. public string id
  342. {
  343. get
  344. {
  345. string s = Helpers.HashAndShortenText(UserId + FileId);
  346. // Cosmos db doesn't like '/', '\', '?', '#' and base64 strings can have '/'
  347. return s.Replace('/', '-');
  348. }
  349. }
  350. public string AppKey { get; set; } // the customer's AppKey
  351. public string FileId { get; set; }
  352. public string FileName { get; set; }
  353. public string UserId { get; set; } // This is owner of the file...they will get a manage policy
  354. public AccessPolicy Policy { get; set; }
  355. }
  356. public class AccessPolicy
  357. {
  358. public string Email { get; set; } // for sanity's sake. The end user will probably want this anyway.
  359. public GroupsRecord Group { get; set; }
  360. public string GroupId { get; set; }
  361. public string Access { get; set; } // Read Only, Manage, Print. CSV...opting for usability over a sexier bit flag.
  362. public string Key { get; set; } // encrypted with Constants.PublicKey
  363. public Boolean CheckAccess(string accessToCheck)
  364. {
  365. // Split the input string into an array of entries using commas as the separator
  366. string[] entries = Access.Split(',');
  367. // Iterate through the entries and check if any match the target string
  368. foreach (string entry in entries)
  369. {
  370. // Use StringComparison.OrdinalIgnoreCase for case-insensitive comparison
  371. if (entry.Trim().Equals(accessToCheck, StringComparison.OrdinalIgnoreCase))
  372. {
  373. return true; // Found a match
  374. }
  375. }
  376. // No matching entry found
  377. return false;
  378. }
  379. }
  380. }