public async Task <ActionResult> Create( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerPartyId, [FromRoute] Guid instanceGuid, [FromQuery] string dataType) { if (string.IsNullOrWhiteSpace(dataType)) { return(BadRequest("Element type must be provided.")); } Application application = _appResourcesService.GetApplication(); if (application == null) { return(NotFound($"AppId {org}/{app} was not found")); } DataType dataTypeFromMetadata = application.DataTypes.FirstOrDefault(e => e.Id.Equals(dataType, StringComparison.InvariantCultureIgnoreCase)); if (dataTypeFromMetadata == null) { return(BadRequest($"Element type {dataType} not allowed for instance {instanceGuid}.")); } try { bool appLogic = dataTypeFromMetadata.AppLogic != null; Instance instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid); if (instance == null) { return(NotFound($"Did not find instance {instance}")); } if (appLogic) { return(await CreateAppModelData(org, app, instance, dataType)); } else { return(await CreateBinaryData(org, app, instance, dataType)); } } catch (PlatformHttpException pce) { return(ExceptionResponse(pce, $"Cannot create data element of {dataType} for {instanceOwnerPartyId}/{instanceGuid}")); } }
public async Task <IActionResult> Get(string org, string app, bool allowedToInstantiateFilter = false) { UserContext userContext = _userHelper.GetUserContext(HttpContext).Result; List <Party> partyList = _authorization.GetPartyList(userContext.UserId); if (allowedToInstantiateFilter) { Application application = _appResourcesService.GetApplication(); List <Party> validParties = InstantiationHelper.FilterPartiesByAllowedPartyTypes(partyList, application.PartyTypesAllowed); return(Ok(validParties)); } return(Ok(partyList)); }
public async Task <IActionResult> ValidateData( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerId, [FromRoute] Guid instanceId, [FromRoute] Guid dataGuid) { Instance instance = await _instanceService.GetInstance(app, org, instanceOwnerId, instanceId); if (instance == null) { return(NotFound()); } // Todo. Figure out where to get this from Dictionary <string, Dictionary <string, string> > serviceText = new Dictionary <string, Dictionary <string, string> >(); if (instance.Process?.CurrentTask?.ElementId == null) { throw new ValidationException("Unable to validate instance without a started process."); } List <ValidationIssue> messages = new List <ValidationIssue>(); DataElement element = instance.Data.FirstOrDefault(d => d.Id == dataGuid.ToString()); if (element == null) { throw new ValidationException("Unable to validate data element."); } Application application = _appResourceService.GetApplication(); DataType dataType = application.DataTypes.FirstOrDefault(et => et.Id == element.DataType); if (dataType == null) { throw new ValidationException("Unknown element type."); } messages.AddRange(await _validationService.ValidateDataElement(instance, dataType, element)); string taskId = instance.Process.CurrentTask.ElementId; if (!dataType.TaskId.Equals(taskId, StringComparison.OrdinalIgnoreCase)) { ValidationIssue message = new ValidationIssue { Code = ValidationIssueCodes.DataElementCodes.DataElementValidatedAtWrongTask, InstanceId = instance.Id, Severity = ValidationIssueSeverity.Warning, DataElementId = element.Id, Description = AppTextHelper.GetAppText( ValidationIssueCodes.DataElementCodes.DataElementValidatedAtWrongTask, serviceText, null, "nb") }; messages.Add(message); } return(Ok(messages)); }
/// <summary> /// Initialize a new instance of <see cref="AppBase"/> class with the given services. /// </summary> /// <param name="resourceService">The service giving access to local resources.</param> /// <param name="logger">A logging service.</param> /// <param name="dataService">The service giving access to data.</param> /// <param name="processService">The service giving access the App process.</param> /// <param name="pdfService">The service giving access to the PDF generator.</param> /// <param name="prefillService">The service giving access to prefill mechanisms.</param> /// <param name="instanceService">The service giving access to instance data</param> /// <param name="registerService">The service giving access to register data</param> /// <param name="settings">the general settings</param> /// <param name="profileService">the profile service</param> /// <param name="textService">The text service</param> /// <param name="httpContextAccessor">the httpContextAccessor</param> /// <param name="eFormidlingClient">The eFormidling client</param> /// <param name="appSettings">The appsettings</param> protected AppBase( IAppResources resourceService, ILogger <AppBase> logger, IData dataService, IProcess processService, IPDF pdfService, IPrefill prefillService, IInstance instanceService, IRegister registerService, IOptions <GeneralSettings> settings, IProfile profileService, IText textService, IHttpContextAccessor httpContextAccessor, IEFormidlingClient eFormidlingClient = null, IOptions <AppSettings> appSettings = null) { _appMetadata = resourceService.GetApplication(); _resourceService = resourceService; _logger = logger; _dataService = dataService; _processService = processService; _pdfService = pdfService; _prefillService = prefillService; _instanceService = instanceService; _registerService = registerService; _userHelper = new UserHelper(profileService, registerService, settings); _profileService = profileService; _textService = textService; _httpContextAccessor = httpContextAccessor; _appSettings = appSettings?.Value; _eFormidlingClient = eFormidlingClient; }
/// <inheritdoc/> public async Task GenerateAndStoreReceiptPDF(Instance instance) { string app = instance.AppId.Split("/")[1]; string org = instance.Org; int instanceOwnerId = int.Parse(instance.InstanceOwner.PartyId); Application application = _appResourcesService.GetApplication(); Guid instanceGuid = Guid.Parse(instance.Id.Split("/")[1]); DataType dataModelDataElement = application.DataTypes.Find(element => element.AppLogic != null); Guid dataModelDataElementGuid = Guid.Parse(instance.Data.Find(element => element.DataType.Equals(dataModelDataElement.Id))?.Id); Stream dataStream = await _dataService.GetBinaryData(org, app, instanceOwnerId, instanceGuid, dataModelDataElementGuid); byte[] dataAsBytes = new byte[dataStream.Length]; await dataStream.ReadAsync(dataAsBytes); string encodedXml = System.Convert.ToBase64String(dataAsBytes); byte[] formLayout = _appResourcesService.GetAppResource(org, app, _appSettings.FormLayoutJSONFileName); byte[] textResources = _appResourcesService.GetText(org, app, "resource.nb.json"); string formLayoutString = GetUTF8String(formLayout); string textResourcesString = GetUTF8String(textResources); PDFContext pdfContext = new PDFContext { Data = encodedXml, FormLayout = JsonConvert.DeserializeObject(formLayoutString), TextResources = JsonConvert.DeserializeObject(textResourcesString), Party = await _registerService.GetParty(instanceOwnerId), Instance = instance }; Stream pdfContent; try { pdfContent = await GeneratePDF(pdfContext); } catch (Exception exception) { _logger.LogError($"Could not generate pdf for {instance.Id}, failed with message {exception.Message}"); return; } try { await StorePDF(pdfContent, instance); } catch (Exception exception) { _logger.LogError($"Could not store pdf for {instance.Id}, failed with message {exception.Message}"); return; } finally { pdfContent.Dispose(); } }
public AppBase( IAppResources resourceService, ILogger <AppBase> logger, IData dataService, IProcess processService) { _appMetadata = resourceService.GetApplication(); _resourceService = resourceService; _logger = logger; _dataService = dataService; _processService = processService; }
/// <inheritdoc/> public async Task <string> AddEvent(string eventType, Instance instance) { string alternativeSubject = null; if (!string.IsNullOrWhiteSpace(instance.InstanceOwner.OrganisationNumber)) { alternativeSubject = $"/org/{instance.InstanceOwner.OrganisationNumber}"; } if (!string.IsNullOrWhiteSpace(instance.InstanceOwner.PersonNumber)) { alternativeSubject = $"/person/{instance.InstanceOwner.PersonNumber}"; } CloudEvent cloudEvent = new CloudEvent { Subject = $"/party/{instance.InstanceOwner.PartyId}", Type = eventType, AlternativeSubject = alternativeSubject, Time = DateTime.UtcNow, SpecVersion = "1.0", Source = new Uri($"https://{instance.Org}.apps.{_generalSettings.HostName}/{instance.AppId}/instances/{instance.Id}") }; string accessToken = _accessTokenGenerator.GenerateAccessToken(_appResources.GetApplication().Org, _appResources.GetApplication().Id.Split("/")[1]); string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName); string serializedCloudEvent = JsonSerializer.Serialize(cloudEvent); HttpResponseMessage response = await _client.PostAsync( token, "app", new StringContent(serializedCloudEvent, Encoding.UTF8, "application/json"), accessToken); if (response.IsSuccessStatusCode) { string eventId = await response.Content.ReadAsStringAsync(); return(eventId); } throw await PlatformHttpException.CreateAsync(response); }
/// <summary> /// Initialize a new instance of <see cref="AppBase"/> class with the given services. /// </summary> /// <param name="resourceService">The service giving access to local resources.</param> /// <param name="logger">A logging service.</param> /// <param name="dataService">The service giving access to data.</param> /// <param name="processService">The service giving access the App process.</param> /// <param name="pdfService">The service giving access to the PDF generator.</param> /// <param name="prefillService">The service giving access to prefill mechanisms.</param> protected AppBase( IAppResources resourceService, ILogger <AppBase> logger, IData dataService, IProcess processService, IPDF pdfService, IPrefill prefillService, IInstance instanceService) { _appMetadata = resourceService.GetApplication(); _resourceService = resourceService; _logger = logger; _dataService = dataService; _processService = processService; _pdfService = pdfService; _prefillService = prefillService; _instanceService = instanceService; }
public async Task <IActionResult> GetAction(string org, string app) { Application application = _appResources.GetApplication(); if (application != null) { string wantedAppId = $"{org}/{app}"; if (application.Id.Equals(wantedAppId)) { return(Ok(application)); } return(Conflict($"This is {application.Id}, and not the app you are looking for: {wantedAppId}!")); } return(NotFound()); }
public async Task <DataElement> InsertBinaryData(string instanceId, string dataType, string contentType, string filename, Stream stream) { Application app = _applicationService.GetApplication(); Guid dataGuid = Guid.NewGuid(); string dataPath = GetDataPath(app.Org, app.Id.Split("/")[1], Convert.ToInt32(instanceId.Split("/")[0]), new Guid(instanceId.Split("/")[1])); DataElement dataElement = new DataElement() { Id = dataGuid.ToString(), DataType = dataType, ContentType = contentType, }; if (!Directory.Exists(Path.GetDirectoryName(dataPath))) { Directory.CreateDirectory(Path.GetDirectoryName(dataPath)); } Directory.CreateDirectory(dataPath + @"blob"); long filesize; using (Stream streamToWriteTo = File.Open(dataPath + @"blob\" + dataGuid.ToString(), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite)) { await stream.CopyToAsync(streamToWriteTo); streamToWriteTo.Flush(); filesize = streamToWriteTo.Length; } dataElement.Size = filesize; string jsonData = JsonConvert.SerializeObject(dataElement); using StreamWriter sw = new StreamWriter(dataPath + dataGuid.ToString() + @".json"); sw.Write(jsonData.ToString()); sw.Close(); return(dataElement); }
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> Create( [FromRoute] string org, [FromRoute] string app, [FromRoute] int instanceOwnerPartyId, [FromRoute] Guid instanceGuid, [FromQuery] string dataType) { if (string.IsNullOrWhiteSpace(dataType)) { return BadRequest("Element type must be provided."); } /* The Body of the request is read much later when it has been made sure it is worth it. */ try { Application application = _appResourcesService.GetApplication(); if (application == null) { return NotFound($"AppId {org}/{app} was not found"); } DataType dataTypeFromMetadata = application.DataTypes.FirstOrDefault(e => e.Id.Equals(dataType, StringComparison.InvariantCultureIgnoreCase)); if (dataTypeFromMetadata == null) { return BadRequest($"Element type {dataType} not allowed for instance {instanceOwnerPartyId}/{instanceGuid}."); } if (!IsValidContributer(dataTypeFromMetadata, User)) { return Forbid(); } bool appLogic = dataTypeFromMetadata.AppLogic != null; Instance instance = await _instanceService.GetInstance(app, org, instanceOwnerPartyId, instanceGuid); if (instance == null) { return NotFound($"Did not find instance {instance}"); } if (!InstanceIsActive(instance)) { return Conflict($"Cannot upload data for archived or deleted instance {instanceOwnerPartyId}/{instanceGuid}"); } if (appLogic) { return await CreateAppModelData(org, app, instance, dataType); } else { if (!CompliesWithDataRestrictions(dataTypeFromMetadata, out string errorMessage)) { return BadRequest($"Invalid data provided. Error: {errorMessage}"); } return await CreateBinaryData(org, app, instance, dataType); } } catch (PlatformHttpException e) { return HandlePlatformHttpException(e, $"Cannot create data element of {dataType} for {instanceOwnerPartyId}/{instanceGuid}"); } }
/// <inheritdoc /> public async Task <UserProfile> GetUserProfile(int userId) { UserProfile userProfile = null; string endpointUrl = $"users/{userId}"; string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName); HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, _accessTokenGenerator.GenerateAccessToken(_appResources.GetApplication().Org, _appResources.GetApplication().Id)); if (response.StatusCode == System.Net.HttpStatusCode.OK) { userProfile = await response.Content.ReadAsAsync <UserProfile>(); } else { _logger.LogError($"Getting user profile with userId {userId} failed with statuscode {response.StatusCode}"); } return(userProfile); }
/// <inheritdoc/> public async Task GenerateAndStoreReceiptPDF(Instance instance, DataElement dataElement) { string app = instance.AppId.Split("/")[1]; string org = instance.Org; int instanceOwnerId = int.Parse(instance.InstanceOwner.PartyId); Application application = _appResourcesService.GetApplication(); Guid instanceGuid = Guid.Parse(instance.Id.Split("/")[1]); Stream dataStream = await _dataService.GetBinaryData(org, app, instanceOwnerId, instanceGuid, new Guid(dataElement.Id)); byte[] dataAsBytes = new byte[dataStream.Length]; await dataStream.ReadAsync(dataAsBytes); string encodedXml = Convert.ToBase64String(dataAsBytes); UserContext userContext = await _userHelper.GetUserContext(_httpContextAccessor.HttpContext); UserProfile userProfile = await _profileService.GetUserProfile(userContext.UserId); byte[] formLayout = _appResourcesService.GetAppResource(org, app, _appSettings.FormLayoutJSONFileName); TextResource textResource = await _textService.GetText(org, app, userProfile.ProfileSettingPreference.Language); string formLayoutString = GetUTF8String(formLayout); string textResourcesString = JsonConvert.SerializeObject(textResource); PDFContext pdfContext = new PDFContext { Data = encodedXml, FormLayout = JsonConvert.DeserializeObject(formLayoutString), TextResources = JsonConvert.DeserializeObject(textResourcesString), Party = await _registerService.GetParty(instanceOwnerId), Instance = instance, UserProfile = userProfile, UserParty = userProfile.Party }; Stream pdfContent; try { pdfContent = await GeneratePDF(pdfContext); } catch (Exception exception) { _logger.LogError($"Could not generate pdf for {instance.Id}, failed with message {exception.Message}"); return; } try { await StorePDF(pdfContent, instance, textResource); } catch (Exception exception) { _logger.LogError($"Could not store pdf for {instance.Id}, failed with message {exception.Message}"); return; } finally { pdfContent.Dispose(); } }
/// <inheritdoc/> public async Task <Party> GetParty(int partyId) { Party party = null; string endpointUrl = $"parties/{partyId}"; string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName); HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, _accessTokenGenerator.GenerateAccessToken(_appResources.GetApplication().Org, _appResources.GetApplication().Id)); if (response.StatusCode == System.Net.HttpStatusCode.OK) { party = await response.Content.ReadAsAsync <Party>(); } else { _logger.LogError($"// Getting party with partyID {partyId} failed with statuscode {response.StatusCode}"); } return(party); }
/// <inheritdoc/> public async Task <Person> GetPerson(string SSN) { Person person = null; string endpointUrl = $"persons/{SSN}"; string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName); HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, _accessTokenGenerator.GenerateAccessToken(_appResource.GetApplication().Org, _appResource.GetApplication().Id.Split("/")[1])); if (response.StatusCode == System.Net.HttpStatusCode.OK) { person = await response.Content.ReadAsAsync <Person>(); } else { _logger.LogError($"Getting person with ssn {SSN} failed with statuscode {response.StatusCode}"); } return(person); }
public async Task <List <ValidationIssue> > ValidateAndUpdateProcess(Instance instance, string taskId) { // Todo. Figure out where to get this from Dictionary <string, Dictionary <string, string> > serviceText = new Dictionary <string, Dictionary <string, string> >(); _logger.LogInformation($"Validation of {instance.Id}"); List <ValidationIssue> messages = new List <ValidationIssue>(); ModelStateDictionary validationResults = new ModelStateDictionary(); await _altinnApp.RunTaskValidation(instance, taskId, validationResults); messages.AddRange(MapModelStateToIssueList(validationResults, instance, serviceText)); Application application = _appResourcesService.GetApplication(); foreach (DataType dataType in application.DataTypes.Where(et => et.TaskId == taskId)) { List <DataElement> elements = instance.Data.Where(d => d.DataType == dataType.Id).ToList(); if (dataType.MaxCount > 0 && dataType.MaxCount < elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = AppTextHelper.GetAppText( ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, serviceText, null, "nb"), Field = dataType.Id }; messages.Add(message); } if (dataType.MinCount > 0 && dataType.MinCount > elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = AppTextHelper.GetAppText( ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, null, null, "nb"), Field = dataType.Id }; messages.Add(message); } foreach (DataElement dataElement in elements) { messages.AddRange(await ValidateDataElement(instance, dataType, dataElement)); } } if (messages.Count == 0) { instance.Process.CurrentTask.Validated = new ValidationStatus { CanCompleteTask = true, Timestamp = DateTime.Now }; } else { instance.Process.CurrentTask.Validated = new ValidationStatus { CanCompleteTask = false, Timestamp = DateTime.Now }; } instance = await _instanceService.UpdateProcess(instance); return(messages); }
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)); }
public async Task <System.Collections.Generic.List <ValidationIssue> > ValidateAndUpdateInstance(Instance instance, string taskId) { string org = instance.Org; string app = instance.AppId.Split("/")[1]; _logger.LogInformation($"Validation of {instance.Id}"); Application application = _appResourcesService.GetApplication(); // Todo. Figure out where to get this from Dictionary <string, Dictionary <string, string> > serviceText = new Dictionary <string, Dictionary <string, string> >(); List <ValidationIssue> messages = new List <ValidationIssue>(); foreach (DataType dataType in application.DataTypes.Where(et => et.TaskId == taskId)) { List <DataElement> elements = instance.Data.Where(d => d.DataType == dataType.Id).ToList(); if (dataType.MaxCount > 0 && dataType.MaxCount < elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = AppTextHelper.GetAppText( ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, serviceText, null, "nb") }; messages.Add(message); } if (dataType.MinCount > 0 && dataType.MinCount > elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = AppTextHelper.GetAppText( ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, null, null, "nb") }; messages.Add(message); } foreach (DataElement dataElement in elements) { messages.AddRange(await ValidateDataElement(instance, dataType, dataElement)); } } if (messages.Count == 0) { instance.Process.CurrentTask.Validated = new ValidationStatus { CanCompleteTask = true, Timestamp = DateTime.Now }; } else { instance.Process.CurrentTask.Validated = new ValidationStatus { CanCompleteTask = false, Timestamp = DateTime.Now }; } return(messages); }
/// <inheritdoc /> public async Task <Organization> GetOrganization(string OrgNr) { Organization organization = null; string endpointUrl = $"organizations/{OrgNr}"; string token = JwtTokenUtil.GetTokenFromContext(_httpContextAccessor.HttpContext, _settings.RuntimeCookieName); HttpResponseMessage response = await _client.GetAsync(token, endpointUrl, _accessTokenGenerator.GenerateAccessToken(_appResources.GetApplication().Org, _appResources.GetApplication().Id)); if (response.StatusCode == System.Net.HttpStatusCode.OK) { organization = await response.Content.ReadAsAsync <Organization>(); } else { _logger.LogError($"Getting organisation with orgnr {OrgNr} failed with statuscode {response.StatusCode}"); } return(organization); }
/// <summary> /// Validate an instance for a specified process step. /// </summary> /// <param name="instance">The instance to validate</param> /// <param name="taskId">The task to validate the instance for.</param> /// <returns>A list of validation errors if any were found</returns> public async Task <List <ValidationIssue> > ValidateAndUpdateProcess(Instance instance, string taskId) { _logger.LogInformation($"Validation of {instance.Id}"); List <ValidationIssue> messages = new List <ValidationIssue>(); ModelStateDictionary validationResults = new ModelStateDictionary(); await _altinnApp.RunTaskValidation(instance, taskId, validationResults); messages.AddRange(MapModelStateToIssueList(validationResults, instance)); Application application = _appResourcesService.GetApplication(); foreach (DataType dataType in application.DataTypes.Where(et => et.TaskId == taskId)) { List <DataElement> elements = instance.Data.Where(d => d.DataType == dataType.Id).ToList(); if (dataType.MaxCount > 0 && dataType.MaxCount < elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = ValidationIssueCodes.InstanceCodes.TooManyDataElementsOfType, Field = dataType.Id }; messages.Add(message); } if (dataType.MinCount > 0 && dataType.MinCount > elements.Count) { ValidationIssue message = new ValidationIssue { InstanceId = instance.Id, Code = ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, Severity = ValidationIssueSeverity.Error, Description = ValidationIssueCodes.InstanceCodes.TooFewDataElementsOfType, Field = dataType.Id }; messages.Add(message); } foreach (DataElement dataElement in elements) { messages.AddRange(await ValidateDataElement(instance, dataType, dataElement)); } } instance.Process.CurrentTask.Validated = new ValidationStatus { // The condition for completion is met if there are no errors (or other weirdnesses). CanCompleteTask = messages.Count == 0 || messages.All(m => m.Severity != ValidationIssueSeverity.Error && m.Severity != ValidationIssueSeverity.Unspecified), Timestamp = DateTime.Now }; await _instanceService.UpdateProcess(instance); return(messages); }