public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var client = storageAccount.CreateCloudTableClient(); string partitionKey = await Authenticator.Authenticate(client, req); if (string.IsNullOrEmpty(partitionKey)) { return(new UnauthorizedResult()); } string json = await req.ReadAsStringAsync(); var items = JsonConvert.DeserializeObject <List <ItemJson> >(json); if (items == null) { return(new BadRequestObjectResult("Could not correctly parse the request parameters")); } else if (items.Count > 100) { return(new BadRequestObjectResult("Too many items to store, maximum 100 per call")); } else if (items.Count <= 0) { return(new BadRequestObjectResult("No items to store")); } var partition = await PartionUtility.GetUploadPartitionV2(log, client, partitionKey); log.Info($"Received a request from {partitionKey} to upload {items.Count} items to {partition.RowKey}"); var itemTable = client.GetTableReference(ItemV2.TableName); await itemTable.CreateIfNotExistsAsync(); var itemMapping = await Insert(partitionKey, partition.RowKey, itemTable, items); log.Info($"Inserted {items.Count} items over {itemMapping.Count} batches"); bool shouldClosePartition = items.Count >= 90; if (shouldClosePartition) { log.Info($"Closing partition {partition.PartitionKey}, due to received count at {items.Count}"); partition.IsActive = false; await client.GetTableReference(PartitionV2.TableName).ExecuteAsync(TableOperation.Replace(partition)); } var result = new UploadResultDto { Partition = itemMapping.First().Partition, IsClosed = shouldClosePartition, Items = itemMapping }; return(new OkObjectResult(result)); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var client = storageAccount.CreateCloudTableClient(); string partitionKey = await Authenticator.Authenticate(client, req); if (string.IsNullOrEmpty(partitionKey)) { return(new UnauthorizedResult()); } string json = await req.ReadAsStringAsync(); var data = JsonConvert.DeserializeObject <List <ItemToRemove> >(json); if (data == null) { return(new BadRequestObjectResult("Could not correctly parse the request parameters")); } else if (data?.Count <= 0) { return(new BadRequestObjectResult("No items to delete")); } log.Info($"Received a request from {partitionKey} to remove {data.Count} items"); var itemTable = client.GetTableReference(ItemV1.TableName); DeleteByPartition(partitionKey, itemTable, data, log); var partition = await PartionUtility.GetUploadPartition(log, client, partitionKey); var deletedItemsTable = client.GetTableReference(DeletedItemV1.TableName); DeleteInActivePartition(partition.RowKey, deletedItemsTable, data); log.Info($"Marked {data.Count} items as deleted in the active partition {partition.RowKey}"); return(new OkResult()); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var client = storageAccount.CreateCloudTableClient(); string partitionKey = await Authenticator.Authenticate(client, req); if (string.IsNullOrEmpty(partitionKey)) { return(new UnauthorizedResult()); } string json = await req.ReadAsStringAsync(); var items = JsonConvert.DeserializeObject <List <ItemJsonV3> >(json); if (items == null) { return(new BadRequestObjectResult("Could not correctly parse the request parameters")); } else if (items.Count > 100) { return(new BadRequestObjectResult("Too many items to store, maximum 100 per call")); } else if (items.Count <= 0) { return(new BadRequestObjectResult("No items to store")); } else if (items.Select(item => item.RemotePartition).Distinct().Count() > 1) { return(new BadRequestObjectResult("Cannot store items from multiple partitions in a single call")); } // Just ensuring that a partition entry exists, so that we can find it again later. var partition = await PartionUtility.GetUploadPartitionV3(log, client, partitionKey, items.First().RemotePartition); log.Info($"Received a request from {partitionKey} to upload {items.Count} items to {partition.RowKey}"); var itemTable = client.GetTableReference(ItemV2.TableName); await itemTable.CreateIfNotExistsAsync(); var itemMapping = await Insert(log, partition.RowKey, itemTable, items); log.Info($"Inserted {items.Count} items"); bool shouldClosePartition = items.Count >= 90; if (shouldClosePartition) { log.Info($"Closing partition {partition.PartitionKey}, due to received count at {items.Count}"); partition.IsActive = false; await client.GetTableReference(PartitionV2.TableName).ExecuteAsync(TableOperation.Replace(partition)); } var result = new UploadResultDto { Partition = partition.RowKey.Remove(0, partitionKey.Length), // Strip the owner email from the partition IsClosed = shouldClosePartition, }; return(new OkObjectResult(result)); }
public static async Task <IActionResult> Run( [HttpTrigger(AuthorizationLevel.Anonymous, "post")] HttpRequest req, [StorageAccount("StorageConnectionString")] CloudStorageAccount storageAccount, TraceWriter log ) { var client = storageAccount.CreateCloudTableClient(); string partitionKey = await Authenticator.Authenticate(client, req); if (string.IsNullOrEmpty(partitionKey)) { return(new UnauthorizedResult()); } var partitions = await PartionUtility.GetAllPartitions(log, client, partitionKey); log.Info($"Received a request from {partitionKey} to erase the account"); // Foreach partition: Delete all items var itemTable = client.GetTableReference(ItemV2.TableName); foreach (var partition in partitions) { var query = TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, partition.RowKey); var exQuery = new TableQuery <ItemV2>().Where(query); var items = await QueryHelper.ListAll(itemTable, exQuery); log.Info($"Deleting stored items in partition {partition.RowKey} for {partitionKey}"); BatchDelete(log, itemTable, partition.RowKey, items); } // Delete the 'removed items' entries foreach (var partition in partitions) { log.Info($"Deleting removed items in partition {partition.RowKey} for {partitionKey}"); DeleteDeletedItems(log, client, partition.RowKey); } // Delete the partition entries var partitionTable = client.GetTableReference(PartitionV2.TableName); foreach (var partition in partitions) { log.Info($"Deleting partition {partition.RowKey} for {partitionKey}"); await partitionTable.ExecuteAsync(TableOperation.Delete(partition)); } // Delete auth entry used for logins try { var table = client.GetTableReference(Authentication.TableName); await table.CreateIfNotExistsAsync(); var query = TableQuery.CombineFilters( TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, Authentication.PartitionName), TableOperators.And, TableQuery.GenerateFilterCondition("RowKey", QueryComparisons.Equal, req.Headers["Simple-Auth"]) ); var exQuery = new TableQuery <Authentication>().Where(query); var authenticationKeys = await QueryHelper.ListAll(table, exQuery); BatchDelete(log, table, Authentication.PartitionName, authenticationKeys); } catch (Exception ex) { log.Warning("Error deleting auth entry", ex.StackTrace); } return(new OkObjectResult("")); }