public void ValidatePart_InvalidContentSize()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "hundebilde";
            string      contentType = "application/pdf";

            using Stream stream = new MemoryStream();

            RequestPart part = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
                Stream      = stream
            };

            string expectedErrorMessage = $"The multipart section named {partName} has no data. Cannot process empty part.";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidatePart(part);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
Esempio n. 2
0
        public void ValidatePartTest_ValidElement_ReturnsNull()
        {
            // Arrange
            Application application = new Application
            {
                ElementTypes = new List <ElementType>
                {
                    new ElementType {
                        Id = "default", AllowedContentType = new List <string> {
                            "application/xml"
                        }, MaxCount = 1
                    }
                }
            };

            RequestPartValidator target = new RequestPartValidator(application);

            RequestPart part = new RequestPart
            {
                Name        = "default",
                ContentType = "application/xml",
                Stream      = new MemoryStream(Encoding.UTF8.GetBytes("viktig melding"))
            };

            // Act
            string error = target.ValidatePart(part);

            // Assert
            Assert.Null(error);
        }
        public void ValidateParts_ListContainsInvalidPart()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "hundebilde";
            string      dataTypeId  = "hundebilde";
            string      contentType = "application/pdf";

            RequestPart validPart = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
                FileSize    = 1337
            };

            RequestPart invalidPart = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
                FileSize    = 1337 * 1024 * 1024
            };

            List <RequestPart> parts = new List <RequestPart> {
                validPart, invalidPart
            };

            string expectedErrorMessage = $"The multipart section named {partName} exceeds the size limit of element type '{dataTypeId}'";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidateParts(parts);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
        public void ValidateParts_ExceedsAllowedNuberOfDataElements()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "hundebilde";
            string      dataTypeId  = "hundebilde";
            string      contentType = "application/pdf";

            RequestPart part = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
                FileSize    = 1337
            };

            List <RequestPart> parts = new List <RequestPart> {
                part, part
            };

            string expectedErrorMessage = $"The list of parts contains more elements of type '{dataTypeId}' than the element type allows.";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidateParts(parts);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
        public void ValidatePart_MissingContentType()
        {
            // Arrange
            Application app      = TestDataUtil.GetApplication("ttd", "events");
            string      partName = "hundebilde";

            RequestPart part = new RequestPart
            {
                Name = partName
            };

            string expectedErrorMessage = $"The multipart section named {partName} is missing Content-Type.";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidatePart(part);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
        public void ValidatePart_InvalidDataType()
        {
            // Arrange
            Application app      = TestDataUtil.GetApplication("ttd", "events");
            string      partName = "kattebilde";

            RequestPart part = new RequestPart
            {
                Name = partName
            };

            string expectedErrorMessage = $"Multipart section named, '{partName}' does not correspond to an element type in application metadata";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidatePart(part);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
Esempio n. 7
0
        public void ValidatePartTest_InstanceElementWithWrongContentType_ReturnsError()
        {
            // Arrange
            Application application = new Application();

            RequestPartValidator target = new RequestPartValidator(application);

            RequestPart part = new RequestPart
            {
                Name        = "instance",
                ContentType = "application/xml",
                Stream      = new MemoryStream(Encoding.UTF8.GetBytes("viktig melding")) // Content isn't validated atm.
            };

            // Act
            string error = target.ValidatePart(part);

            // Assert
            Assert.Contains("Expecting 'application/json'", error);
        }
Esempio n. 8
0
        public void ValidatePartTest_ValidInstanceElement_ReturnsNull()
        {
            // Arrange
            Application application = new Application();

            RequestPartValidator target = new RequestPartValidator(application);

            RequestPart part = new RequestPart
            {
                Name        = "instance",
                ContentType = "application/json",
                Stream      = new MemoryStream(Encoding.UTF8.GetBytes("viktig melding")) // Content isn't validated atm.
            };

            // Act
            string error = target.ValidatePart(part);

            // Assert
            Assert.Null(error);
        }
        public void ValidatePart_ValidateInstance_ValidInstance()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "instance";
            string      contentType = "application/json";

            RequestPart part = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
            };

            RequestPartValidator sut = new RequestPartValidator(app);

            // Act
            var actual = sut.ValidatePart(part);

            // Assert
            Assert.Null(actual);
        }
        public void ValidatePart_ValidateInstance_InvalidContentType()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "instance";
            string      contentType = "application/pdf";

            RequestPart part = new RequestPart
            {
                Name        = partName,
                ContentType = contentType,
            };

            string expectedErrorMessage = $"Unexpected Content-Type '{contentType}' of embedded instance template. Expecting 'application/json'";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidatePart(part);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
