예제 #1
0
        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));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }
예제 #4
0
        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);
        }
예제 #5
0
        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);
        }
예제 #6
0
        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));
        }
예제 #7
0
 public async Task <IActionResult> CreateSubmission([FromBody] SubmitDataBody submitBody)
 {
     return(await Submit(submitBody));
 }
예제 #8
0
        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));
            }
        }