private static HttpContent ConstructSubmitBodyFromObject(object obj, bool overwrite, string id) { var dataType = CollectionNameDeterminer.GetCollectionName(obj.GetType()); var submitDataBody = new SubmitDataBody(dataType, obj, overwrite, id); return(PostBodyBuilder.ConstructBody(submitDataBody)); }
private static HttpContent ConstructSubmitBodyFromJson(string dataType, string json, bool overwrite, string id) { var submitDataBody = new SubmitDataBody(dataType, null, overwrite, id); var submitBodyJsonObject = JObject.FromObject(submitDataBody); submitBodyJsonObject["Data"] = JObject.Parse(json); return(PostBodyBuilder.ConstructBodyFromJObject(submitBodyJsonObject)); }
public async Task SubmissionBodyIdIsUsed() { var rdDataStorage = new Mock <IRdDataStorage>(); var obj = new ClassWithoutId("Bob"); var submitBody = new SubmitDataBody(nameof(ClassWithoutId), obj, false, "SubmitBodyID"); submitBody = JsonConvert.DeserializeObject <SubmitDataBody>(JsonConvert.SerializeObject(submitBody)); var sut = new DefaultIdPolicy(); var actual = await sut.DetermineIdAsync(submitBody, Submitter, rdDataStorage.Object); Assert.That(actual.Id, Is.EqualTo(submitBody.Id)); rdDataStorage.Verify(x => x.GetIdsAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>()), Times.Never); }
public async Task IIdIdIsUsed() { var rdDataStorage = new Mock <IRdDataStorage>(); var obj = new Location("Hørsholm", "2.31.14"); var submitBody = new SubmitDataBody(nameof(Location), obj, false, "SubmitBodyID"); submitBody = JsonConvert.DeserializeObject <SubmitDataBody>(JsonConvert.SerializeObject(submitBody)); var sut = new DefaultIdPolicy(); var actual = await sut.DetermineIdAsync(submitBody, Submitter, rdDataStorage.Object); Assert.That(actual.Id, Is.EqualTo(obj.Id)); rdDataStorage.Verify(x => x.GetIdsAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>()), Times.Never); }
public async Task RdDataStorageIdIsUsed() { var rdDataStorageId = "RdDataStorageId"; var idReservationResult = IdReservationResult.Success(rdDataStorageId, false); var rdDataStorage = new Mock <IRdDataStorage>(); rdDataStorage.Setup(x => x.GetIdsAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>())).Returns(Task.FromResult(new List <IdReservationResult> { idReservationResult })); var obj = new ClassWithoutId("Bob"); var submitBody = new SubmitDataBody(nameof(ClassWithoutId), obj, false); // ! No ID provided ! submitBody = JsonConvert.DeserializeObject <SubmitDataBody>(JsonConvert.SerializeObject(submitBody)); var sut = new DefaultIdPolicy(); var actual = await sut.DetermineIdAsync(submitBody, Submitter, rdDataStorage.Object); Assert.That(actual.Id, Is.EqualTo(rdDataStorageId)); rdDataStorage.Verify(x => x.GetIdsAsync(It.IsAny <string>(), It.IsAny <string>(), It.IsAny <int>()), Times.Once); }
public async Task <SuggestedId> DetermineIdAsync(SubmitDataBody body, string submitter, IRdDataStorage rdDataStorage) { var dataType = body.Data.GetType(); string dataId; if (dataType == typeof(JObject)) { var jObject = (JObject)body.Data; dataId = jObject["Id"]?.Value <string>() ?? jObject["id"]?.Value <string>() ?? jObject["ID"]?.Value <string>() ?? jObject["_id"]?.Value <string>(); } else { var idProperty = dataType.GetProperty("Id") ?? dataType.GetProperty("id") ?? dataType.GetProperty("ID") ?? dataType.GetProperty("_id"); dataId = idProperty?.GetValue(body.Data) as string; } if (dataId != null) { return(new SuggestedId(dataId, false)); } if (body.Id != null) { return(new SuggestedId(body.Id, false)); } var idReservationResult = (await rdDataStorage.GetIdsAsync(body.DataType, submitter, 1)).Single(); if (!idReservationResult.IsReserved) { throw new Exception($"Could not determine a suitable ID for data type '{dataType}'"); } return(new SuggestedId(idReservationResult.Id, idReservationResult.IsReserved)); }
public async Task <IActionResult> CreateSubmission([FromBody] SubmitDataBody submitBody) { return(await Submit(submitBody)); }
public async Task <IActionResult> Submit([FromBody] SubmitDataBody body) { if (!NamingConventions.IsValidDataType(body.DataType)) { return(BadRequest($"Data type '{body.DataType}' is not a valid name for a collection")); } if (body.Data == null) { return(BadRequest("No data submitted")); } // Authorize var loggedInUsername = UsernameNormalizer.Normalize(HttpContext.User.Identity.Name); var resourceDescription = new SubmitDataResourceDescription(body.DataType); var authorizationResult = await authorizationModule.AuthorizeAsync(resourceDescription, loggedInUsername); if (!authorizationResult.IsAuthorized) { return(StatusCode((int)HttpStatusCode.Unauthorized, "Not authorized")); } IRdDataStorage rdDataStorage; try { rdDataStorage = await dataRouter.GetSourceSystemAsync(body.DataType); } catch (KeyNotFoundException) { return(BadRequest($"No data storage backend for data type '{body.DataType}'")); } // Validate var suggestedId = await idPolicy.DetermineIdAsync(body, loggedInUsername, rdDataStorage); if (!rdDataStorage.IsValidId(suggestedId.Id)) { return(BadRequest($"The ID '{suggestedId.Id}' for object of type '{body.DataType}' is not valid")); } if (body.Overwrite) { if (string.IsNullOrEmpty(suggestedId.Id)) { return(BadRequest("Overwriting of existing data is requested, but no ID is provided.")); } } var validators = await validatorManager.GetApprovedValidators(body.DataType); foreach (var validator in validators) { try { var validationResult = validator.Validate(body.Data.ToString()); if (!validationResult.IsValid) { return(new ContentResult { ContentType = Conventions.JsonContentType, Content = JsonConvert.SerializeObject(validationResult), StatusCode = (int)HttpStatusCode.BadRequest }); } } catch (Exception e) { apiEventLogger.Log(LogLevel.Error, e.ToString()); return(StatusCode((int)HttpStatusCode.InternalServerError, e.Message)); } } var existingData = await GetExistingMetadataAsync(rdDataStorage, body.DataType, suggestedId.Id); if (body.Overwrite) { if (!await IsAllowedToOverwriteDataAsync(body.DataType, existingData, authorizationResult.User)) { return(StatusCode((int)HttpStatusCode.Unauthorized, "Data from other users cannot be overwritten, unless you're an admin")); } } else if (existingData != null && !suggestedId.HasBeenReserved) { return(Conflict($"Document of type '{body.DataType}' with ID '{suggestedId.Id}' already exists")); } // Provide var apiVersion = ApiVersion.Current; var data = DataEncoder.Encode(JsonConvert.SerializeObject(body.Data)); var utcNow = DateTime.UtcNow; var dataContainer = new GenericDataContainer( suggestedId.Id, existingData?.OriginalSubmitter ?? authorizationResult.User.UserName, existingData?.CreatedTimeUtc ?? utcNow, authorizationResult.User.UserName, utcNow, apiVersion, data); try { var storeResult = await rdDataStorage.StoreAsync(body.DataType, dataContainer, body.Overwrite || suggestedId.HasBeenReserved); apiEventLogger.Log(LogLevel.Info, $"User '{authorizationResult.User.UserName}' has submitted data of type '{body.DataType}' with ID '{suggestedId.Id}'"); await subscriptionManager.NotifyDataChangedAsync(body.DataType, suggestedId.Id, storeResult.ModificationType); if (storeResult.IsNewCollection) { newCollectionTasks.PerformTasks(body.DataType, authorizationResult.User); } return(new ContentResult { ContentType = "text/plain", Content = storeResult.Id, StatusCode = (int)HttpStatusCode.OK }); } catch (DocumentAlreadyExistsException) { return(Conflict($"Document of type '{body.DataType}' with ID '{suggestedId.Id}' already exists")); } catch (Exception e) { apiEventLogger.Log(LogLevel.Error, e.ToString()); return(StatusCode((int)HttpStatusCode.InternalServerError, e.Message)); } }