Esempio n. 11
0
        public void ValidatePartsTest_ListHasTooManyElementsOfOneType_ReturnsErrorMessage()
        {
            // Arrange
            Application application = new Application
            {
                ElementTypes = new List <ElementType>
                {
                    new ElementType {
                        Id = "story", AllowedContentType = new List <string> {
                            "application/text"
                        }, MaxCount = 1
                    }
                }
            };

            RequestPartValidator target = new RequestPartValidator(application);

            List <RequestPart> parts = new List <RequestPart>
            {
                new RequestPart
                {
                    Name        = "story",
                    ContentType = "application/text",
                    Stream      = new MemoryStream(Encoding.UTF8.GetBytes("det var en gang"))
                },
                new RequestPart
                {
                    Name        = "story",
                    ContentType = "application/text",
                    Stream      = new MemoryStream(Encoding.UTF8.GetBytes("en stor ku"))
                }
            };

            // Act
            string error = target.ValidateParts(parts);

            // Assert
            Assert.Contains("than the element type allows", error);
        }
Esempio n. 12
0
        public void ValidatePartsTest_ListOfValidElements_ReturnsNull()
        {
            // Arrange
            Application application = new Application
            {
                ElementTypes = new List <ElementType>
                {
                    new ElementType {
                        Id = "story", AllowedContentType = new List <string> {
                            "application/text"
                        }, MaxCount = 2
                    }
                }
            };

            RequestPartValidator target = new RequestPartValidator(application);

            List <RequestPart> parts = new List <RequestPart>
            {
                new RequestPart
                {
                    Name        = "story",
                    ContentType = "application/text",
                    Stream      = new MemoryStream(Encoding.UTF8.GetBytes("det var en gang"))
                },
                new RequestPart
                {
                    Name        = "story",
                    ContentType = "application/text",
                    Stream      = new MemoryStream(Encoding.UTF8.GetBytes("en stor ku"))
                }
            };

            // Act
            string error = target.ValidateParts(parts);

            // Assert
            Assert.Null(error);
        }
        public void ValidatePart_InvalidContentType()
        {
            // Arrange
            Application app         = TestDataUtil.GetApplication("ttd", "events");
            string      partName    = "hundebilde";
            string      dataTypeId  = "hundebilde";
            string      contentType = "application/xml";

            RequestPart part = new RequestPart
            {
                Name        = partName,
                ContentType = contentType
            };

            string expectedErrorMessage = $"The multipart section named {partName} has a Content-Type '{contentType}' which is invalid for element type '{dataTypeId}'";
            RequestPartValidator sut    = new RequestPartValidator(app);

            // Act
            string actual = sut.ValidatePart(part);

            // Assert
            Assert.Equal(expectedErrorMessage, actual);
        }
        public async Task <ActionResult <Instance> > Post(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromQuery] int?instanceOwnerPartyId)
        {
            if (string.IsNullOrEmpty(org))
            {
                return(BadRequest("The path parameter 'org' cannot be empty"));
            }

            if (string.IsNullOrEmpty(app))
            {
                return(BadRequest("The path parameter 'app' cannot be empty"));
            }

            Application application = _appResourcesService.GetApplication();

            if (application == null)
            {
                return(NotFound($"AppId {org}/{app} was not found"));
            }

            MultipartRequestReader parsedRequest = new MultipartRequestReader(Request);
            await parsedRequest.Read();

            if (parsedRequest.Errors.Any())
            {
                return(BadRequest($"Error when reading content: {JsonConvert.SerializeObject(parsedRequest.Errors)}"));
            }

            Instance instanceTemplate = await ExtractInstanceTemplate(parsedRequest);

            if (!instanceOwnerPartyId.HasValue && instanceTemplate == null)
            {
                return(BadRequest("Cannot create an instance without an instanceOwner.partyId. Either provide instanceOwner party Id as a query parameter or an instanceTemplate object in the body."));
            }

            if (instanceOwnerPartyId.HasValue && instanceTemplate?.InstanceOwner?.PartyId != null)
            {
                return(BadRequest("You cannot provide an instanceOwnerPartyId as a query param as well as an instance template in the body. Choose one or the other."));
            }

            RequestPartValidator requestValidator = new RequestPartValidator(application);

            string multipartError = requestValidator.ValidateParts(parsedRequest.Parts);

            if (!string.IsNullOrEmpty(multipartError))
            {
                return(BadRequest($"Error when comparing content to application metadata: {multipartError}"));
            }

            if (instanceTemplate != null)
            {
                InstanceOwner lookup = instanceTemplate.InstanceOwner;

                if (lookup == null || lookup.PersonNumber == null && lookup.OrganisationNumber == null && lookup.PartyId == null)
                {
                    return(BadRequest("Error: instanceOwnerPartyId query parameter is empty and InstanceOwner is missing from instance template. You must populate instanceOwnerPartyId or InstanceOwner"));
                }
            }
            else
            {
                // create minimum instance template
                instanceTemplate = new Instance
                {
                    InstanceOwner = new InstanceOwner {
                        PartyId = instanceOwnerPartyId.Value.ToString()
                    }
                };
            }

            Party party;

            try
            {
                party = await LookupParty(instanceTemplate);
            }
            catch (Exception partyLookupException)
            {
                return(NotFound($"Cannot lookup party: {partyLookupException.Message}"));
            }

            EnforcementResult enforcementResult = await AuthorizeAction(org, app, party.PartyId, "instantiate");

            if (!enforcementResult.Authorized)
            {
                if (enforcementResult.FailedObligations != null && enforcementResult.FailedObligations.Count > 0)
                {
                    return(StatusCode((int)HttpStatusCode.Forbidden, enforcementResult.FailedObligations));
                }

                return(StatusCode((int)HttpStatusCode.Forbidden));
            }

            if (!InstantiationHelper.IsPartyAllowedToInstantiate(party, application.PartyTypesAllowed))
            {
                return(StatusCode((int)HttpStatusCode.Forbidden, $"Party {party.PartyId} is not allowed to instantiate this application {org}/{app}"));
            }

            // Run custom app logic to validate instantiation
            InstantiationValidationResult validationResult = await _altinnApp.RunInstantiationValidation(instanceTemplate);

            if (validationResult != null && !validationResult.Valid)
            {
                return(StatusCode((int)HttpStatusCode.Forbidden, validationResult));
            }

            Instance           instance;
            ProcessStateChange processResult;

            try
            {
                // start process and goto next task
                instanceTemplate.Process = null;
                string startEvent = await _altinnApp.OnInstantiateGetStartEvent();

                processResult = _processService.ProcessStartAndGotoNextTask(instanceTemplate, startEvent, User);

                // create the instance
                instance = await _instanceService.CreateInstance(org, app, instanceTemplate);
            }
            catch (Exception exception)
            {
                return(ExceptionResponse(exception, $"Instantiation of appId {org}/{app} failed for party {instanceTemplate.InstanceOwner?.PartyId}"));
            }

            try
            {
                await StorePrefillParts(instance, application, parsedRequest.Parts);

                // get the updated instance
                instance = await _instanceService.GetInstance(app, org, int.Parse(instance.InstanceOwner.PartyId), Guid.Parse(instance.Id.Split("/")[1]));

                // notify app and store events
                await ProcessController.NotifyAppAboutEvents(_altinnApp, instance, processResult.Events);

                await _processService.DispatchProcessEventsToStorage(instance, processResult.Events);
            }
            catch (Exception exception)
            {
                return(ExceptionResponse(exception, $"Instantiation of data elements failed for instance {instance.Id} for party {instanceTemplate.InstanceOwner?.PartyId}"));
            }

            SelfLinkHelper.SetInstanceAppSelfLinks(instance, Request);
            string url = instance.SelfLinks.Apps;

            return(Created(url, instance));
        }
