public async Task <IActionResult> ValidateInstantiation(string org, string app, [FromQuery] int partyId) { UserContext userContext = await _userHelper.GetUserContext(HttpContext); UserProfile user = await _profile.GetUserProfile(userContext.UserId); List <Party> partyList = await _authorization.GetPartyList(userContext.UserId); Application application = _appResourcesService.GetApplication(); if (application == null) { return(NotFound("Application not found")); } PartyTypesAllowed partyTypesAllowed = application.PartyTypesAllowed; Party partyUserRepresents = null; // Check if the user can represent the supplied partyId if (partyId != user.PartyId) { Party represents = InstantiationHelper.GetPartyByPartyId(partyList, partyId); if (represents == null) { // the user does not represent the chosen party id, is not allowed to initiate return(Ok(new InstantiationValidationResult { Valid = false, Message = "The user does not represent the supplied party", ValidParties = InstantiationHelper.FilterPartiesByAllowedPartyTypes(partyList, partyTypesAllowed) })); } partyUserRepresents = represents; } if (partyUserRepresents == null) { // if not set, the user represents itself partyUserRepresents = user.Party; } // Check if the application can be initiated with the party chosen bool canInstantiate = InstantiationHelper.IsPartyAllowedToInstantiate(partyUserRepresents, partyTypesAllowed); if (!canInstantiate) { return(Ok(new InstantiationValidationResult { Valid = false, Message = "The supplied party is not allowed to instantiate the application", ValidParties = InstantiationHelper.FilterPartiesByAllowedPartyTypes(partyList, partyTypesAllowed) })); } return(Ok(new InstantiationValidationResult { Valid = true, })); }
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)); }
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)); }
public async Task <dynamic> InstantiateApp(StartServiceModel startServiceModel) { // Dependency Injection: Getting the Service Specific Implementation based on the service parameter data store // Will compile code and load DLL in to memory for AltinnCore bool startService = true; IServiceImplementation serviceImplementation = _execution.GetServiceImplementation(startServiceModel.Org, startServiceModel.Service, startService); // Get the service context containing metadata about the service ServiceContext serviceContext = _execution.GetServiceContext(startServiceModel.Org, startServiceModel.Service, startService); // Create and populate the RequestContext object and make it available for the service implementation so // service developer can implement logic based on information about the request and the user performing // the request RequestContext requestContext = RequestHelper.GetRequestContext(Request.Query, Guid.Empty); requestContext.UserContext = await _userHelper.GetUserContext(HttpContext); // Populate the reportee information requestContext.UserContext.Party = await _register.GetParty(startServiceModel.PartyId); requestContext.Party = requestContext.UserContext.Party; // Checks if the reportee is allowed to initiate the application Application application = _repository.GetApplication(startServiceModel.Org, startServiceModel.Service); if (application != null && !InstantiationHelper.IsPartyAllowedToInstantiate(requestContext.UserContext.Party, application.PartyTypesAllowed)) { return(new StatusCodeResult(403)); } // Create platform service and assign to service implementation making it possible for the service implementation // to use plattform services. Also make it available in ViewBag so it can be used from Views serviceImplementation.SetPlatformServices(_platformSI); // Assign the different context information to the service implementation making it possible for // the service developer to take use of this information serviceImplementation.SetContext(requestContext, serviceContext, null, ModelState); object serviceModel = null; if (!string.IsNullOrEmpty(startServiceModel.PrefillKey)) { _form.GetPrefill( startServiceModel.Org, startServiceModel.Service, serviceImplementation.GetServiceModelType(), startServiceModel.PartyId, startServiceModel.PrefillKey); } if (serviceModel == null) { // If the service model was not loaded from prefill. serviceModel = serviceImplementation.CreateNewServiceModel(); } // Assign service model to the implementation serviceImplementation.SetServiceModel(serviceModel); // Run Instansiation event await serviceImplementation.RunServiceEvent(ServiceEventType.Instantiation); // Run validate Instansiation event where await serviceImplementation.RunServiceEvent(ServiceEventType.ValidateInstantiation); // If ValidateInstansiation event has not added any errors the new form is saved and user is redirercted to the correct if (ModelState.IsValid) { if (serviceContext.WorkFlow.Any() && serviceContext.WorkFlow[0].StepType.Equals(StepType.Lookup)) { return(JsonConvert.SerializeObject( new { org = startServiceModel.Org, service = startServiceModel.Service })); } int instanceOwnerId = requestContext.UserContext.PartyId; // Create a new instance document Instance instance = await _instance.InstantiateInstance(startServiceModel, serviceModel, serviceImplementation); // Create and store the instance created event InstanceEvent instanceEvent = new InstanceEvent { AuthenticationLevel = requestContext.UserContext.AuthenticationLevel, EventType = InstanceEventType.Created.ToString(), InstanceId = instance.Id, InstanceOwnerId = instanceOwnerId.ToString(), UserId = requestContext.UserContext.UserId, WorkflowStep = instance.Process.CurrentTask }; await _event.SaveInstanceEvent(instanceEvent, startServiceModel.Org, startServiceModel.Service); Enum.TryParse <WorkflowStep>(instance.Process.CurrentTask, out WorkflowStep currentStep); return(JsonConvert.SerializeObject( new { instanceId = instance.Id, })); } startServiceModel.PartyList = _authorization.GetPartyList(requestContext.UserContext.UserId) .Select(x => new SelectListItem { Text = (x.PartyTypeName == PartyType.Person) ? x.SSN + " " + x.Name : x.OrgNumber + " " + x.Name, Value = x.PartyId.ToString(), }).ToList(); HttpContext.Response.Cookies.Append(_generalSettings.GetAltinnPartyCookieName, startServiceModel.PartyId.ToString()); return(JsonConvert.SerializeObject( new { redirectUrl = View(startServiceModel), })); }
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)); }