/// <summary> /// Imports the data sets and returns a map of old ids to new ids. /// </summary> /// <param name="sessionData">The session data.</param> /// <param name="migrationData">Contains the data sets to import.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> /// <returns>A map of data set ids, where the old id is the key and the new id is the value.</returns> private Dictionary<string, string> ImportDataSets(SessionData sessionData, MigrationData migrationData, MigrationDataResults validationResults, MigrationDataResults migrationResults) { Dictionary<string, string> map = new Dictionary<string, string>(); GenericDataSetList dataSetList = this.manager.GetDataSetList(sessionData.UserId, false); foreach (GenericDataSet dataSet in migrationData.DataSets) { var dataSetId = dataSet.Id; if (!validationResults.GetNotificationsFor(dataSet).CanImport) { migrationResults.AddNotification(dataSet, MessageType.Information, string.Format(Messages.Import_DataSetSkipped, dataSet.Name)); continue; } // Match on dataset name and overwrite if one exists var match = dataSetList.FirstOrDefault(ds => ds.Name == dataSet.Name); if (match != null) { dataSet.Id = match.Id; } GenericDataSet savedDataSet = this.manager.SaveDataSet(dataSet, sessionData.UserId); migrationResults.AddNotification(savedDataSet, MessageType.Information, string.Format(Messages.Import_DataSetSuccess, savedDataSet.Name)); map.Add(dataSetId, savedDataSet.Id); } return map; }
/// <summary> /// Perform an import. /// </summary> /// <param name="sessionData">The session data.</param> /// <param name="migrationData">The data to import.</param> /// <param name="validator">A validator for validating data prior to import.</param> /// <returns>The import process results.</returns> public MigrationDataResults Import(SessionData sessionData, MigrationData migrationData, MigrationDataValidator validator) { MigrationDataResults validationResults = validator.Validate(migrationData); MigrationDataResults migrationResults = new MigrationDataResults(); OrganisationList allOrganisations = this.manager.GetOrganisationList(sessionData.UserId, true); Dictionary<string, string> orgMap = this.ImportOrganisations(sessionData.UserId, allOrganisations, migrationData.Organisations, validationResults, migrationResults); RoleList allRoles = this.manager.GetRoleList(sessionData.UserId); Dictionary<string, string> systemRoleMap = this.ImportRoles(sessionData.UserId, migrationData.Roles, allRoles, validationResults, migrationResults); this.ImportUsers(sessionData, migrationData.Users, allRoles, allOrganisations, systemRoleMap, orgMap, validationResults, migrationResults); this.ImportProducts(sessionData, migrationData, systemRoleMap, orgMap, validationResults, migrationResults); return migrationResults; }
/// <summary> /// Imports the service endpoints and returns a map of old ids to new ids. /// </summary> /// <param name="sessionData">The session data.</param> /// <param name="migrationData">Contains the service endpoints to import.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> /// <returns>A map of service endpoint ids, where the old id is the key and the new id is the value.</returns> private Dictionary<string, string> ImportServiceEndpoints(SessionData sessionData, MigrationData migrationData, MigrationDataResults validationResults, MigrationDataResults migrationResults) { Dictionary<string, string> map = new Dictionary<string, string>(); foreach (ServiceEndpoint endpoint in migrationData.ServiceEndpoints) { if (!validationResults.GetNotificationsFor(endpoint).CanImport) { migrationResults.AddNotification(endpoint, MessageType.Information, string.Format(Messages.Import_ServiceEndpointSkipped, endpoint.Name)); continue; } ServiceEndpoint savedEndpoint; try { savedEndpoint = this.manager.SaveServiceEndpoint(endpoint, sessionData.UserId); } catch (ValidationException e) { throw new Exception(string.Format(Messages.Validate_ServiceEndpointFailure, endpoint.Name, endpoint.Id, e.Results.First().Message)); } migrationResults.AddNotification(savedEndpoint, MessageType.Information, string.Format(Messages.Import_ServiceEndpointSuccess, savedEndpoint.Name)); map.Add(endpoint.Id, savedEndpoint.Id); } return map; }
/// <summary> /// Imports the users. /// </summary> /// <param name="sessionData">The session data.</param> /// <param name="users">The list of users to import.</param> /// <param name="allRoles">A list of all roles in the system.</param> /// <param name="allOrganisations">A list of all organisations in the system.</param> /// <param name="systemRoleMap">A map of role ids, where the old id is the key and the new id is the value.</param> /// <param name="organisationMap">A map of organisation ids, where the old id is the key and the new id is the value.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> private void ImportUsers(SessionData sessionData, UserList users, RoleList allRoles, OrganisationList allOrganisations, Dictionary<string, string> systemRoleMap, Dictionary<string, string> organisationMap, MigrationDataResults validationResults, MigrationDataResults migrationResults) { foreach (User user in users) { if (!validationResults.GetNotificationsFor(user).CanImport) { migrationResults.AddNotification(user, MessageType.Information, string.Format(Messages.Import_UserSkipped, user.DisplayName)); continue; } foreach (KeyValuePair<string, string> kvp in systemRoleMap) { if (user.Roles.ContainsKey(kvp.Key)) { user.Roles.Remove(kvp.Key); user.Roles.Add(kvp.Value, allRoles[kvp.Value].RoleName); } } foreach (KeyValuePair<string, string> kvp in organisationMap) { if (user.Organisations.ContainsKey(kvp.Key)) { user.Organisations.Remove(kvp.Key); user.Organisations.Add(kvp.Value, allOrganisations[kvp.Value].Name); } } user.Id = null; User savedUser = this.securityGateway.SaveUser(sessionData, user); if (string.IsNullOrEmpty(user.ExternalId)) { migrationResults.AddNotification(savedUser, MessageType.Information, string.Format(Messages.Import_UserSuccess, savedUser.DisplayName)); } else { migrationResults.AddNotification(savedUser, MessageType.Information, string.Format(Messages.Import_UserSuccessNoPasswordChange, savedUser.DisplayName)); } } }
/// <summary> /// Imports the roles. /// </summary> /// <param name="userId">The user making the request.</param> /// <param name="roles">The list of roles to import.</param> /// <param name="allRoles">A list of all roles already in the system.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> /// <returns>A map of role ids, where the old id is the key and the new id is the value.</returns> private Dictionary<string, string> ImportRoles(string userId, RoleList roles, RoleList allRoles, MigrationDataResults validationResults, MigrationDataResults migrationResults) { Dictionary<string, string> systemRoleMap = new Dictionary<string, string>(); foreach (Role role in roles) { if (role.SystemDefined) { string mappedValue = allRoles.FirstOrDefault(r => r.RoleName == role.RoleName).Id; systemRoleMap.Add(role.Id, mappedValue); migrationResults.AddNotification(role, MessageType.Information, string.Format(Messages.Import_RoleSkipped, role.RoleName)); continue; } if (!validationResults.GetNotificationsFor(role).CanImport) { migrationResults.AddNotification(role, MessageType.Information, string.Format(Messages.Import_RoleSkipped, role.RoleName)); continue; } this.manager.SaveRole(userId, role, true); migrationResults.AddNotification(role, MessageType.Information, string.Format(Messages.Import_RoleSuccess, role.RoleName)); } return systemRoleMap; }
/// <summary> /// Imports the products. /// </summary> /// <param name="sessionData">The session data.</param> /// <param name="migrationData">Contains the products to import.</param> /// <param name="systemRoleMap">A map of role ids, where the old id is the key and the new id is the value.</param> /// <param name="organisationMap">A map of organisation ids, where the old id is the key and the new id is the value.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> private void ImportProducts(SessionData sessionData, MigrationData migrationData, Dictionary<string, string> systemRoleMap, Dictionary<string, string> organisationMap, MigrationDataResults validationResults, MigrationDataResults migrationResults) { const string importedMessage = "Imported via Workbench"; Dictionary<string, string> validatorMap = this.ImportValidators(sessionData.UserId, migrationData.Validators); Dictionary<string, string> serviceEndpointMap = this.ImportServiceEndpoints(sessionData, migrationData, validationResults, migrationResults); Dictionary<string, string> dataSetMap = this.ImportDataSets(sessionData, migrationData, validationResults, migrationResults); SystemSettings settings = this.manager.GetSystemSettings(sessionData.UserId); if (settings.EnableFormApprovals) { migrationData.Products.ForEach(p => p.BranchName = Constants.DefaultImportBranch); } foreach (ProductDefinition product in migrationData.Products) { if (!validationResults.GetNotificationsFor(product).CanImport) { continue; } ProductDataSourceConfiguration dataSourceConfiguration = migrationData.ProductDataSourceConfigurations[product.Id]; if (organisationMap.ContainsKey(product.OrganisationId)) { product.OrganisationId = organisationMap[product.OrganisationId]; } WorkflowConfigurationContainer workflowConfiguration = migrationData.WorkflowConfigurations[product.Id]; ApplicationEntitlementList applicationEntitlements = new ApplicationEntitlementList(migrationData.Security.SelectMany(s => s.ApplicationEntitlements).Where(e => e.ProductId == product.Id)); PageEntitlementList pageEntitlements = new PageEntitlementList(migrationData.Security.SelectMany(s => s.PageEntitlements).Where(e => e.ProductId == product.Id)); ControlEntitlementList controlEntitlements = new ControlEntitlementList(migrationData.Security.SelectMany(s => s.ControlEntitlements).Where(e => e.ProductId == product.Id)); MetadataEntitlementList metadataEntitlements = new MetadataEntitlementList(migrationData.Security.SelectMany(s => s.MetadataEntitlements).Where(e => e.ProductId == product.Id)); SecurityConfiguration securityConfiguration = new SecurityConfiguration(applicationEntitlements, pageEntitlements, controlEntitlements, metadataEntitlements); foreach (KeyValuePair<string, string> kvp in systemRoleMap) { foreach (ApplicationEntitlement entitlement in applicationEntitlements.Where(e => e.RoleId == kvp.Key)) { entitlement.RoleId = systemRoleMap[entitlement.RoleId]; } foreach (PageEntitlement entitlement in pageEntitlements.Where(e => e.RoleId == kvp.Key)) { entitlement.RoleId = systemRoleMap[entitlement.RoleId]; } foreach (ControlEntitlement entitlement in controlEntitlements.Where(e => e.RoleId == kvp.Key)) { entitlement.RoleId = systemRoleMap[entitlement.RoleId]; } foreach (MetadataEntitlement entitlement in metadataEntitlements.Where(e => e.RoleId == kvp.Key)) { entitlement.RoleId = systemRoleMap[entitlement.RoleId]; } foreach (EmailWorkflowTransitionAction emailTransition in workflowConfiguration.Configuration.States.SelectMany(s => s.Transitions).SelectMany(t => t.TransitionActionList).OfType<EmailWorkflowTransitionAction>().Where(ewt => ewt.PdfRenderRole == kvp.Key)) { emailTransition.PdfRenderRole = systemRoleMap[emailTransition.PdfRenderRole]; } } string mappedId; // Update control validators with new IDs IEnumerable<ControlRegexValidator> controlValidators = product.FormDefinition.Pages.AllControls.AllValidators(); foreach (ControlRegexValidator validator in controlValidators) { bool available = validatorMap.TryGetValue(validator.ValidatorId, out mappedId); if (available) { validator.ValidatorId = mappedId; } } // Update prebuilt option sources with new IDs List<ControlWithOptions> prebuiltOptionControls = product.FormDefinition.Pages.AllControls.FindAllRecursive<ControlWithOptions>(x => x.OptionSource.Type == OptionSourceType.Prebuilt); foreach (ControlWithOptions prebuiltOptionControl in prebuiltOptionControls) { bool available = dataSetMap.TryGetValue(((PrebuiltOptionSource)prebuiltOptionControl.OptionSource).DataSetId, out mappedId); if (available) { ((PrebuiltOptionSource)prebuiltOptionControl.OptionSource).DataSetId = mappedId; } } // Update service endpoints with new IDs this.UpdateServiceEndpoints(product, dataSourceConfiguration, workflowConfiguration.Configuration, serviceEndpointMap); product.EditComment = importedMessage; ProductVariation productVariation = null; if (product.IsChildForm) { productVariation = migrationData.ProductVariations.Exists(p => p.ProductId == product.Id) ? migrationData.ProductVariations.First(p => p.ProductId == product.Id) : new ProductVariation { AddedControls = new List<int>(), EditedControls = new List<int>(), RemovedControls = new List<int>() }; } Product savedProduct = this.manager.SaveProduct(sessionData, product, workflowConfiguration.Configuration, securityConfiguration, dataSourceConfiguration, productVariation); migrationResults.AddNotification(savedProduct, MessageType.Information, string.Format(Messages.Import_ProductSuccess, savedProduct.Name, savedProduct.Version)); } }
/// <summary> /// Imports the organisations. /// </summary> /// <param name="userId">The user making the request.</param> /// <param name="allOrganisations">All organisations.</param> /// <param name="organisations">The list of organisations to import.</param> /// <param name="validationResults">A list of validation results.</param> /// <param name="migrationResults">A list to which import results will be appended.</param> /// <returns> /// A map of organisation ids, where the old id is the key and the new id is the value. /// </returns> private Dictionary<string, string> ImportOrganisations(string userId, OrganisationList allOrganisations, List<MigrationOrganisation> organisations, MigrationDataResults validationResults, MigrationDataResults migrationResults) { Dictionary<string, string> organisationMap = new Dictionary<string, string>(); Organisation baseOrg = this.manager.GetBaseOrganisation(); foreach (MigrationOrganisation org in organisations) { if (!validationResults.GetNotificationsFor(org).CanImport) { migrationResults.AddNotification(org, MessageType.Information, string.Format(Messages.Import_OrganisationSkipped, org.Name)); continue; } string oldId = org.Id; org.Id = null; if (string.IsNullOrWhiteSpace(org.ParentOrganisationId) || org.BaseOrganisation) { organisationMap.Add(oldId, baseOrg.Id); migrationResults.AddNotification(org, MessageType.Information, string.Format(Messages.Import_BaseOrganisation, org.Name)); } else { Organisation parent = allOrganisations.FirstOrDefault(o => o.Name == org.ParentOrganisationName); Organisation thisOrg = allOrganisations.FirstOrDefault(o => o.Name == org.Name); if (parent != null) { org.ParentOrganisationId = parent.Id; } if (thisOrg != null) { organisationMap.Add(oldId, thisOrg.Id); migrationResults.AddNotification(org, MessageType.Information, string.Format(Messages.Import_OrganisationSkipped, org.Name)); } else { Organisation newOrg = this.manager.SaveOrganisation(org, userId); organisationMap.Add(oldId, newOrg.Id); allOrganisations.Add(newOrg); migrationResults.AddNotification(org, MessageType.Information, string.Format(Messages.Import_OrganisationSuccess, org.Name)); } } } return organisationMap; }
/// <summary> /// Validates the <paramref name="migrationData"/> and returns the results as a list of messages. /// </summary> /// <param name="migrationData">The migration data to validate.</param> /// <returns>A list of warnings resulting from the validation.</returns> public MigrationDataResults Validate(MigrationData migrationData) { MigrationDataResults results = new MigrationDataResults(); Version currentSystemVersion = this.dataAccess.GetSystemVersion(); if (migrationData.SystemVersion != null && currentSystemVersion.CompareTo(migrationData.SystemVersion, 2) != 0) { string message = currentSystemVersion.CompareTo(migrationData.SystemVersion, 2) > 0 ? string.Format(Messages.Validate_TargetSystemVersionTooHigh, currentSystemVersion.ToString(2), migrationData.SystemVersion.ToString(2)) : string.Format(Messages.Validate_TargetSystemVersionTooLow, currentSystemVersion.ToString(2), migrationData.SystemVersion.ToString(2)); throw new MigrationVersionException(message); } if (migrationData.SystemVersion == null) { string message = string.Format(Messages.Validate_ExportMissingVersion, currentSystemVersion.ToString(2)); throw new MigrationVersionException(message); } this.ValidateProducts(migrationData, results); if (migrationData.Users.Count > 0) { IEnumerable<string> usernames = migrationData.Users.Select(p => p.Username); OrganisationList orgList = this.dataAccess.GetOrganisationList(); UserSearchCriteria filter = new UserSearchCriteria { OrganisationIds = orgList.Select(x => x.Id).ToList(), Usernames = usernames.ToList() }; UserList foundUsers = this.dataAccess.FindUsers(filter); foreach (User u in foundUsers) { results.AddNotification(migrationData.Users.FirstOrDefault(user => user.Username == u.Username), MessageType.Error, string.Format(Messages.Validate_UserExistsUsername, u.Username)); } } if (migrationData.Roles.Count > 0) { RoleList allRoles = this.dataAccess.GetRoleList(); foreach (Role r in allRoles.Where(r => !r.SystemDefined)) { if (migrationData.Roles.Contains(r.Id)) { results.AddNotification(r, MessageType.Error, string.Format(Messages.Validate_RoleExistsId, r.RoleName)); } } } if (migrationData.Organisations.Count > 0) { OrganisationList allOrganisations = this.dataAccess.GetOrganisationList(); foreach (Organisation org in allOrganisations) { MigrationOrganisation migrationOrgMatchId = migrationData.Organisations.FirstOrDefault(o => o.Id == org.Id); if (migrationOrgMatchId != null) { results.AddNotification(migrationOrgMatchId, MessageType.Error, string.Format(Messages.Validate_OrgExistsId, org.Name)); } else { MigrationOrganisation migrationOrgMatchName = migrationData.Organisations.FirstOrDefault(o => o.Name == org.Name); if (migrationOrgMatchName != null) { results.AddNotification(migrationOrgMatchName, MessageType.Warning, string.Format(Messages.Validate_OrgExistsId, org.Name)); } } } } if (migrationData.ServiceEndpoints.Count > 0) { ServiceEndpointList allEndpoints = this.dataAccess.GetServiceEndpointList(); foreach (ServiceEndpoint endpoint in allEndpoints) { if (migrationData.ServiceEndpoints.Contains(endpoint.Id)) { results.AddNotification(endpoint, MessageType.Error, string.Format(Messages.Validate_ServiceEndpointExistsId, endpoint.Name, endpoint.Id)); } } } if (migrationData.DataSets.Count > 0) { GenericDataSetList allDataSets = this.dataAccess.GetDataSetList(false); foreach (GenericDataSet dataSet in allDataSets) { if (migrationData.DataSets.Any(x => x.Id == dataSet.Id)) { results.AddNotification(dataSet, MessageType.Warning, string.Format(Messages.Validate_DataSetExistsId, dataSet.Name, dataSet.Id)); } } } return results; }
/// <summary> /// Validates the products. /// </summary> /// <param name="migrationData">The migration data.</param> /// <param name="results">The results.</param> private void ValidateProducts(MigrationData migrationData, MigrationDataResults results) { foreach (ProductDefinition p in migrationData.Products) { if (!migrationData.ProductDataSourceConfigurations.ContainsKey(p.Id)) { results.AddNotification(p, MessageType.Error, string.Format(Messages.Validate_ProductMissingDataSourceConfig, p.Name)); } if (migrationData.Security.SelectMany(s => s.ApplicationEntitlements).All(e => e.ProductId != p.Id)) { results.AddNotification(p, MessageType.Error, string.Format(Messages.Validate_ProductMissingSecurityConfig, p.Name)); } if (!migrationData.WorkflowConfigurations.Contains(p.Id)) { results.AddNotification(p, MessageType.Error, string.Format(Messages.Validate_ProductMissingWorkflowConfig, p.Name)); } if (!results.GetNotificationsFor(p).CanImport) { continue; } try { Product foundProduct = this.dataAccess.GetProduct<ProductSearchResult>(p.Id); results.AddNotification(p, MessageType.Warning, string.Format(Messages.Validate_ProductWillBeOverriden, migrationData.Products[p.Id].Name, foundProduct.Name)); } catch (NullReferenceException) { // Product does not already exist. } } }