Esempio n. 15
0
        public async Task <ActionResult <Instance> > Post(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromQuery] int?instanceOwnerId)
        {
            if (string.IsNullOrEmpty(org))
            {
                return(BadRequest("The path parameter 'org' cannot be empty"));
            }

            if (string.IsNullOrEmpty(app))
            {
                return(BadRequest("The path parameter 'app' cannot be empty"));
            }

            Application application = repositoryService.GetApplication(org, app);

            if (application == null)
            {
                return(NotFound($"AppId {org}/{app} was not found"));
            }

            MultipartRequestReader parsedRequest = new MultipartRequestReader(Request);

            parsedRequest.Read().Wait();

            if (parsedRequest.Errors.Any())
            {
                return(BadRequest($"Error when reading content: {parsedRequest.Errors}"));
            }

            Instance instanceTemplate = ExtractInstanceTemplate(parsedRequest);

            if (!instanceOwnerId.HasValue && instanceTemplate == null)
            {
                return(BadRequest("Cannot create an instance without an instanceOwnerId. Either provide instanceOwnerId as a query parameter or an instanceTemplate object in the body."));
            }

            if (instanceOwnerId.HasValue && instanceTemplate != null)
            {
                return(BadRequest("You cannot provide an instanceOwnerId as a query param as well as an instance template in the body. Choose one or the other."));
            }

            RequestPartValidator requestValidator = new RequestPartValidator(application);

            string multipartError = requestValidator.ValidateParts(parsedRequest.Parts);

            if (!string.IsNullOrEmpty(multipartError))
            {
                return(BadRequest($"Error when comparing content to application metadata: {multipartError}"));
            }

            // extract or create instance template
            if (instanceTemplate != null)
            {
                InstanceOwnerLookup lookup = instanceTemplate.InstanceOwnerLookup;

                if (string.IsNullOrEmpty(instanceTemplate.InstanceOwnerId) && (lookup == null || (lookup.PersonNumber == null && lookup.OrganisationNumber == null)))
                {
                    return(BadRequest($"Error: instanceOwnerId is empty and InstanceOwnerLookup is missing. You must populate instanceOwnerId or InstanceOwnerLookup"));
                }
            }
            else
            {
                instanceTemplate = new Instance();
                instanceTemplate.InstanceOwnerId = instanceOwnerId.Value.ToString();
            }

            Party party = null;

            if (instanceTemplate.InstanceOwnerId != null)
            {
                party = await registerService.GetParty(int.Parse(instanceTemplate.InstanceOwnerId));
            }
            else
            {
                /* todo - lookup personNumber or organisationNumber - awaiting registry endpoint implementation */
            }

            if (!InstantiationHelper.IsPartyAllowedToInstantiate(party, application.PartyTypesAllowed))
            {
                return(Forbid($"Party {party?.PartyId} is not allowed to instantiate this application {org}/{app}"));
            }

            // use process controller to start process
            instanceTemplate.Process = null;

            Instance instance = null;

            try
            {
                instance = await instanceService.CreateInstance(org, app, instanceTemplate);

                if (instance == null)
                {
                    throw new PlatformClientException("Failure instantiating instance. UnknownError");
                }
            }
            catch (Exception instanceException)
            {
                string message = $"Failure in multipart prefil. Could not create an instance of {org}/{app} for {instanceOwnerId}. App-backend has problem accessing platform storage.";

                logger.LogError($"{message} - {instanceException}");
                return(StatusCode(500, $"{message} - {instanceException.Message}"));
            }

            try
            {
                Instance instanceWithData = await StorePrefillParts(instance, parsedRequest.Parts);

                if (instanceWithData != null)
                {
                    instance = instanceWithData;
                }
            }
            catch (Exception dataException)
            {
                string message = $"Failure storing multipart prefil. Could not create a data element for {instance.Id} of {org}/{app}. App-backend has problem accessing platform storage.";
                logger.LogError($"{message} - {dataException}");

                // todo add compensating transaction (delete instance)
                return(StatusCode(500, $"{message} - {dataException.Message}"));
            }

            SetAppSelfLinks(instance, Request);
            string url = instance.SelfLinks.Apps;

            return(Created(url, instance));
        }
