public async Task <IActionResult> CreateResource([FromBody] ResourceRequestDTO resource)
        {
            //Validate Resource
            var result = await _resourceService.CreateResource(resource);

            return(Ok(result));
        }
        public async Task <IActionResult> CreateResourceBatch([FromBody] ResourceRequestDTO resource)
        {
            //Validate Resource
            var result = _resourceService.QueueResourceCreation(resource);

            return(Ok(result));
        }
Ejemplo n.º 3
0
        private async Task <ColidIdentifierResponse> CheckDuplicate(ResourceRequestDTO resourceRequestDto, string previousVersion = "")
        {
            var url = $"{_apiPathV3}/checkForDuplicate";

            if (!string.IsNullOrWhiteSpace(previousVersion))
            {
                url += $"?previousVersion={previousVersion}";
            }

            var response = await _client.PostAsync(url, BuildJsonHttpContent(resourceRequestDto));

            var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);

            _output.WriteLine(content);
            Assert.NotNull(content);
            var result = JsonConvert.DeserializeObject <List <ValidationResultProperty> >(content);

            Assert.NotNull(result);

            if (!response.IsSuccessStatusCode)
            {
                _output.WriteLine(result.ToString());
            }

            return(new ColidIdentifierResponse(response, content, result));
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Gets the NGINX proxy configuration for a resource.
        /// </summary>
        /// <param name="resource">Resource</param>
        /// <returns>Serialized NGINX configuration</returns>
        private string GetProxyConfigurationByResource(ResourceRequestDTO resource)
        {
            List <ResourceProxyDTO> publishedResourceProxyDTOs = new List <ResourceProxyDTO>();

            publishedResourceProxyDTOs.Add(ConvertResourceToProxyDto(resource));

            var nginxConfigSections = GenerateConfigSections(publishedResourceProxyDTOs);

            nginxConfigSections = FilterDuplicateConfigurationSections(nginxConfigSections);
            nginxConfigSections = OrderConfigurationSections(nginxConfigSections);
            return(SerializeNginxConfigList(nginxConfigSections));;
        }
Ejemplo n.º 5
0
        public async Task <ResourceWriteResultCTO> EditResource(Uri pidUri, ResourceRequestDTO resourceRequest)
        {
            _validationService.CheckInstantiableEntityType(resourceRequest);

            using (var lockService = _lockServiceFactory.CreateLockService())
            {
                await lockService.CreateLockAsync(pidUri.ToString());

                var resourcesCTO = GetResourcesByPidUri(pidUri);
                var id           = resourcesCTO.GetDraftOrPublishedVersion().Id;

                if (resourcesCTO.HasPublishedAndNoDraft)
                {
                    id = CreateNewResourceId();
                }

                var(validationResult, failed, validationFacade) =
                    await _resourcePreprocessService.ValidateAndPreProcessResource(id, resourceRequest, resourcesCTO,
                                                                                   ResourceCrudAction.Update);

                HandleValidationFailures(resourcesCTO.GetDraftOrPublishedVersion(), id, validationResult, failed,
                                         validationFacade);

                using (var transaction = _resourceRepository.CreateTransaction())
                {
                    // try deleting draft version and all inbound edges are changed to the new entry.
                    _resourceRepository.DeleteDraft(validationFacade.RequestResource.PidUri,
                                                    new Uri(validationFacade.RequestResource.Id));

                    // all inbound edges pointing to an entry of a pid uri(published entry) will be duplicated to the request id as well.
                    _resourceRepository.Relink(pidUri, new Uri(validationFacade.RequestResource.Id));

                    if (resourcesCTO.HasDraft)
                    {
                        _identifierService.DeleteAllUnpublishedIdentifiers(resourcesCTO.Draft);
                    }

                    _resourceRepository.Create(validationFacade.RequestResource, validationFacade.MetadataProperties);

                    CreateHasPidEntryDraftProperty(validationFacade.RequestResource.PidUri);

                    transaction.Commit();
                }

                // Check whether the correct entity type is specified -> throw exception
                return(new ResourceWriteResultCTO(validationFacade.RequestResource, validationResult));
            }
        }
