From 1beb5dc5c0e834f7700dc509ffc8cbdb06ac3c23 Mon Sep 17 00:00:00 2001 From: Todd Martin <106564991+trmartin4@users.noreply.github.com> Date: Tue, 1 Apr 2025 10:06:30 -0400 Subject: [PATCH 1/3] Separate desktop and CLI for ClientType checks (#5441) --- src/Core/Enums/ClientType.cs | 4 +++- src/Core/Utilities/DeviceTypes.cs | 7 ++++++- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Core/Enums/ClientType.cs b/src/Core/Enums/ClientType.cs index 4e95584e8d..0e0cfe4b26 100644 --- a/src/Core/Enums/ClientType.cs +++ b/src/Core/Enums/ClientType.cs @@ -14,5 +14,7 @@ public enum ClientType : byte [Display(Name = "Desktop App")] Desktop = 3, [Display(Name = "Mobile App")] - Mobile = 4 + Mobile = 4, + [Display(Name = "CLI")] + Cli = 5 } diff --git a/src/Core/Utilities/DeviceTypes.cs b/src/Core/Utilities/DeviceTypes.cs index a1cca75757..f42d1d9a2b 100644 --- a/src/Core/Utilities/DeviceTypes.cs +++ b/src/Core/Utilities/DeviceTypes.cs @@ -16,7 +16,11 @@ public static class DeviceTypes DeviceType.LinuxDesktop, DeviceType.MacOsDesktop, DeviceType.WindowsDesktop, - DeviceType.UWP, + DeviceType.UWP + ]; + + public static IReadOnlyCollection CliTypes { get; } = + [ DeviceType.WindowsCLI, DeviceType.MacOsCLI, DeviceType.LinuxCLI @@ -50,6 +54,7 @@ public static class DeviceTypes { not null when MobileTypes.Contains(deviceType.Value) => ClientType.Mobile, not null when DesktopTypes.Contains(deviceType.Value) => ClientType.Desktop, + not null when CliTypes.Contains(deviceType.Value) => ClientType.Cli, not null when BrowserExtensionTypes.Contains(deviceType.Value) => ClientType.Browser, not null when BrowserTypes.Contains(deviceType.Value) => ClientType.Web, _ => ClientType.All From fd781415c4d013a3f3ea99b801a6c1676e6cc4b7 Mon Sep 17 00:00:00 2001 From: Vijay Oommen Date: Tue, 1 Apr 2025 09:19:42 -0500 Subject: [PATCH 2/3] [PM-19222] Include UseRiskInsights in license file (#5528) --- .../Services/Implementations/OrganizationService.cs | 1 + src/Core/Models/Business/OrganizationLicense.cs | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/Core/AdminConsole/Services/Implementations/OrganizationService.cs b/src/Core/AdminConsole/Services/Implementations/OrganizationService.cs index 64bd434327..32fcbb0608 100644 --- a/src/Core/AdminConsole/Services/Implementations/OrganizationService.cs +++ b/src/Core/AdminConsole/Services/Implementations/OrganizationService.cs @@ -575,6 +575,7 @@ public class OrganizationService : IOrganizationService UseSecretsManager = license.UseSecretsManager, SmSeats = license.SmSeats, SmServiceAccounts = license.SmServiceAccounts, + UseRiskInsights = license.UseRiskInsights, }; var result = await SignUpAsync(organization, owner.Id, ownerKey, collectionName, false); diff --git a/src/Core/Models/Business/OrganizationLicense.cs b/src/Core/Models/Business/OrganizationLicense.cs index d280a81023..a23e18e2b7 100644 --- a/src/Core/Models/Business/OrganizationLicense.cs +++ b/src/Core/Models/Business/OrganizationLicense.cs @@ -55,6 +55,7 @@ public class OrganizationLicense : ILicense UseSecretsManager = org.UseSecretsManager; SmSeats = org.SmSeats; SmServiceAccounts = org.SmServiceAccounts; + UseRiskInsights = org.UseRiskInsights; // Deprecated. Left for backwards compatibility with old license versions. LimitCollectionCreationDeletion = org.LimitCollectionCreation || org.LimitCollectionDeletion; @@ -143,6 +144,7 @@ public class OrganizationLicense : ILicense public bool UseSecretsManager { get; set; } public int? SmSeats { get; set; } public int? SmServiceAccounts { get; set; } + public bool UseRiskInsights { get; set; } // Deprecated. Left for backwards compatibility with old license versions. public bool LimitCollectionCreationDeletion { get; set; } = true; @@ -218,7 +220,8 @@ public class OrganizationLicense : ILicense !p.Name.Equals(nameof(Issued)) && !p.Name.Equals(nameof(Refresh)) ) - )) + ) && + !p.Name.Equals(nameof(UseRiskInsights))) .OrderBy(p => p.Name) .Select(p => $"{p.Name}:{Utilities.CoreHelpers.FormatLicenseSignatureValue(p.GetValue(this, null))}") .Aggregate((c, n) => $"{c}|{n}"); From f90bcd44ded104af16688f801ee70a6415097d9b Mon Sep 17 00:00:00 2001 From: Jimmy Vo Date: Tue, 1 Apr 2025 10:28:57 -0400 Subject: [PATCH 3/3] [PM-19575] Allow enabling Single Org policy when the organization has claimed domains. (#5565) --- .../Response/Helpers/PolicyDetailResponses.cs | 12 +++++++++++- .../Helpers/PolicyDetailResponsesTests.cs | 15 ++++++++++----- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/src/Api/AdminConsole/Models/Response/Helpers/PolicyDetailResponses.cs b/src/Api/AdminConsole/Models/Response/Helpers/PolicyDetailResponses.cs index 14b9642f61..dded6a4c89 100644 --- a/src/Api/AdminConsole/Models/Response/Helpers/PolicyDetailResponses.cs +++ b/src/Api/AdminConsole/Models/Response/Helpers/PolicyDetailResponses.cs @@ -13,7 +13,17 @@ public static class PolicyDetailResponses { throw new ArgumentException($"'{nameof(policy)}' must be of type '{nameof(PolicyType.SingleOrg)}'.", nameof(policy)); } + return new PolicyDetailResponseModel(policy, await CanToggleState()); - return new PolicyDetailResponseModel(policy, !await hasVerifiedDomainsQuery.HasVerifiedDomainsAsync(policy.OrganizationId)); + async Task CanToggleState() + { + if (!await hasVerifiedDomainsQuery.HasVerifiedDomainsAsync(policy.OrganizationId)) + { + return true; + } + + return !policy.Enabled; + } } + } diff --git a/test/Api.Test/AdminConsole/Models/Response/Helpers/PolicyDetailResponsesTests.cs b/test/Api.Test/AdminConsole/Models/Response/Helpers/PolicyDetailResponsesTests.cs index c380185a70..9b863091db 100644 --- a/test/Api.Test/AdminConsole/Models/Response/Helpers/PolicyDetailResponsesTests.cs +++ b/test/Api.Test/AdminConsole/Models/Response/Helpers/PolicyDetailResponsesTests.cs @@ -10,14 +10,19 @@ namespace Bit.Api.Test.AdminConsole.Models.Response.Helpers; public class PolicyDetailResponsesTests { - [Fact] - public async Task GetSingleOrgPolicyDetailResponseAsync_GivenPolicyEntity_WhenIsSingleOrgTypeAndHasVerifiedDomains_ThenShouldNotBeAbleToToggle() + [Theory] + [InlineData(true, false)] + [InlineData(false, true)] + public async Task GetSingleOrgPolicyDetailResponseAsync_WhenIsSingleOrgTypeAndHasVerifiedDomains_ShouldReturnExpectedToggleState( + bool policyEnabled, + bool expectedCanToggle) { var fixture = new Fixture(); var policy = fixture.Build() .Without(p => p.Data) .With(p => p.Type, PolicyType.SingleOrg) + .With(p => p.Enabled, policyEnabled) .Create(); var querySub = Substitute.For(); @@ -26,11 +31,11 @@ public class PolicyDetailResponsesTests var result = await policy.GetSingleOrgPolicyDetailResponseAsync(querySub); - Assert.False(result.CanToggleState); + Assert.Equal(expectedCanToggle, result.CanToggleState); } [Fact] - public async Task GetSingleOrgPolicyDetailResponseAsync_GivenPolicyEntity_WhenIsNotSingleOrgType_ThenShouldThrowArgumentException() + public async Task GetSingleOrgPolicyDetailResponseAsync_WhenIsNotSingleOrgType_ThenShouldThrowArgumentException() { var fixture = new Fixture(); @@ -49,7 +54,7 @@ public class PolicyDetailResponsesTests } [Fact] - public async Task GetSingleOrgPolicyDetailResponseAsync_GivenPolicyEntity_WhenIsSingleOrgTypeAndDoesNotHaveVerifiedDomains_ThenShouldBeAbleToToggle() + public async Task GetSingleOrgPolicyDetailResponseAsync_WhenIsSingleOrgTypeAndDoesNotHaveVerifiedDomains_ThenShouldBeAbleToToggle() { var fixture = new Fixture();