Esempio n. 16
0
        public async Task <ActionResult <Instance> > Post(
            [FromRoute] string org,
            [FromRoute] string app,
            [FromQuery] int?instanceOwnerPartyId)
        {
            if (string.IsNullOrEmpty(org))
            {
                return(BadRequest("The path parameter 'org' cannot be empty"));
            }

            if (string.IsNullOrEmpty(app))
            {
                return(BadRequest("The path parameter 'app' cannot be empty"));
            }

            Application application = _appResourcesService.GetApplication();

            if (application == null)
            {
                return(NotFound($"AppId {org}/{app} was not found"));
            }

            MultipartRequestReader parsedRequest = new MultipartRequestReader(Request);
            await parsedRequest.Read();

            if (parsedRequest.Errors.Any())
            {
                return(BadRequest($"Error when reading content: {JsonConvert.SerializeObject(parsedRequest.Errors)}"));
            }

            Instance instanceTemplate = ExtractInstanceTemplate(parsedRequest);

            if (!instanceOwnerPartyId.HasValue && instanceTemplate == null)
            {
                return(BadRequest("Cannot create an instance without an instanceOwner.partyId. Either provide instanceOwner party Id as a query parameter or an instanceTemplate object in the body."));
            }

            if (instanceOwnerPartyId.HasValue && instanceTemplate?.InstanceOwner?.PartyId != null)
            {
                return(BadRequest("You cannot provide an instanceOwnerPartyId as a query param as well as an instance template in the body. Choose one or the other."));
            }

            RequestPartValidator requestValidator = new RequestPartValidator(application);

            string multipartError = requestValidator.ValidateParts(parsedRequest.Parts);

            if (!string.IsNullOrEmpty(multipartError))
            {
                return(BadRequest($"Error when comparing content to application metadata: {multipartError}"));
            }

            // extract or create instance template
            if (instanceTemplate != null)
            {
                InstanceOwner lookup = instanceTemplate.InstanceOwner;

                if (string.IsNullOrEmpty(instanceTemplate.InstanceOwner.PartyId) && (lookup == null || (lookup.PersonNumber == null && lookup.OrganisationNumber == null)))
                {
                    return(BadRequest($"Error: instanceOwnerPartyId query parameter is empty and InstanceOwner is missing from instance template. You must populate instanceOwnerPartyId or InstanceOwner"));
                }
            }
            else
            {
                instanceTemplate = new Instance
                {
                    InstanceOwner = new InstanceOwner {
                        PartyId = instanceOwnerPartyId.Value.ToString()
                    }
                };
            }

            Party party;

            try
            {
                party = await LookupParty(instanceTemplate);
            }
            catch (Exception partyLookupException)
            {
                return(NotFound($"Cannot lookup party: {partyLookupException.Message}"));
            }

            XacmlJsonRequestRoot request = DecisionHelper.CreateXacmlJsonRequest(org, app, HttpContext.User, "instantiate", party.PartyId.ToString(), null);
            bool authorized = await _pdp.GetDecisionForUnvalidateRequest(request, HttpContext.User);

            if (!authorized)
            {
                return(Forbid());
            }

            if (!InstantiationHelper.IsPartyAllowedToInstantiate(party, application.PartyTypesAllowed))
            {
                return(Forbid($"Party {party?.PartyId} is not allowed to instantiate this application {org}/{app}"));
            }

            // use process controller to start process
            instanceTemplate.Process = null;

            Instance instance;

            try
            {
                instance = await _instanceService.CreateInstance(org, app, instanceTemplate);

                if (instance == null)
                {
                    throw new PlatformClientException("Failure instantiating instance. UnknownError");
                }
            }
            catch (Exception instanceException)
            {
                string message = $"Failure in multipart prefil. Could not create an instance of {org}/{app} for party {instanceTemplate.InstanceOwner.PartyId}.";

                _logger.LogError($"{message} - {instanceException}");
                return(StatusCode(500, $"{message} - {instanceException.Message}"));
            }

            try
            {
                await StorePrefillParts(instance, application, parsedRequest.Parts);

                // get the updated instance
                instance = await _instanceService.GetInstance(app, org, int.Parse(instance.InstanceOwner.PartyId), Guid.Parse(instance.Id.Split("/")[1]));

                Instance instanceWithStartedProcess = await StartProcessAndGotoNextTask(instance);

                if (instanceWithStartedProcess != null)
                {
                    instance = instanceWithStartedProcess;
                }
                else
                {
                    return(Conflict($"Unable to start and move process to next task for instance {instance.Id}"));
                }
            }
            catch (Exception dataException)
            {
                string message = $"Failure storing multipart prefil data. Could not create a data element for {instance.Id} of {org}/{app}.";
                _logger.LogError($"{message} - {dataException}");

                // todo add compensating transaction (delete instance)
                return(StatusCode(500, $"{message} Exception: {dataException.Message}"));
            }

            SelfLinkHelper.SetInstanceAppSelfLinks(instance, Request);
            string url = instance.SelfLinks.Apps;

            return(Created(url, instance));
        }