diff --git a/src/Api/Controllers/OrganizationsController.cs b/src/Api/Controllers/OrganizationsController.cs index 92e9fcb876..ea7330b756 100644 --- a/src/Api/Controllers/OrganizationsController.cs +++ b/src/Api/Controllers/OrganizationsController.cs @@ -28,6 +28,7 @@ public class OrganizationsController : Controller private readonly IOrganizationRepository _organizationRepository; private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IPolicyRepository _policyRepository; + private readonly IProviderRepository _providerRepository; private readonly IOrganizationService _organizationService; private readonly IUserService _userService; private readonly IPaymentService _paymentService; @@ -46,6 +47,7 @@ public class OrganizationsController : Controller IOrganizationRepository organizationRepository, IOrganizationUserRepository organizationUserRepository, IPolicyRepository policyRepository, + IProviderRepository providerRepository, IOrganizationService organizationService, IUserService userService, IPaymentService paymentService, @@ -63,6 +65,7 @@ public class OrganizationsController : Controller _organizationRepository = organizationRepository; _organizationUserRepository = organizationUserRepository; _policyRepository = policyRepository; + _providerRepository = providerRepository; _organizationService = organizationService; _userService = userService; _paymentService = paymentService; @@ -101,7 +104,7 @@ public class OrganizationsController : Controller public async Task GetBilling(string id) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.ViewBillingHistory(orgIdGuid)) { throw new NotFoundException(); } @@ -120,7 +123,7 @@ public class OrganizationsController : Controller public async Task GetSubscription(string id) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.ViewSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -139,7 +142,9 @@ public class OrganizationsController : Controller throw new NotFoundException(); } - return new OrganizationSubscriptionResponseModel(organization, subscriptionInfo); + var hideSensitiveData = !await _currentContext.EditSubscription(orgIdGuid); + + return new OrganizationSubscriptionResponseModel(organization, subscriptionInfo, hideSensitiveData); } else { @@ -240,7 +245,7 @@ public class OrganizationsController : Controller model.BillingEmail != organization.BillingEmail); var hasRequiredPermissions = updateBilling - ? await _currentContext.ManageBilling(orgIdGuid) + ? await _currentContext.EditSubscription(orgIdGuid) : await _currentContext.OrganizationOwner(orgIdGuid); if (!hasRequiredPermissions) @@ -257,7 +262,7 @@ public class OrganizationsController : Controller public async Task PostPayment(string id, [FromBody] PaymentRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditPaymentMethods(orgIdGuid)) { throw new NotFoundException(); } @@ -280,7 +285,7 @@ public class OrganizationsController : Controller public async Task PostUpgrade(string id, [FromBody] OrganizationUpgradeRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -294,7 +299,7 @@ public class OrganizationsController : Controller public async Task PostSubscription(string id, [FromBody] OrganizationSubscriptionUpdateRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -307,7 +312,7 @@ public class OrganizationsController : Controller public async Task PostSeat(string id, [FromBody] OrganizationSeatRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -321,7 +326,7 @@ public class OrganizationsController : Controller public async Task PostStorage(string id, [FromBody] StorageRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -335,7 +340,7 @@ public class OrganizationsController : Controller public async Task PostVerifyBank(string id, [FromBody] OrganizationVerifyBankRequestModel model) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -348,7 +353,7 @@ public class OrganizationsController : Controller public async Task PostCancel(string id) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } @@ -361,7 +366,7 @@ public class OrganizationsController : Controller public async Task PostReinstate(string id) { var orgIdGuid = new Guid(id); - if (!await _currentContext.ManageBilling(orgIdGuid)) + if (!await _currentContext.EditSubscription(orgIdGuid)) { throw new NotFoundException(); } diff --git a/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs b/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs index 0e284ab9cb..d2fdc1e0ba 100644 --- a/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs +++ b/src/Api/Models/Response/Organizations/OrganizationResponseModel.cs @@ -84,28 +84,30 @@ public class OrganizationResponseModel : ResponseModel public class OrganizationSubscriptionResponseModel : OrganizationResponseModel { - public OrganizationSubscriptionResponseModel(Organization organization, SubscriptionInfo subscription = null) - : base(organization, "organizationSubscription") + public OrganizationSubscriptionResponseModel(Organization organization) : base(organization, "organizationSubscription") { - if (subscription != null) - { - Subscription = subscription.Subscription != null ? - new BillingSubscription(subscription.Subscription) : null; - UpcomingInvoice = subscription.UpcomingInvoice != null ? - new BillingSubscriptionUpcomingInvoice(subscription.UpcomingInvoice) : null; - Expiration = DateTime.UtcNow.AddYears(1); // Not used, so just give it a value. - } - else - { - Expiration = organization.ExpirationDate; - } - + Expiration = organization.ExpirationDate; StorageName = organization.Storage.HasValue ? CoreHelpers.ReadableBytesSize(organization.Storage.Value) : null; StorageGb = organization.Storage.HasValue ? Math.Round(organization.Storage.Value / 1073741824D, 2) : 0; // 1 GB } + public OrganizationSubscriptionResponseModel(Organization organization, SubscriptionInfo subscription, bool hideSensitiveData) + : this(organization) + { + Subscription = subscription.Subscription != null ? new BillingSubscription(subscription.Subscription) : null; + UpcomingInvoice = subscription.UpcomingInvoice != null ? new BillingSubscriptionUpcomingInvoice(subscription.UpcomingInvoice) : null; + Expiration = DateTime.UtcNow.AddYears(1); // Not used, so just give it a value. + + if (hideSensitiveData) + { + BillingEmail = null; + Subscription.Items = null; + UpcomingInvoice.Amount = null; + } + } + public string StorageName { get; set; } public double? StorageGb { get; set; } public BillingSubscription Subscription { get; set; } diff --git a/src/Api/Models/Response/ProfileOrganizationResponseModel.cs b/src/Api/Models/Response/ProfileOrganizationResponseModel.cs index b8895fdc92..871e48d0a1 100644 --- a/src/Api/Models/Response/ProfileOrganizationResponseModel.cs +++ b/src/Api/Models/Response/ProfileOrganizationResponseModel.cs @@ -1,4 +1,5 @@ using Bit.Core.Enums; +using Bit.Core.Enums.Provider; using Bit.Core.Models.Api; using Bit.Core.Models.Data; using Bit.Core.Models.Data.Organizations.OrganizationUsers; @@ -46,6 +47,7 @@ public class ProfileOrganizationResponseModel : ResponseModel UserId = organization.UserId?.ToString(); ProviderId = organization.ProviderId?.ToString(); ProviderName = organization.ProviderName; + ProviderType = organization.ProviderType; FamilySponsorshipFriendlyName = organization.FamilySponsorshipFriendlyName; FamilySponsorshipAvailable = FamilySponsorshipFriendlyName == null && StaticStore.GetSponsoredPlan(PlanSponsorshipType.FamiliesForEnterprise) @@ -97,6 +99,7 @@ public class ProfileOrganizationResponseModel : ResponseModel public bool HasPublicAndPrivateKeys { get; set; } public string ProviderId { get; set; } public string ProviderName { get; set; } + public ProviderType? ProviderType { get; set; } public string FamilySponsorshipFriendlyName { get; set; } public bool FamilySponsorshipAvailable { get; set; } public ProductType PlanProductType { get; set; } diff --git a/src/Api/Models/Response/SubscriptionResponseModel.cs b/src/Api/Models/Response/SubscriptionResponseModel.cs index 4888bd2080..3ec1b975e3 100644 --- a/src/Api/Models/Response/SubscriptionResponseModel.cs +++ b/src/Api/Models/Response/SubscriptionResponseModel.cs @@ -100,6 +100,6 @@ public class BillingSubscriptionUpcomingInvoice Date = inv.Date; } - public decimal Amount { get; set; } + public decimal? Amount { get; set; } public DateTime? Date { get; set; } } diff --git a/src/Core/Context/CurrentContext.cs b/src/Core/Context/CurrentContext.cs index 598f30bbb2..512ab44310 100644 --- a/src/Core/Context/CurrentContext.cs +++ b/src/Core/Context/CurrentContext.cs @@ -13,9 +13,11 @@ namespace Bit.Core.Context; public class CurrentContext : ICurrentContext { + private readonly IProviderOrganizationRepository _providerOrganizationRepository; private readonly IProviderUserRepository _providerUserRepository; private bool _builtHttpContext; private bool _builtClaimsPrincipal; + private IEnumerable _providerOrganizationProviderDetails; private IEnumerable _providerUserOrganizations; public virtual HttpContext HttpContext { get; set; } @@ -37,8 +39,11 @@ public class CurrentContext : ICurrentContext public virtual ClientType ClientType { get; set; } public virtual Guid? ServiceAccountOrganizationId { get; set; } - public CurrentContext(IProviderUserRepository providerUserRepository) + public CurrentContext( + IProviderOrganizationRepository providerOrganizationRepository, + IProviderUserRepository providerUserRepository) { + _providerOrganizationRepository = providerOrganizationRepository; _providerUserRepository = providerUserRepository; } @@ -392,15 +397,34 @@ public class CurrentContext : ICurrentContext && (o.Permissions?.ManageResetPassword ?? false)) ?? false); } - public async Task ManageBilling(Guid orgId) + public async Task ViewSubscription(Guid orgId) { - var orgManagedByProvider = await ProviderIdForOrg(orgId) != null; + var orgManagedByMspProvider = (await GetOrganizationProviderDetails()).Any(po => po.OrganizationId == orgId && po.ProviderType == ProviderType.Msp); + + return orgManagedByMspProvider + ? await ProviderUserForOrgAsync(orgId) + : await OrganizationOwner(orgId); + } + + public async Task EditSubscription(Guid orgId) + { + var orgManagedByProvider = (await GetOrganizationProviderDetails()).Any(po => po.OrganizationId == orgId); return orgManagedByProvider ? await ProviderUserForOrgAsync(orgId) : await OrganizationOwner(orgId); } + public async Task EditPaymentMethods(Guid orgId) + { + return await EditSubscription(orgId); + } + + public async Task ViewBillingHistory(Guid orgId) + { + return await EditSubscription(orgId); + } + public bool ProviderProviderAdmin(Guid providerId) { return Providers?.Any(o => o.Id == providerId && o.Type == ProviderUserType.ProviderAdmin) ?? false; @@ -433,7 +457,7 @@ public class CurrentContext : ICurrentContext public async Task ProviderUserForOrgAsync(Guid orgId) { - return (await GetProviderOrganizations()).Any(po => po.OrganizationId == orgId); + return (await GetProviderUserOrganizations()).Any(po => po.OrganizationId == orgId); } public async Task ProviderIdForOrg(Guid orgId) @@ -443,7 +467,7 @@ public class CurrentContext : ICurrentContext return null; } - var po = (await GetProviderOrganizations()) + var po = (await GetProviderUserOrganizations()) ?.FirstOrDefault(po => po.OrganizationId == orgId); return po?.ProviderId; @@ -520,7 +544,7 @@ public class CurrentContext : ICurrentContext }; } - protected async Task> GetProviderOrganizations() + protected async Task> GetProviderUserOrganizations() { if (_providerUserOrganizations == null && UserId.HasValue) { @@ -529,4 +553,14 @@ public class CurrentContext : ICurrentContext return _providerUserOrganizations; } + + protected async Task> GetOrganizationProviderDetails() + { + if (_providerOrganizationProviderDetails == null && UserId.HasValue) + { + _providerOrganizationProviderDetails = await _providerOrganizationRepository.GetManyByUserAsync(UserId.Value); + } + + return _providerOrganizationProviderDetails; + } } diff --git a/src/Core/Context/ICurrentContext.cs b/src/Core/Context/ICurrentContext.cs index a78757d090..76a71e01a7 100644 --- a/src/Core/Context/ICurrentContext.cs +++ b/src/Core/Context/ICurrentContext.cs @@ -52,7 +52,10 @@ public interface ICurrentContext Task ManageUsers(Guid orgId); Task ManageScim(Guid orgId); Task ManageResetPassword(Guid orgId); - Task ManageBilling(Guid orgId); + Task ViewSubscription(Guid orgId); + Task EditSubscription(Guid orgId); + Task EditPaymentMethods(Guid orgId); + Task ViewBillingHistory(Guid orgId); Task ProviderUserForOrgAsync(Guid orgId); bool ProviderProviderAdmin(Guid providerId); bool ProviderUser(Guid providerId); diff --git a/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs b/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs index 32b7003700..1a6197e94a 100644 --- a/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs +++ b/src/Core/Models/Data/Organizations/OrganizationUsers/OrganizationUserOrganizationDetails.cs @@ -1,4 +1,6 @@ -namespace Bit.Core.Models.Data.Organizations.OrganizationUsers; +using Bit.Core.Enums.Provider; + +namespace Bit.Core.Models.Data.Organizations.OrganizationUsers; public class OrganizationUserOrganizationDetails { @@ -36,6 +38,7 @@ public class OrganizationUserOrganizationDetails public string PrivateKey { get; set; } public Guid? ProviderId { get; set; } public string ProviderName { get; set; } + public ProviderType? ProviderType { get; set; } public string FamilySponsorshipFriendlyName { get; set; } public string SsoConfig { get; set; } public DateTime? FamilySponsorshipLastSyncDate { get; set; } diff --git a/src/Core/Models/Data/Provider/ProviderOrganizationProviderDetails.cs b/src/Core/Models/Data/Provider/ProviderOrganizationProviderDetails.cs new file mode 100644 index 0000000000..8ae9559c86 --- /dev/null +++ b/src/Core/Models/Data/Provider/ProviderOrganizationProviderDetails.cs @@ -0,0 +1,12 @@ +using Bit.Core.Enums.Provider; + +namespace Bit.Core.Models.Data; + +public class ProviderOrganizationProviderDetails +{ + public Guid Id { get; set; } + public Guid ProviderId { get; set; } + public Guid OrganizationId { get; set; } + public string ProviderName { get; set; } + public ProviderType ProviderType { get; set; } +} diff --git a/src/Core/Repositories/IProviderOrganizationRepository.cs b/src/Core/Repositories/IProviderOrganizationRepository.cs index cc2d3d54ff..282bd1d326 100644 --- a/src/Core/Repositories/IProviderOrganizationRepository.cs +++ b/src/Core/Repositories/IProviderOrganizationRepository.cs @@ -8,4 +8,5 @@ public interface IProviderOrganizationRepository : IRepository> CreateManyAsync(IEnumerable providerOrganizations); Task> GetManyDetailsByProviderAsync(Guid providerId); Task GetByOrganizationId(Guid organizationId); + Task> GetManyByUserAsync(Guid userId); } diff --git a/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs b/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs index be0ea6db26..2ea12e9443 100644 --- a/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs +++ b/src/Infrastructure.Dapper/Repositories/ProviderOrganizationRepository.cs @@ -86,6 +86,19 @@ public class ProviderOrganizationRepository : Repository> GetManyByUserAsync(Guid userId) + { + using (var connection = new SqlConnection(ConnectionString)) + { + var results = await connection.QueryAsync( + "[dbo].[ProviderOrganizationProviderDetails_ReadByUserId]", + new { UserId = userId }, + commandType: CommandType.StoredProcedure); + + return results.ToList(); + } + } + private DataTable BuildProviderOrganizationsTable(SqlBulkCopy bulkCopy, IEnumerable providerOrganizations) { var po = providerOrganizations.FirstOrDefault(); diff --git a/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs b/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs index 7e7082dd99..7426aa43a5 100644 --- a/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs +++ b/src/Infrastructure.EntityFramework/Repositories/ProviderOrganizationRepository.cs @@ -56,4 +56,15 @@ public class ProviderOrganizationRepository : var dbContext = GetDatabaseContext(scope); return await GetDbSet(dbContext).Where(po => po.OrganizationId == organizationId).FirstOrDefaultAsync(); } + + public async Task> GetManyByUserAsync(Guid userId) + { + using (var scope = ServiceScopeFactory.CreateScope()) + { + var dbContext = GetDatabaseContext(scope); + var query = new ProviderOrganizationReadByUserIdQuery(userId); + var data = await query.Run(dbContext).ToListAsync(); + return data; + } + } } diff --git a/src/Infrastructure.EntityFramework/Repositories/Queries/OrganizationUserOrganizationDetailsViewQuery.cs b/src/Infrastructure.EntityFramework/Repositories/Queries/OrganizationUserOrganizationDetailsViewQuery.cs index aecad397b5..1a400a948b 100644 --- a/src/Infrastructure.EntityFramework/Repositories/Queries/OrganizationUserOrganizationDetailsViewQuery.cs +++ b/src/Infrastructure.EntityFramework/Repositories/Queries/OrganizationUserOrganizationDetailsViewQuery.cs @@ -55,6 +55,7 @@ public class OrganizationUserOrganizationDetailsViewQuery : IQuery +{ + private readonly Guid _userId; + + public ProviderOrganizationReadByUserIdQuery(Guid userId) + { + _userId = userId; + } + + public IQueryable Run(DatabaseContext dbContext) + { + var query = from po in dbContext.ProviderOrganizations + join ou in dbContext.OrganizationUsers + on po.OrganizationId equals ou.OrganizationId + join p in dbContext.Providers + on po.ProviderId equals p.Id + where ou.UserId == _userId + select new ProviderOrganizationProviderDetails + { + Id = po.Id, + OrganizationId = po.OrganizationId, + ProviderId = po.ProviderId, + ProviderName = p.Name, + ProviderType = p.Type + }; + return query; + } +} diff --git a/src/Notifications/NotificationsHub.cs b/src/Notifications/NotificationsHub.cs index 6d7a66b894..a86cf329c5 100644 --- a/src/Notifications/NotificationsHub.cs +++ b/src/Notifications/NotificationsHub.cs @@ -18,7 +18,7 @@ public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub public override async Task OnConnectedAsync() { - var currentContext = new CurrentContext(null); + var currentContext = new CurrentContext(null, null); await currentContext.BuildAsync(Context.User, _globalSettings); if (currentContext.Organizations != null) { @@ -33,7 +33,7 @@ public class NotificationsHub : Microsoft.AspNetCore.SignalR.Hub public override async Task OnDisconnectedAsync(Exception exception) { - var currentContext = new CurrentContext(null); + var currentContext = new CurrentContext(null, null); await currentContext.BuildAsync(Context.User, _globalSettings); if (currentContext.Organizations != null) { diff --git a/src/Sql/Sql.sqlproj b/src/Sql/Sql.sqlproj index 6ae3559106..249c2a8397 100644 --- a/src/Sql/Sql.sqlproj +++ b/src/Sql/Sql.sqlproj @@ -263,6 +263,7 @@ + diff --git a/src/Sql/dbo/Stored Procedures/ProviderOrganizationProviderDetails_ReadByUserId.sql b/src/Sql/dbo/Stored Procedures/ProviderOrganizationProviderDetails_ReadByUserId.sql new file mode 100644 index 0000000000..5441e6dceb --- /dev/null +++ b/src/Sql/dbo/Stored Procedures/ProviderOrganizationProviderDetails_ReadByUserId.sql @@ -0,0 +1,21 @@ +CREATE PROCEDURE [dbo].[ProviderOrganizationProviderDetails_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + +SELECT + PO.Id, + PO.OrganizationId, + PO.ProviderId, + P.Name as ProviderName, + P.[Type] as ProviderType +FROM + [dbo].[ProviderOrganizationView] PO +INNER JOIN + [dbo].[OrganizationUser] OU ON PO.OrganizationId = OU.OrganizationId +INNER JOIN + [dbo].[Provider] P ON PO.ProviderId = P.Id +WHERE + OU.UserId = @UserId +END diff --git a/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql b/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql index d475ca216e..3a7bc10edd 100644 --- a/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql +++ b/src/Sql/dbo/Views/OrganizationUserOrganizationDetailsView.sql @@ -35,6 +35,7 @@ SELECT OU.[Permissions], PO.[ProviderId], P.[Name] ProviderName, + P.[Type] ProviderType, SS.[Data] SsoConfig, OS.[FriendlyName] FamilySponsorshipFriendlyName, OS.[LastSyncDate] FamilySponsorshipLastSyncDate, diff --git a/test/Api.Test/Controllers/OrganizationsControllerTests.cs b/test/Api.Test/Controllers/OrganizationsControllerTests.cs index 0933a6ae53..a3d8192f33 100644 --- a/test/Api.Test/Controllers/OrganizationsControllerTests.cs +++ b/test/Api.Test/Controllers/OrganizationsControllerTests.cs @@ -24,6 +24,7 @@ public class OrganizationsControllerTests : IDisposable private readonly IOrganizationUserRepository _organizationUserRepository; private readonly IPaymentService _paymentService; private readonly IPolicyRepository _policyRepository; + private readonly IProviderRepository _providerRepository; private readonly ISsoConfigRepository _ssoConfigRepository; private readonly ISsoConfigService _ssoConfigService; private readonly IUserService _userService; @@ -46,6 +47,7 @@ public class OrganizationsControllerTests : IDisposable _organizationUserRepository = Substitute.For(); _paymentService = Substitute.For(); _policyRepository = Substitute.For(); + _providerRepository = Substitute.For(); _ssoConfigRepository = Substitute.For(); _ssoConfigService = Substitute.For(); _getOrganizationApiKeyQuery = Substitute.For(); @@ -57,7 +59,7 @@ public class OrganizationsControllerTests : IDisposable _updateOrganizationLicenseCommand = Substitute.For(); _sut = new OrganizationsController(_organizationRepository, _organizationUserRepository, - _policyRepository, _organizationService, _userService, _paymentService, _currentContext, + _policyRepository, _providerRepository, _organizationService, _userService, _paymentService, _currentContext, _ssoConfigRepository, _ssoConfigService, _getOrganizationApiKeyQuery, _rotateOrganizationApiKeyCommand, _createOrganizationApiKeyCommand, _organizationApiKeyRepository, _updateOrganizationLicenseCommand, _cloudGetOrganizationLicenseQuery, _globalSettings); diff --git a/util/Migrator/DbScripts/2023-03-08_OrganizationProviderType.sql b/util/Migrator/DbScripts/2023-03-08_OrganizationProviderType.sql new file mode 100644 index 0000000000..685b2d3b2f --- /dev/null +++ b/util/Migrator/DbScripts/2023-03-08_OrganizationProviderType.sql @@ -0,0 +1,82 @@ +CREATE OR ALTER VIEW [dbo].[OrganizationUserOrganizationDetailsView] +AS +SELECT + OU.[UserId], + OU.[OrganizationId], + O.[Name], + O.[Enabled], + O.[PlanType], + O.[UsePolicies], + O.[UseSso], + O.[UseKeyConnector], + O.[UseScim], + O.[UseGroups], + O.[UseDirectory], + O.[UseEvents], + O.[UseTotp], + O.[Use2fa], + O.[UseApi], + O.[UseResetPassword], + O.[SelfHost], + O.[UsersGetPremium], + O.[UseCustomPermissions], + O.[UseSecretsManager], + O.[Seats], + O.[MaxCollections], + O.[MaxStorageGb], + O.[Identifier], + OU.[Key], + OU.[ResetPasswordKey], + O.[PublicKey], + O.[PrivateKey], + OU.[Status], + OU.[Type], + SU.[ExternalId] SsoExternalId, + OU.[Permissions], + PO.[ProviderId], + P.[Name] ProviderName, + P.[Type] ProviderType, + SS.[Data] SsoConfig, + OS.[FriendlyName] FamilySponsorshipFriendlyName, + OS.[LastSyncDate] FamilySponsorshipLastSyncDate, + OS.[ToDelete] FamilySponsorshipToDelete, + OS.[ValidUntil] FamilySponsorshipValidUntil, + OU.[AccessSecretsManager] +FROM + [dbo].[OrganizationUser] OU +LEFT JOIN + [dbo].[Organization] O ON O.[Id] = OU.[OrganizationId] +LEFT JOIN + [dbo].[SsoUser] SU ON SU.[UserId] = OU.[UserId] AND SU.[OrganizationId] = OU.[OrganizationId] +LEFT JOIN + [dbo].[ProviderOrganization] PO ON PO.[OrganizationId] = O.[Id] +LEFT JOIN + [dbo].[Provider] P ON P.[Id] = PO.[ProviderId] +LEFT JOIN + [dbo].[SsoConfig] SS ON SS.[OrganizationId] = OU.[OrganizationId] +LEFT JOIN + [dbo].[OrganizationSponsorship] OS ON OS.[SponsoringOrganizationUserID] = OU.[Id] +GO + +CREATE OR ALTER PROCEDURE [dbo].[ProviderOrganizationProviderDetails_ReadByUserId] + @UserId UNIQUEIDENTIFIER +AS +BEGIN + SET NOCOUNT ON + +SELECT + PO.Id, + PO.OrganizationId, + PO.ProviderId, + P.Name as ProviderName, + P.[Type] as ProviderType +FROM + [dbo].[ProviderOrganizationView] PO +INNER JOIN + [dbo].[OrganizationUser] OU ON PO.OrganizationId = OU.OrganizationId +INNER JOIN + [dbo].[Provider] P ON PO.ProviderId = P.Id +WHERE + OU.UserId = @UserId +END +GO \ No newline at end of file