Ejemplo n.º 6
0
        public void AddUpdateNginxConfigRepository(ResourceRequestDTO resource)
        {
            var    hasPid = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.hasPID, true);
            string pidUri = hasPid != null ? hasPid.Id : "";
            Dictionary <string, AttributeValue> attributes = new Dictionary <string, AttributeValue>();

            // PidUri is hash-key
            attributes["pid_uri"] = new AttributeValue {
                S = pidUri
            };

            //Try deleting if there is an existing entry in dynamoDB
            try
            {
                _amazonDynamoDbService.DeleteItemAsync(_nginxConfigDynamoDbTable, attributes);
            }
            catch (System.Exception ex)
            {
                _logger.LogInformation($"ProxyConfigService: could not delete Nginx Config before Added/Updated for : {pidUri} Error {ex.StackTrace}", pidUri, ex);
            }

            // Title is range-key
            attributes["configString"] = new AttributeValue {
                S = GetProxyConfigurationByResource(resource)
            };

            //Add new Entry
            try
            {
                _amazonDynamoDbService.PutItemAsync(_nginxConfigDynamoDbTable, attributes);
                _logger.LogInformation($"ProxyConfigService: Nginx Config Added/Updated for : {pidUri}", pidUri);
            }
            catch (System.Exception ex)
            {
                _logger.LogError($"ProxyConfigService: Error occured while Add & Update DynamoDb: {ex.StackTrace}", ex);
            }
        }
Ejemplo n.º 7
0
        public async Task <ResourceWriteResultCTO> CreateResource(ResourceRequestDTO resourceRequest)
        {
            var newResourceId = CreateNewResourceId();

            _logger.LogInformation("Create resource with id={id}", newResourceId);

            // Check whether the correct entity type is specified -> throw exception
            _validationService.CheckInstantiableEntityType(resourceRequest);

            var(validationResult, failed, validationFacade) =
                await _resourcePreprocessService.ValidateAndPreProcessResource(newResourceId, resourceRequest,
                                                                               new ResourcesCTO(), ResourceCrudAction.Create);

            validationFacade.RequestResource.Id = newResourceId;

            if (failed)
            {
                throw new ResourceValidationException(validationResult, validationFacade.RequestResource);
            }

            using (var transaction = _resourceRepository.CreateTransaction())
            {
                _resourceRepository.Create(validationFacade.RequestResource, validationFacade.MetadataProperties);

                transaction.Commit();

                // TODO: Handle error if linking failed
                if (!string.IsNullOrWhiteSpace(resourceRequest.HasPreviousVersion))
                {
                    _resourceLinkingService.LinkResourceIntoList(validationFacade.RequestResource.PidUri,
                                                                 new Uri(resourceRequest.HasPreviousVersion));
                }
            }

            return(new ResourceWriteResultCTO(validationFacade.RequestResource, validationResult));
        }
