From 8a337b7923207dffdf3cd8c4e2807817723381e6 Mon Sep 17 00:00:00 2001 From: semalaiappan <34613894+semalaiappan@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:50:20 -0600 Subject: [PATCH] [ODS-6100] Sandbox Admin needs a way to create vendors, applications and sanboxes (#980) --- .../workflows/Lib edFi.admin.dataaccess.yml | 2 +- .../Models/Application.cs | 19 +++ .../EdFi.Admin.DataAccess/Models/Vendor.cs | 3 +- .../Repositories/ClientAppRepo.cs | 128 +++++++++++++++++- .../Repositories/IClientAppRepo.cs | 19 ++- .../Utils/DefaultApplicationCreator.cs | 2 +- Application/EdFi.Ods.Api/EdFi.Ods.Api.csproj | 2 +- .../EdFi.Ods.Sandbox/EdFi.Ods.Sandbox.csproj | 2 +- .../EdFi.Ods.Tests/EdFi.Ods.Tests.csproj | 2 +- ...i.Ods.WebApi.CompositeSpecFlowTests.csproj | 6 +- .../EdFi.Ods.WebApi.IntegrationTests.csproj | 2 +- 11 files changed, 172 insertions(+), 15 deletions(-) diff --git a/.github/workflows/Lib edFi.admin.dataaccess.yml b/.github/workflows/Lib edFi.admin.dataaccess.yml index 5e73d4fc15..68cecdfdbc 100644 --- a/.github/workflows/Lib edFi.admin.dataaccess.yml +++ b/.github/workflows/Lib edFi.admin.dataaccess.yml @@ -15,7 +15,7 @@ concurrency: env: INFORMATIONAL_VERSION: "7.2" - BUILD_INCREMENTER: "-71" + BUILD_INCREMENTER: "-50" CONFIGURATION: "Release" AZURE_ARTIFACT_URL: "https://pkgs.dev.azure.com/ed-fi-alliance/Ed-Fi-Alliance-OSS/_packaging/EdFi/nuget/v3/index.json" AZURE_ARTIFACT_NUGET_KEY: ${{ secrets.AZURE_ARTIFACTS_PERSONAL_ACCESS_TOKEN }} diff --git a/Application/EdFi.Admin.DataAccess/Models/Application.cs b/Application/EdFi.Admin.DataAccess/Models/Application.cs index b0e095eb38..d980b09b75 100644 --- a/Application/EdFi.Admin.DataAccess/Models/Application.cs +++ b/Application/EdFi.Admin.DataAccess/Models/Application.cs @@ -47,5 +47,24 @@ public ApplicationEducationOrganization CreateApplicationEducationOrganization(l Application = this, ApiClients = ApiClients }; + + public static Application Create(string applicationName, long educationOrganizationId, Vendor vendor, string claimSetName, string operationalContextUri) + { + var application = new Application + { + ApplicationName = applicationName, + ClaimSetName = claimSetName, + OperationalContextUri = operationalContextUri, + Vendor =vendor + }; + + application.ApplicationEducationOrganizations.Add( + new ApplicationEducationOrganization + { + Application = application, + EducationOrganizationId = educationOrganizationId + }); + return application; + } } } diff --git a/Application/EdFi.Admin.DataAccess/Models/Vendor.cs b/Application/EdFi.Admin.DataAccess/Models/Vendor.cs index f95c9ca5af..7e20a023c3 100644 --- a/Application/EdFi.Admin.DataAccess/Models/Vendor.cs +++ b/Application/EdFi.Admin.DataAccess/Models/Vendor.cs @@ -46,7 +46,7 @@ public Application CreateApplication(string applicationName, string claimSetName public static Vendor Create(string vendorName, IEnumerable namespacePrefixes) { - var vendor = new Vendor { VendorName = vendorName }; + var vendor = new Vendor { VendorName = vendorName }; foreach (string namespacePrefix in namespacePrefixes) { @@ -58,6 +58,7 @@ public static Vendor Create(string vendorName, IEnumerable namespacePref }); } + return vendor; } } diff --git a/Application/EdFi.Admin.DataAccess/Repositories/ClientAppRepo.cs b/Application/EdFi.Admin.DataAccess/Repositories/ClientAppRepo.cs index e2f715bb8e..145258cf36 100644 --- a/Application/EdFi.Admin.DataAccess/Repositories/ClientAppRepo.cs +++ b/Application/EdFi.Admin.DataAccess/Repositories/ClientAppRepo.cs @@ -294,15 +294,117 @@ public void DeleteClient(string key) } } - public Application[] GetVendorApplications(int vendorId) + public IEnumerable GetVendors() { using (var context = _contextFactory.CreateContext()) { - return context.Applications.Where(a => a.Vendor.VendorId == vendorId) - .ToArray(); + return context.Vendors.Include(u => u.VendorNamespacePrefixes).Include(a=>a.Applications) + .Include(b=>b.Users) + .ToList(); + } + } + + public IEnumerable GetApplications() + { + using (var context = _contextFactory.CreateContext()) + { + return context.Applications.Include(u => u.ApplicationEducationOrganizations).Include(a=>a.Vendor).ToList(); + } + } + + public Vendor GetVendor(int vendorId) + { + using var context = _contextFactory.CreateContext(); + return context.Vendors.FirstOrDefault(c => c.VendorId == vendorId); + } + + public Application GetApplication(int applicationId) + { + using var context = _contextFactory.CreateContext(); + var application = context.Applications + .Where(x => x.ApplicationId == applicationId) + .Include(x => x.ApplicationEducationOrganizations) + .FirstOrDefault(); + return application; + } + + public void DeleteApplication(int applicationId) + { + using var context = _contextFactory.CreateContext(); + var application = context.Applications.Include(a => a.ApiClients).First(x => x.ApplicationId == applicationId); + + var applicationEducationOrganizations = context.ApplicationEducationOrganizations.Include(x => x.Application) + .Where(x => x.Application.ApplicationId == application.ApplicationId); + + foreach (var applicationEducationOrganization in applicationEducationOrganizations) + { + context.ApplicationEducationOrganizations.Remove(applicationEducationOrganization); + } + + var apiClientKeysToDelete = application.ApiClients.Select(a => a.Key).ToList(); + + context.Applications.Remove(application); + + context.SaveChanges(); + + foreach (var key in apiClientKeysToDelete) + { + DeleteClient(key); + } + } + + public void DeleteVendor(int vendorId) + { + using (var context = _contextFactory.CreateContext()) + { + var vendor = context.Vendors.First(x => x.VendorId == vendorId); + + var applications = context.Applications.Include(c => c.Vendor) + .ThenInclude(c => c.VendorNamespacePrefixes) + .Include(c => c.ApplicationEducationOrganizations) + .Include(c => c.ApiClients) + .Where(x => x.Vendor.VendorId == vendor.VendorId); + + List apiClientKeysToDelete = new(); + + foreach (var application in applications) + { + apiClientKeysToDelete.AddRange(application.ApiClients.Select(a => a.Key).ToList()); + context.ApplicationEducationOrganizations.RemoveRange(application.ApplicationEducationOrganizations); + context.Applications.Remove(application); + } + + foreach (var user in vendor.Users) + { + context.Users.Remove(user); + } + context.Vendors.Remove(vendor); + context.SaveChanges(); + + foreach (var key in apiClientKeysToDelete) + { + DeleteClient(key); + } } } + public Application CreateOrGetApplication(int vendorId, string applicationName, long educationOrganizationId,string claimSetName= "Ed-Fi Sandbox", string operationalContextUri = "uri://ed-fi-api-host.org") + { + using (var context = _contextFactory.CreateContext()) + { + var application = context.Applications.SingleOrDefault(v => v.ApplicationName == applicationName); + + if (application == null) + { + var vendor = context.Vendors.SingleOrDefault(v => v.VendorId == vendorId); + application = Application.Create(applicationName, educationOrganizationId, vendor, claimSetName, operationalContextUri); + } + context.Applications.Update(application); + context.SaveChanges(); + return application; + } + } + public void AddApiClientToUserWithVendorApplication(int userId, ApiClient client) { using (var context = _contextFactory.CreateContext()) @@ -489,7 +591,27 @@ public Vendor CreateOrGetVendor(string userEmail, string userName, IEnumerable namespacePrefixes, string contactName, string contactEmailAddress) + { + using (var context = _contextFactory.CreateContext()) + { + var vendor = context.Vendors.SingleOrDefault(v => v.VendorName == vendorName); + if (vendor == null) + { + vendor = Vendor.Create(vendorName, namespacePrefixes); + } + + var user = new User { FullName = contactName, Email = contactEmailAddress,Vendor=vendor }; + + vendor.Users.Add(user); + + context.Vendors.Add(vendor); + context.SaveChanges(); return vendor; } } diff --git a/Application/EdFi.Admin.DataAccess/Repositories/IClientAppRepo.cs b/Application/EdFi.Admin.DataAccess/Repositories/IClientAppRepo.cs index 8502b0f2be..cc3e788cea 100644 --- a/Application/EdFi.Admin.DataAccess/Repositories/IClientAppRepo.cs +++ b/Application/EdFi.Admin.DataAccess/Repositories/IClientAppRepo.cs @@ -37,8 +37,6 @@ public interface IClientAppRepo void SetDefaultVendorOnUserFromEmailAndName(string userEmail, string userName); - Application[] GetVendorApplications(int vendorId); - void AddApiClientToUserWithVendorApplication(int userId, ApiClient client); ApiClient SetupDefaultSandboxClient(string name, SandboxType sandboxType, string key, string secret, int userId, @@ -49,6 +47,23 @@ void SetupKeySecret(string name, SandboxType sandboxType, string key, string sec Vendor CreateOrGetVendor(string userEmail, string userName, IEnumerable namespacePrefixes); + Vendor CreateOrGetVendor(string vendorName, IEnumerable namespacePrefixes, string contactName, string contactEmailAddress); + + + Application CreateOrGetApplication(int vendorId, string applicationName, long educationOrganizationId, string claimSetName, string operationalContextUri); + + Vendor GetVendor(int vendorId); + + Application GetApplication(int applicationId); + + void DeleteApplication(int applicationId); + + void DeleteVendor(int vendorId); + + IEnumerable GetVendors(); + + IEnumerable GetApplications(); + Application CreateApplicationForVendor(int vendorId, string applicationName, string claimSetName); ApiClient CreateApiClient(int userId, string name, string key, string secret); diff --git a/Application/EdFi.Admin.DataAccess/Utils/DefaultApplicationCreator.cs b/Application/EdFi.Admin.DataAccess/Utils/DefaultApplicationCreator.cs index f6a9da9366..8c9c71caed 100644 --- a/Application/EdFi.Admin.DataAccess/Utils/DefaultApplicationCreator.cs +++ b/Application/EdFi.Admin.DataAccess/Utils/DefaultApplicationCreator.cs @@ -40,7 +40,7 @@ public Application FindOrCreateUpdatedDefaultSandboxApplication(int vendorId, Sa var vendor = context.Vendors .Where(x => x.VendorId == vendorId) .Include(x => x.Applications).ThenInclude(x => x.ApplicationEducationOrganizations) - .Single(); + .FirstOrDefault(); var defaultAppName = _configuration.GetSection("DefaultApplicationName").Value ?? "Default Sandbox Application"; var applicationName = defaultAppName + " " + sandboxType; diff --git a/Application/EdFi.Ods.Api/EdFi.Ods.Api.csproj b/Application/EdFi.Ods.Api/EdFi.Ods.Api.csproj index 8ec9e404da..cbb44a497e 100644 --- a/Application/EdFi.Ods.Api/EdFi.Ods.Api.csproj +++ b/Application/EdFi.Ods.Api/EdFi.Ods.Api.csproj @@ -26,7 +26,7 @@ - + diff --git a/Application/EdFi.Ods.Sandbox/EdFi.Ods.Sandbox.csproj b/Application/EdFi.Ods.Sandbox/EdFi.Ods.Sandbox.csproj index 93bc9895f7..ce8a71d992 100644 --- a/Application/EdFi.Ods.Sandbox/EdFi.Ods.Sandbox.csproj +++ b/Application/EdFi.Ods.Sandbox/EdFi.Ods.Sandbox.csproj @@ -20,7 +20,7 @@ - + diff --git a/Application/EdFi.Ods.Tests/EdFi.Ods.Tests.csproj b/Application/EdFi.Ods.Tests/EdFi.Ods.Tests.csproj index 6ac1bb2dda..0f7d4794d0 100644 --- a/Application/EdFi.Ods.Tests/EdFi.Ods.Tests.csproj +++ b/Application/EdFi.Ods.Tests/EdFi.Ods.Tests.csproj @@ -27,7 +27,7 @@ - + diff --git a/tests/EdFi.Ods.WebApi.CompositeSpecFlowTests/EdFi.Ods.WebApi.CompositeSpecFlowTests.csproj b/tests/EdFi.Ods.WebApi.CompositeSpecFlowTests/EdFi.Ods.WebApi.CompositeSpecFlowTests.csproj index 6e4257a107..c13115af51 100644 --- a/tests/EdFi.Ods.WebApi.CompositeSpecFlowTests/EdFi.Ods.WebApi.CompositeSpecFlowTests.csproj +++ b/tests/EdFi.Ods.WebApi.CompositeSpecFlowTests/EdFi.Ods.WebApi.CompositeSpecFlowTests.csproj @@ -33,19 +33,19 @@ - + - + - + diff --git a/tests/EdFi.Ods.WebApi.IntegrationTests/EdFi.Ods.WebApi.IntegrationTests.csproj b/tests/EdFi.Ods.WebApi.IntegrationTests/EdFi.Ods.WebApi.IntegrationTests.csproj index a99ba81929..d33b29b5af 100644 --- a/tests/EdFi.Ods.WebApi.IntegrationTests/EdFi.Ods.WebApi.IntegrationTests.csproj +++ b/tests/EdFi.Ods.WebApi.IntegrationTests/EdFi.Ods.WebApi.IntegrationTests.csproj @@ -22,7 +22,7 @@ - +