public async Task <HttpResponseMessage> Save(UpdateRequestTypeRequestDTO details) { if (details.Queries == null || !details.Queries.Any()) { throw new ArgumentException("Templates cannot be null for the RequestType, at least one template is required.", "details.Templates"); } if (details.RequestType == null) { throw new ArgumentException("RequestType cannot be null.", "details.RequestType"); } RequestType requestType = null; if (details.RequestType.ID.HasValue) { //check for edit permission if ((await DataContext.HasGrantedPermissions <RequestType>(Identity, details.RequestType.ID.Value, PermissionIdentifiers.RequestTypes.Edit)).Any() == false) { return(Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Permission required to update the specified request type.")); } requestType = await DataContext.RequestTypes.FindAsync(details.RequestType.ID.Value); await DataContext.LoadCollection(requestType, rt => rt.Queries); await DataContext.LoadCollection(requestType, rt => rt.Terms); } else { if (!(await DataContext.HasPermissions <RequestType>(Identity, PermissionIdentifiers.Portal.CreateRequestTypes))) { return(Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Permission required to create request types.")); } requestType = DataContext.RequestTypes.Add(new RequestType { ProcessorID = QueryComposerModelProcessorID, PackageIdentifier = QueryComposerPackageIdentifier, Models = new HashSet <RequestTypeModel>(), Terms = new HashSet <RequestTypeTerm>() }); } //update request type details.RequestType.Apply(DataContext.Entry(requestType)); //update the request type permissions var updatedAcls = new List <AclRequestType>(); var dbAcls = await DataContext.RequestTypeAcls.Where(a => a.RequestTypeID == requestType.ID).ToArrayAsync(); foreach (var acl in dbAcls) { var perm = details.Permissions.FirstOrDefault(p => requestType.ID == p.RequestTypeID && p.SecurityGroupID == acl.SecurityGroupID && p.PermissionID == acl.PermissionID); if (perm == null || perm.Allowed == null) { DataContext.RequestTypeAcls.Remove(acl); } else if (acl.Allowed != perm.Allowed.Value) { acl.Allowed = perm.Allowed.Value; acl.Overridden = true; updatedAcls.Add(acl); } } var newAcls = details.Permissions.Where(p => (p.RequestTypeID == requestType.ID || p.RequestTypeID == Guid.Empty) && p.Allowed.HasValue && dbAcls.Any(a => p.SecurityGroupID == a.SecurityGroupID && p.PermissionID == a.PermissionID) == false).ToArray(); foreach (var acl in newAcls) { updatedAcls.Add(DataContext.RequestTypeAcls.Add(new AclRequestType { Allowed = acl.Allowed.Value, Overridden = true, PermissionID = acl.PermissionID, RequestTypeID = requestType.ID, SecurityGroupID = acl.SecurityGroupID })); } //update the queries for the requesttype foreach (var templateDTO in details.Queries) { Template template = null; if (templateDTO.ID.HasValue) { template = requestType.Queries.FirstOrDefault(t => t.ID == templateDTO.ID.Value); } if (template == null) { template = DataContext.Templates.Add(new Template { CreatedByID = Identity.ID, CreatedOn = DateTime.UtcNow, Type = DTO.Enums.TemplateTypes.Request, RequestType = requestType, RequestTypeID = requestType.ID }); requestType.Queries.Add(template); templateDTO.ID = template.ID; } //these properties should never change after creation templateDTO.CreatedByID = template.CreatedByID; templateDTO.CreatedOn = template.CreatedOn; templateDTO.Type = DTO.Enums.TemplateTypes.Request; templateDTO.RequestTypeID = requestType.ID; templateDTO.Apply(DataContext.Entry(template)); if (string.IsNullOrEmpty(template.Name)) { template.Name = "Cohort " + (template.Order + 1); } } //for requesttype templates remove all permissions - permission will be assumbed by the requesttype permissions DataContext.TemplateAcls.RemoveRange(DataContext.TemplateAcls.Where(a => a.Template.RequestTypeID == requestType.ID)); //update associated models if (details.RequestType.ID.HasValue) { await DataContext.Entry(requestType).Collection(m => m.Models).LoadAsync(); } if (details.Models != null && details.Models.Any()) { //models to delete List <RequestTypeModel> modelToDelete = new List <RequestTypeModel>(); modelToDelete.AddRange(requestType.Models.Where(m => details.Models.Any(id => m.DataModelID == id) == false).ToArray()); foreach (var rtm in modelToDelete) { requestType.Models.Remove(rtm); } //models to add var modelsToAdd = details.Models.Where(id => requestType.Models.Any(mm => mm.DataModelID == id) == false).Select(m => new RequestTypeModel { RequestTypeID = requestType.ID, DataModelID = m }); foreach (var newModel in modelsToAdd) { requestType.Models.Add(newModel); } } else { requestType.Models.Clear(); } //update associated terms if (details.Terms != null && details.Terms.Any()) { //terms to delete List <RequestTypeTerm> termsToDelete = new List <RequestTypeTerm>(); termsToDelete.AddRange(requestType.Terms.Where(t => details.Terms.Any(id => t.TermID == id) == false).ToArray()); foreach (var term in termsToDelete) { requestType.Terms.Remove(term); } //terms to add var termsToAdd = details.Terms.Where(id => requestType.Terms.Any(t => t.TermID == id) == false).Select(t => new RequestTypeTerm { RequestTypeID = requestType.ID, TermID = t }); foreach (var newTerm in termsToAdd) { requestType.Terms.Add(newTerm); } } else { requestType.Terms.Clear(); } /* NotAllowed Terms are the terms that are hidden from the end user when not in template edit mode - ie creating a new request. */ if (details.NotAllowedTerms.Any()) { foreach (var template in details.Queries) { //clear out the existing hidden terms for the template DataContext.TemplateTerms.RemoveRange(DataContext.TemplateTerms.Where(t => t.TemplateID == template.ID.Value)); //add any specified term to the hidden terms collection foreach (var ht in details.NotAllowedTerms.Where(nt => nt.TemplateID == template.ID.Value).ToArray()) { DataContext.TemplateTerms.Add(new TemplateTerm { TermID = ht.TermID, TemplateID = ht.TemplateID, Section = ht.Section, Allowed = false }); } } } await DataContext.SaveChangesAsync(); var responseDetail = await(from rt in DataContext.RequestTypes where rt.ID == requestType.ID select new UpdateRequestTypeResponseDTO { RequestType = new RequestTypeDTO { AddFiles = rt.AddFiles, Description = rt.Description, ID = rt.ID, Metadata = rt.MetaData, Name = rt.Name, Notes = rt.Notes, PostProcess = rt.PostProcess, RequiresProcessing = rt.RequiresProcessing, SupportMultiQuery = rt.SupportMultiQuery, Timestamp = rt.Timestamp, Workflow = rt.Workflow.Name, WorkflowID = rt.WorkflowID }, Queries = rt.Queries.OrderBy(q => q.Order).Select(q => new TemplateDTO { ID = q.ID, ComposerInterface = q.ComposerInterface, CreatedBy = q.CreatedBy.UserName, CreatedByID = q.CreatedByID, CreatedOn = q.CreatedOn, Data = q.Data, Description = q.Description, Name = q.Name, Notes = q.Notes, Order = q.Order, QueryType = q.QueryType, RequestType = rt.Name, RequestTypeID = rt.ID, Timestamp = q.Timestamp, Type = q.Type }) }).FirstOrDefaultAsync(); var response = Request.CreateResponse(HttpStatusCode.Accepted, responseDetail); return(response); }
public async Task <HttpResponseMessage> Save(UpdateRequestTypeRequestDTO details) { if (details.Template == null) { throw new ArgumentException("Template cannot be null for the RequestType.", "details.Template"); } if (details.RequestType == null) { throw new ArgumentException("RequestType cannot be null.", "details.RequestType"); } RequestType requestType = null; Template template = null; if (details.RequestType.ID.HasValue) { //check for edit permission if ((await DataContext.HasGrantedPermissions <RequestType>(Identity, details.RequestType.ID.Value, PermissionIdentifiers.RequestTypes.Edit)).Any() == false) { return(Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Permission required to update the specified request type.")); } requestType = await DataContext.RequestTypes.FindAsync(details.RequestType.ID.Value); await DataContext.Entry(requestType).Reference(t => t.Template).LoadAsync(); } else { if (!(await DataContext.HasPermissions <RequestType>(Identity, PermissionIdentifiers.Portal.CreateRequestTypes))) { return(Request.CreateErrorResponse(HttpStatusCode.Forbidden, "Permission required to create request types.")); } requestType = DataContext.RequestTypes.Add(new RequestType { ProcessorID = QueryComposerModelProcessorID, PackageIdentifier = QueryComposerPackageIdentifier, Models = new HashSet <RequestTypeModel>(), Terms = new HashSet <RequestTypeTerm>() }); } if (details.Template.ID.HasValue) { template = await DataContext.Templates.FindAsync(details.Template.ID.Value); } else { template = DataContext.Templates.Add(new Template { CreatedByID = Identity.ID, CreatedOn = DateTime.UtcNow, Type = DTO.Enums.TemplateTypes.Request, Terms = new HashSet <TemplateTerm>(), RequestTypes = new HashSet <RequestType>() }); details.Template.CreatedByID = Identity.ID; details.Template.CreatedOn = DateTime.UtcNow; details.Template.Type = DTO.Enums.TemplateTypes.Request; } //update request type details.RequestType.Apply(DataContext.Entry(requestType)); if (requestType.TemplateID.HasValue == false || requestType.TemplateID.Value != template.ID) { requestType.TemplateID = template.ID; requestType.Template = template; } //update template details.Template.Apply(DataContext.Entry(template)); if (string.IsNullOrEmpty(template.Name)) { template.Name = requestType.Name; } //update associated models if (details.RequestType.ID.HasValue) { await DataContext.Entry(requestType).Collection(m => m.Models).LoadAsync(); } if (details.Models != null && details.Models.Any()) { //models to delete List <RequestTypeModel> modelToDelete = new List <RequestTypeModel>(); modelToDelete.AddRange(requestType.Models.Where(m => details.Models.Any(id => m.DataModelID == id) == false).ToArray()); foreach (var rtm in modelToDelete) { requestType.Models.Remove(rtm); } //models to add var modelsToAdd = details.Models.Where(id => requestType.Models.Any(mm => mm.DataModelID == id) == false).Select(m => new RequestTypeModel { RequestTypeID = requestType.ID, DataModelID = m }); foreach (var newModel in modelsToAdd) { requestType.Models.Add(newModel); } } else { requestType.Models.Clear(); } //update associated terms if (details.RequestType.ID.HasValue) { await DataContext.Entry(requestType).Collection(t => t.Terms).LoadAsync(); } if (details.Terms != null && details.Terms.Any()) { //terms to delete List <RequestTypeTerm> termsToDelete = new List <RequestTypeTerm>(); termsToDelete.AddRange(requestType.Terms.Where(t => details.Terms.Any(id => t.TermID == id) == false).ToArray()); foreach (var term in termsToDelete) { requestType.Terms.Remove(term); } //terms to add var termsToAdd = details.Terms.Where(id => requestType.Terms.Any(t => t.TermID == id) == false).Select(t => new RequestTypeTerm { RequestTypeID = requestType.ID, TermID = t }); foreach (var newTerm in termsToAdd) { requestType.Terms.Add(newTerm); } } else { requestType.Terms.Clear(); } //update associated templateTerms if (details.NotAllowedTerms.Any()) { if (DataContext.TemplateTerms.Any()) { //remove templateterms in the DB that no longer correspond to templateterms in NotAllowedTerms foreach (TemplateTerm tt in DataContext.TemplateTerms.Where(term => term.TemplateID == template.ID)) { if (!details.NotAllowedTerms.Any(nAT => nAT.TermID == tt.TermID && nAT.Section == tt.Section)) { DataContext.TemplateTerms.Remove(tt); } } } //add the unchecked terms foreach (SectionSpecificTermDTO uncheckedTerm in details.NotAllowedTerms) { if (!DataContext.TemplateTerms.Any(tt => tt.TermID == uncheckedTerm.TermID && tt.Section == uncheckedTerm.Section && tt.TemplateID == template.ID))//it's already in the DB { TemplateTerm templateTerm = new TemplateTerm() { TermID = uncheckedTerm.TermID, Allowed = false, Section = uncheckedTerm.Section, Template = template, TemplateID = template.ID, Term = DataContext.Terms.SingleOrDefault(t => t.ID == uncheckedTerm.TermID) }; DataContext.TemplateTerms.Add(templateTerm); } } } else { if (DataContext.TemplateTerms.Any()) { foreach (TemplateTerm term in DataContext.TemplateTerms.Where(tt => tt.TemplateID == details.Template.ID.Value)) { DataContext.TemplateTerms.Remove(term); } } } await DataContext.SaveChangesAsync(); await DataContext.Entry(requestType).ReloadAsync(); await DataContext.Entry(template).ReloadAsync(); if (DataContext.Entry(template).Reference(t => t.CreatedBy).IsLoaded == false) { await DataContext.Entry(template).Reference(t => t.CreatedBy).LoadAsync(); } if (DataContext.Entry(requestType).Reference(rt => rt.Workflow).IsLoaded == false) { await DataContext.Entry(requestType).Reference(rt => rt.Workflow).LoadAsync(); } var responseDetail = new UpdateRequestTypeResponseDTO { RequestType = requestType.Map <RequestType, RequestTypeDTO>(), Template = template.Map <Template, TemplateDTO>() }; var response = Request.CreateResponse(HttpStatusCode.Accepted, responseDetail); return(response); }