Ejemplo n.º 8
0
        private ResourceProxyDTO ConvertResourceToProxyDto(ResourceRequestDTO resource)
        {
            var    hasPid = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.hasPID, true);
            string pidUri = hasPid != null ? hasPid.Id : "";

            var    hasBaseUri = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.BaseUri, true);
            string baseUri    = hasBaseUri != null ? hasBaseUri.Id : null;

            ResourceProxyDTO resourceProxyDto = new ResourceProxyDTO
            {
                PidUrl          = pidUri,
                TargetUrl       = null,
                ResourceVersion = null,
                NestedProxies   = new List <ResourceProxyDTO>()
            };

            // Get distribution
            if (resource.Properties.ContainsKey(Graph.Metadata.Constants.Resource.Distribution))
            {
                List <dynamic> distList = resource.Properties[Graph.Metadata.Constants.Resource.Distribution];
                foreach (dynamic dist in distList)
                {
                    string distributionPidUri               = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties[Graph.Metadata.Constants.Resource.hasPID][0].Id;
                    string distributionNetworkAddress       = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, true);
                    bool   isDistributionEndpointDeprecated = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.DistributionEndpointLifecycleStatus, true) == Common.Constants.DistributionEndpoint.LifeCycleStatus.Deprecated;
                    //string distBaseUri = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, true);


                    resourceProxyDto.NestedProxies.Add(
                        new ResourceProxyDTO
                    {
                        PidUrl          = distributionPidUri,
                        TargetUrl       = isDistributionEndpointDeprecated ? pidUri : distributionNetworkAddress,
                        ResourceVersion = null,
                        BaseUrl         = baseUri
                    });
                }
            }

            //Get Main distribution
            string baseUriDistTargetUrl = "";

            if (resource.Properties.ContainsKey(Graph.Metadata.Constants.Resource.MainDistribution))
            {
                List <dynamic> distList = resource.Properties[Graph.Metadata.Constants.Resource.MainDistribution];
                foreach (dynamic dist in distList)
                {
                    string mainDistributionPidUri           = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties[Graph.Metadata.Constants.Resource.hasPID][0].Id;
                    string mainDistributionNetworkAddress   = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, true);
                    bool   isDistributionEndpointDeprecated = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.DistributionEndpointLifecycleStatus, true) == Common.Constants.DistributionEndpoint.LifeCycleStatus.Deprecated;
                    //string distBaseUri = ((COLID.Graph.TripleStore.DataModels.Base.EntityBase)dist).Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.DistributionEndpoints.HasNetworkAddress, true);
                    baseUriDistTargetUrl = isDistributionEndpointDeprecated ? pidUri : mainDistributionNetworkAddress;

                    resourceProxyDto.NestedProxies.Add(
                        new ResourceProxyDTO
                    {
                        PidUrl          = mainDistributionPidUri,
                        TargetUrl       = baseUriDistTargetUrl,
                        ResourceVersion = null,
                        BaseUrl         = baseUri
                    });
                }
            }

            // Proxy for base URI
            if (!string.IsNullOrWhiteSpace(baseUri))
            {
                string resourceVersion = resource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.HasVersion, true);

                // distribution target uri is null -> base uri have to redirect to resourcePidUri
                if (!string.IsNullOrWhiteSpace(baseUriDistTargetUrl))
                {
                    if (Uri.TryCreate(baseUriDistTargetUrl, UriKind.Absolute, out _))
                    {
                        resourceProxyDto.NestedProxies.Add(new ResourceProxyDTO {
                            PidUrl = baseUri, TargetUrl = string.IsNullOrWhiteSpace(baseUriDistTargetUrl) ? pidUri : baseUriDistTargetUrl, ResourceVersion = resourceVersion, BaseUrl = baseUri
                        });
                    }
                    else
                    {
                        resourceProxyDto.NestedProxies.Add(new ResourceProxyDTO {
                            PidUrl = baseUri, TargetUrl = pidUri, ResourceVersion = resourceVersion, BaseUrl = baseUri
                        });
                    }
                }
                else
                {
                    resourceProxyDto.NestedProxies.Add(new ResourceProxyDTO {
                        PidUrl = baseUri, TargetUrl = pidUri, ResourceVersion = resourceVersion
                    });
                }
            }

            return(resourceProxyDto);
        }
        public async Task <IActionResult> EditResource([FromQuery] Uri pidUri, [FromBody] ResourceRequestDTO resource)
        {
            var result = await _resourceService.EditResource(pidUri, resource);

            return(Ok(result));
        }
        public async Task <Tuple <ValidationResult, bool, EntityValidationFacade> > ValidateAndPreProcessResource(string resourceId, ResourceRequestDTO resourceRequestDTO,
                                                                                                                  ResourcesCTO resourcesCTO, ResourceCrudAction resourceCrudAction, bool nestedValidation = false, string consumerGroup = null, bool changeResourceType = false)
        {
            var requestResource = _mapper.Map <Resource>(resourceRequestDTO);

            requestResource.Id = string.IsNullOrWhiteSpace(resourceId) ? CreateNewResourceId() : resourceId;

            string entityType = requestResource.Properties.GetValueOrNull(Graph.Metadata.Constants.RDF.Type, true).ToString();
            var    metadata   = _metadataService.GetMetadataForEntityType(entityType);

            // If it is a nested validation (example distribution endpoint), the consumer group of the parent must be included in the process.
            var actualConsumerGroup = nestedValidation ? consumerGroup : requestResource.Properties.GetValueOrNull(Graph.Metadata.Constants.Resource.HasConsumerGroup, true);

            var validationFacade = new EntityValidationFacade(resourceCrudAction, requestResource, resourcesCTO, resourceRequestDTO.HasPreviousVersion, metadata, actualConsumerGroup);

            if (changeResourceType)
            {
                // dirty solution for changing resource type. could be refactored in the future
                var validationRes = await _validationService.ValidateEntity(requestResource, metadata).ConfigureAwait(true);

                if (validationRes.Results.Count == 1 && validationRes.Results[0].Path == Graph.Metadata.Constants.Resource.BaseUri)
                {
                    validationFacade.ResourceCrudAction = ResourceCrudAction.Create;
                }
            }
            // Remove passed properties for several properties and replace it with repo-resource properties afterwards
            RemoveProperty(Graph.Metadata.Constants.Resource.HasLaterVersion, requestResource);
            //RemoveProperty(Graph.Metadata.Constants.Resource.HasHistoricVersion, requestResource);
            RemoveProperty(Graph.Metadata.Constants.Resource.ChangeRequester, requestResource);

            if (resourceCrudAction != ResourceCrudAction.Create)
            {
                UpdatePropertyFromRepositoryResource(Graph.Metadata.Constants.Resource.HasLaterVersion, validationFacade);
                //validationFacade.RequestResource.Properties.AddOrUpdate(Graph.Metadata.Constants.Resource.MetadataGraphConfiguration, new List<dynamic>() { _metadataConfigService.GetLatestConfiguration().Id });
            }
            if (!nestedValidation) // so only new resources get this property, no distribution endpoints
            {
                RemoveProperty(Graph.Metadata.Constants.Resource.MetadataGraphConfiguration, requestResource);
                validationFacade.RequestResource.Properties.AddOrUpdate(Graph.Metadata.Constants.Resource.MetadataGraphConfiguration, new List <dynamic>()
                {
                    _metadataConfigService.GetLatestConfiguration().Id
                });
            }

            // Each property have to be valiated and in same cases transformed
            var keys = requestResource.Properties.Keys.ToList();

            foreach (var key in keys)
            {
                var property = new KeyValuePair <string, List <dynamic> >(key, requestResource.Properties[key]);

                if (changeResourceType && (property.Key == Graph.Metadata.Constants.RDF.Type))
                {
                    continue;
                }
                _entityPropertyValidator.Validate(key, validationFacade);

                await ValidateEndpoint(property, validationFacade);
            }

            // The following processes may only be executed for the main entry, so that the function already ends here with nested validations.
            if (nestedValidation)
            {
                var nestedValidationResult = new ValidationResult()
                {
                    Results = validationFacade.ValidationResults
                };
                var failedValidation = !nestedValidationResult.Conforms &&
                                       nestedValidationResult.Severity != ValidationResultSeverity.Info;
                return(new Tuple <ValidationResult, bool, EntityValidationFacade>(nestedValidationResult, failedValidation, validationFacade));
            }

            var validationResult = await _validationService.ValidateEntity(requestResource, metadata).ConfigureAwait(true);

            validationResult.Results = validationResult.Results.Select(r =>
            {
                r.ResultSeverity = IsWarningSeverity(r, resourceCrudAction) ? ValidationResultSeverity.Warning : r.ResultSeverity;

                return(r);
            }).ToList();

            string validationResourceId = validationFacade.ResourceCrudAction == ResourceCrudAction.Create ? null : resourcesCTO.GetDraftOrPublishedVersion().Id;
            var    duplicateResults     = _identifierValidationService.CheckDuplicates(requestResource, validationResourceId, resourceRequestDTO.HasPreviousVersion);

            if (changeResourceType)
            {
                duplicateResults = duplicateResults.ToList().FindAll(r => r.Path != Graph.Metadata.Constants.Resource.hasPID);
            }
            // Check whether forbidden properties are contained in the entity.
            var forbiddenPropertiesResults = _validationService.CheckForbiddenProperties(requestResource);

            // TODO: Concat or AddRange check
            validationResult.Results = validationResult.Results.Concat(validationFacade.ValidationResults).Concat(duplicateResults).Concat(forbiddenPropertiesResults).OrderBy(t => t.ResultSeverity).ToList();

            var failed = ProcessFailed(validationResult, resourceCrudAction);

            // dirty solution for changing resource type (see also above)
            validationFacade.ResourceCrudAction = changeResourceType ? ResourceCrudAction.Update : validationFacade.ResourceCrudAction;
            if (failed)
            {
                // Reset the lifecycle Status to the correct value
                if (resourceCrudAction == ResourceCrudAction.Update)
                {
                    requestResource.Properties.AddOrUpdate(Graph.Metadata.Constants.Resource.HasEntryLifecycleStatus, new List <dynamic>()
                    {
                        resourcesCTO.HasDraft?Graph.Metadata.Constants.Resource.ColidEntryLifecycleStatus.Draft: Graph.Metadata.Constants.Resource.ColidEntryLifecycleStatus.Published
                    });
                }
            }
            else
            {
                if (resourceCrudAction == ResourceCrudAction.Update && resourcesCTO.HasPublished)
                {
                    requestResource.PublishedVersion = resourcesCTO.Published.Id;
                }
            }

            return(new Tuple <ValidationResult, bool, EntityValidationFacade>(validationResult, failed, validationFacade));
        }
        /// <summary>
        /// Validates all linked entities that are not of type permanent identifier.
        /// </summary>
        /// <param name="property"></param>
        /// <param name="validationFacade"></param>
        /// <returns></returns>
        private async Task ValidateEndpoint(KeyValuePair <string, List <dynamic> > property, EntityValidationFacade validationFacade)
        {
            var key = property.Key;

            // TODO: Check for types permanent identifier
            if (key != Graph.Metadata.Constants.EnterpriseCore.PidUri && key != Graph.Metadata.Constants.Resource.BaseUri)
            {
                var newPropertyValue = new List <dynamic>();
                var tasks            = await Task.WhenAll(validationFacade.RequestResource.Properties[key].Select(async propertyValue =>
                {
                    if (!DynamicExtension.IsType <Entity>(propertyValue, out Entity parsedValue))
                    {
                        return(propertyValue);
                    }

                    var subEntityCrudAction = ResourceCrudAction.Create;
                    Entity repoEntity       = null;

                    // Only if something is updating, we can check if there is a related distribution endpoint
                    if (validationFacade.ResourceCrudAction != ResourceCrudAction.Create)
                    {
                        var repoResource = validationFacade.ResourcesCTO.GetDraftOrPublishedVersion();

                        // Try to get the distribution endpoint
                        foreach (var repoProperty in repoResource.Properties)
                        {
                            foreach (var repoPropertyValue in repoProperty.Value)
                            {
                                if (!DynamicExtension.IsType <Entity>(repoPropertyValue, out Entity parsedRepoValue) ||
                                    parsedRepoValue.Id != parsedValue.Id)
                                {
                                    continue;
                                }

                                repoEntity          = parsedRepoValue;
                                subEntityCrudAction = ResourceCrudAction.Update;
                            }
                        }
                    }

                    var entityRequest = new ResourceRequestDTO()
                    {
                        Properties = parsedValue.Properties
                    };
                    var entitiesCTO = new ResourcesCTO()
                    {
                        Draft = repoEntity, Published = repoEntity
                    };
                    var entityId = GetNestedEntityId(key, parsedValue, validationFacade.ResourcesCTO);

                    // The consumer group of the parent must be included in the process.
                    Tuple <ValidationResult, bool, EntityValidationFacade> subResult = await ValidateAndPreProcessResource(entityId, entityRequest, entitiesCTO, subEntityCrudAction, true, validationFacade.ConsumerGroup);

                    // Add validationResults to resource results
                    validationFacade.ValidationResults.AddRange(subResult.Item1.Results);

                    return(subResult.Item3.RequestResource);
                })).ConfigureAwait(true);

                validationFacade.RequestResource.Properties[key] = tasks.ToList();
            }
        }
        public async Task <IActionResult> EditResourceBatch([FromQuery] Uri pidUri, [FromBody] ResourceRequestDTO resource)
        {
            var result = _resourceService.QueueResourceEdit(pidUri, resource);

            return(Ok(result));
        }