public async Task <IActionResult> Delete([FromQuery] string dataType, [FromQuery] string id) { // Validate if (string.IsNullOrEmpty(dataType)) { return(BadRequest("Data type not specified")); } if (string.IsNullOrEmpty(id)) { return(BadRequest("ID not specified")); } IRdDataStorage rdDataStorage; try { rdDataStorage = await dataRouter.GetSourceSystemAsync(dataType); } catch (KeyNotFoundException e) { return(BadRequest(e.Message)); } // Check existance var metadata = await GetExistingMetadataAsync(rdDataStorage, dataType, id); if (metadata == null) // Object doesn't exist { return(Ok()); // SECURITY NOTE: Returning OK without authentication allows for brute-force scanning for valid IDs! } // Authorize var loggedInUsername = UsernameNormalizer.Normalize(HttpContext.User.Identity.Name); var overwritingAllowed = await authorizationModule.IsOverwritingAllowedForCollectionAsync(dataType); var resourceDescription = new DeleteDataResourceDescription(dataType, metadata.Submitter, overwritingAllowed); var authorizationResult = await authorizationModule.AuthorizeAsync(resourceDescription, loggedInUsername); if (!authorizationResult.IsAuthorized) { return(StatusCode((int)HttpStatusCode.Unauthorized, "Not authorized")); } // Delete if (await rdDataStorage.DeleteDataContainerAsync(dataType, id)) { await subscriptionManager.NotifyDataChangedAsync(dataType, id, DataModificationType.Deleted); apiEventLogger.Log(LogLevel.Warning, $"User '{authorizationResult.User.UserName}' has deleted data of type '{dataType}' with ID '{id}'"); return(Ok()); } return(NotFound()); }
public async Task <IActionResult> DeleteMany([FromQuery] string dataType, [FromQuery] string whereArguments) { // Validate if (string.IsNullOrWhiteSpace(dataType)) { return(BadRequest("Data type not specified")); } IRdDataStorage rdDataStorage; try { rdDataStorage = await dataRouter.GetSourceSystemAsync(dataType); } catch (KeyNotFoundException e) { return(BadRequest(e.Message)); } var loggedInUsername = UsernameNormalizer.Normalize(HttpContext.User.Identity.Name); var overwritingAllowed = await authorizationModule.IsOverwritingAllowedForCollectionAsync(dataType); // Check existance var query = $"SELECT _id, Submitter FROM {dataType} WHERE {whereArguments}"; var searchResult = rdDataStorage.SearchAsync(DataApiSqlQueryParser.Parse(query)); var deleteResults = new List <DeleteResult>(); await foreach (var doc in searchResult) { var submitter = doc["Submitter"].AsString; var id = doc["_id"].AsString; // Authorize var resourceDescription = new DeleteDataResourceDescription(dataType, submitter, overwritingAllowed); var authorizationResult = await authorizationModule.AuthorizeAsync(resourceDescription, loggedInUsername); if (!authorizationResult.IsAuthorized) { deleteResults.Add(DeleteResult.Failed(dataType, id, "Not authorized")); continue; } // Delete if (await rdDataStorage.DeleteDataContainerAsync(dataType, id)) { await subscriptionManager.NotifyDataChangedAsync(dataType, id, DataModificationType.Deleted); deleteResults.Add(DeleteResult.Success(dataType, id)); } else { deleteResults.Add(DeleteResult.Failed(dataType, id, "Not found")); } } apiEventLogger.Log(LogLevel.Warning, $"User '{loggedInUsername}' has deleted data of type '{dataType}' with matching '{whereArguments}'"); return(new ContentResult { ContentType = Conventions.JsonContentType, Content = JsonConvert.SerializeObject(deleteResults), StatusCode = (int)HttpStatusCode.OK }); }