diff --git a/src/Admin/Models/OrganizationEditModel.cs b/src/Admin/Models/OrganizationEditModel.cs index 163136a406..fdc0819c65 100644 --- a/src/Admin/Models/OrganizationEditModel.cs +++ b/src/Admin/Models/OrganizationEditModel.cs @@ -33,6 +33,7 @@ namespace Bit.Admin.Models UseEvents = org.UseEvents; UseTotp = org.UseTotp; Use2fa = org.Use2fa; + UseApi = org.UseApi; SelfHost = org.SelfHost; UsersGetPremium = org.UsersGetPremium; MaxStorageGb = org.MaxStorageGb; @@ -76,6 +77,8 @@ namespace Bit.Admin.Models public bool UseTotp { get; set; } [Display(Name = "2FA")] public bool Use2fa { get; set; } + [Display(Name = "API")] + public bool UseApi{ get; set; } [Display(Name = "Self Host")] public bool SelfHost { get; set; } [Display(Name = "Users Get Premium")] @@ -109,6 +112,7 @@ namespace Bit.Admin.Models existingOrganization.UseEvents = UseEvents; existingOrganization.UseTotp = UseTotp; existingOrganization.Use2fa = Use2fa; + existingOrganization.UseApi = UseApi; existingOrganization.SelfHost = SelfHost; existingOrganization.UsersGetPremium = UsersGetPremium; existingOrganization.MaxStorageGb = MaxStorageGb; diff --git a/src/Admin/Views/Organizations/Edit.cshtml b/src/Admin/Views/Organizations/Edit.cshtml index d64a68f0e6..988d13aa75 100644 --- a/src/Admin/Views/Organizations/Edit.cshtml +++ b/src/Admin/Views/Organizations/Edit.cshtml @@ -27,6 +27,7 @@ document.getElementById('@(nameof(Model.UsersGetPremium))').checked = true; document.getElementById('@(nameof(Model.UseTotp))').checked = true; document.getElementById('@(nameof(Model.Use2fa))').checked = true; + document.getElementById('@(nameof(Model.UseApi))').checked = true; document.getElementById('@(nameof(Model.SelfHost))').checked = true; // Licensing document.getElementById('@(nameof(Model.LicenseKey))').value = '@Model.RandomLicenseKey'; @@ -151,6 +152,10 @@ +
+ + +
diff --git a/src/Core/IdentityServer/ClientStore.cs b/src/Core/IdentityServer/ClientStore.cs index 54abf460c3..5b7895ccfa 100644 --- a/src/Core/IdentityServer/ClientStore.cs +++ b/src/Core/IdentityServer/ClientStore.cs @@ -87,11 +87,11 @@ namespace Bit.Core.IdentityServer { ClientId = $"organization.{org.Id}", RequireClientSecret = true, - ClientSecrets = { new Secret("secret".Sha256()) }, // TODO: org.ApiKey + ClientSecrets = { new Secret(org.ApiKey.Sha256()) }, AllowedScopes = new string[] { "api.organization" }, AllowedGrantTypes = GrantTypes.ClientCredentials, AccessTokenLifetime = 3600 * 1, - Enabled = org.Enabled, // TODO: && org.UseApi + Enabled = org.Enabled && org.UseApi, Claims = new List { new Claim(JwtClaimTypes.Subject, org.Id.ToString()) } }; } diff --git a/src/Core/Models/Api/Response/OrganizationResponseModel.cs b/src/Core/Models/Api/Response/OrganizationResponseModel.cs index 7dbac7ee55..a77c9b972c 100644 --- a/src/Core/Models/Api/Response/OrganizationResponseModel.cs +++ b/src/Core/Models/Api/Response/OrganizationResponseModel.cs @@ -35,6 +35,7 @@ namespace Bit.Core.Models.Api UseEvents = organization.UseEvents; UseTotp = organization.UseTotp; Use2fa = organization.Use2fa; + UseApi = organization.UseApi; UsersGetPremium = organization.UsersGetPremium; SelfHost = organization.SelfHost; } @@ -58,6 +59,7 @@ namespace Bit.Core.Models.Api public bool UseEvents { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi { get; set; } public bool UsersGetPremium { get; set; } public bool SelfHost { get; set; } } diff --git a/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs b/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs index fb4d19e41d..78ef57f009 100644 --- a/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs +++ b/src/Core/Models/Api/Response/ProfileOrganizationResponseModel.cs @@ -15,6 +15,7 @@ namespace Bit.Core.Models.Api UseEvents = organization.UseEvents; UseTotp = organization.UseTotp; Use2fa = organization.Use2fa; + UseApi = organization.UseApi; UsersGetPremium = organization.UsersGetPremium; SelfHost = organization.SelfHost; Seats = organization.Seats; @@ -33,6 +34,7 @@ namespace Bit.Core.Models.Api public bool UseEvents { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi { get; set; } public bool UsersGetPremium { get; set; } public bool SelfHost { get; set; } public int Seats { get; set; } diff --git a/src/Core/Models/Business/OrganizationLicense.cs b/src/Core/Models/Business/OrganizationLicense.cs index 300146b4e0..a25d75a5e4 100644 --- a/src/Core/Models/Business/OrganizationLicense.cs +++ b/src/Core/Models/Business/OrganizationLicense.cs @@ -19,7 +19,7 @@ namespace Bit.Core.Models.Business public OrganizationLicense(Organization org, SubscriptionInfo subscriptionInfo, Guid installationId, ILicensingService licenseService) { - Version = 4; + Version = 4; // TODO: Version 5 bump LicenseKey = org.LicenseKey; InstallationId = installationId; Id = org.Id; @@ -36,6 +36,7 @@ namespace Bit.Core.Models.Business UseDirectory = org.UseDirectory; UseTotp = org.UseTotp; Use2fa = org.Use2fa; + UseApi = org.UseApi; MaxStorageGb = org.MaxStorageGb; SelfHost = org.SelfHost; UsersGetPremium = org.UsersGetPremium; @@ -102,6 +103,7 @@ namespace Bit.Core.Models.Business public bool UseDirectory { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi { get; set; } public short? MaxStorageGb { get; set; } public bool SelfHost { get; set; } public bool UsersGetPremium { get; set; } @@ -118,7 +120,7 @@ namespace Bit.Core.Models.Business public byte[] GetDataBytes(bool forHash = false) { string data = null; - if(Version >= 1 && Version <= 4) + if(Version >= 1 && Version <= 5) { var props = typeof(OrganizationLicense) .GetProperties(BindingFlags.Public | BindingFlags.Instance) @@ -131,6 +133,8 @@ namespace Bit.Core.Models.Business (Version >= 3 || !p.Name.Equals(nameof(UseEvents))) && // Use2fa was added in Version 4 (Version >= 4 || !p.Name.Equals(nameof(Use2fa))) && + // UseApi was added in Version 5 + (Version >= 5 || !p.Name.Equals(nameof(UseApi))) && ( !forHash || ( @@ -167,7 +171,7 @@ namespace Bit.Core.Models.Business return false; } - if(Version >= 1 && Version <= 4) + if(Version >= 1 && Version <= 5) { return InstallationId == globalSettings.Installation.Id && SelfHost; } @@ -184,7 +188,7 @@ namespace Bit.Core.Models.Business return false; } - if(Version >= 1 && Version <= 4) + if(Version >= 1 && Version <= 5) { var valid = globalSettings.Installation.Id == InstallationId && @@ -214,6 +218,11 @@ namespace Bit.Core.Models.Business valid = organization.Use2fa == Use2fa; } + if(valid && Version >= 5) + { + valid = organization.UseApi == UseApi; + } + return valid; } else diff --git a/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs b/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs index 48836a9693..6c39bfd6a1 100644 --- a/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs +++ b/src/Core/Models/Data/OrganizationUserOrganizationDetails.cs @@ -12,6 +12,7 @@ namespace Bit.Core.Models.Data public bool UseEvents { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi{ get; set; } public bool SelfHost { get; set; } public bool UsersGetPremium { get; set; } public int Seats { get; set; } diff --git a/src/Core/Models/StaticStore/Plan.cs b/src/Core/Models/StaticStore/Plan.cs index b11a9f6b26..9f5b5e513c 100644 --- a/src/Core/Models/StaticStore/Plan.cs +++ b/src/Core/Models/StaticStore/Plan.cs @@ -19,6 +19,7 @@ namespace Bit.Core.Models.StaticStore public bool UseEvents { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi { get; set; } public short? MaxStorageGb { get; set; } public decimal BasePrice { get; set; } public decimal SeatPrice { get; set; } diff --git a/src/Core/Models/Table/Organization.cs b/src/Core/Models/Table/Organization.cs index f9aa28229f..fa90a9e47b 100644 --- a/src/Core/Models/Table/Organization.cs +++ b/src/Core/Models/Table/Organization.cs @@ -1,8 +1,6 @@ using System; using Bit.Core.Utilities; using Bit.Core.Enums; -using Bit.Core.Services; -using Bit.Core.Exceptions; using System.Collections.Generic; using Newtonsoft.Json; using System.Linq; @@ -31,6 +29,7 @@ namespace Bit.Core.Models.Table public bool UseEvents { get; set; } public bool UseTotp { get; set; } public bool Use2fa { get; set; } + public bool UseApi { get; set; } public bool SelfHost { get; set; } public bool UsersGetPremium { get; set; } public long? Storage { get; set; } @@ -40,6 +39,7 @@ namespace Bit.Core.Models.Table public string GatewaySubscriptionId { get; set; } public bool Enabled { get; set; } = true; public string LicenseKey { get; set; } + public string ApiKey { get; set; } public string TwoFactorProviders { get; set; } public DateTime? ExpirationDate { get; set; } public DateTime CreationDate { get; internal set; } = DateTime.UtcNow; diff --git a/src/Core/Services/Implementations/OrganizationService.cs b/src/Core/Services/Implementations/OrganizationService.cs index e8d21ded55..ac65ded3ee 100644 --- a/src/Core/Services/Implementations/OrganizationService.cs +++ b/src/Core/Services/Implementations/OrganizationService.cs @@ -513,12 +513,14 @@ namespace Bit.Core.Services UseDirectory = plan.UseDirectory, UseTotp = plan.UseTotp, Use2fa = plan.Use2fa, + UseApi = plan.UseApi, SelfHost = plan.SelfHost, UsersGetPremium = plan.UsersGetPremium || signup.PremiumAccessAddon, Plan = plan.Name, Gateway = null, Enabled = true, LicenseKey = CoreHelpers.SecureRandomString(20), + ApiKey = CoreHelpers.SecureRandomString(30), CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; @@ -582,6 +584,7 @@ namespace Bit.Core.Services UseEvents = license.UseEvents, UseTotp = license.UseTotp, Use2fa = license.Use2fa, + UseApi = license.UseApi, Plan = license.Plan, SelfHost = license.SelfHost, UsersGetPremium = license.UsersGetPremium, @@ -591,6 +594,7 @@ namespace Bit.Core.Services Enabled = license.Enabled, ExpirationDate = license.Expires, LicenseKey = license.LicenseKey, + ApiKey = CoreHelpers.SecureRandomString(30), CreationDate = DateTime.UtcNow, RevisionDate = DateTime.UtcNow }; @@ -740,6 +744,7 @@ namespace Bit.Core.Services organization.UseEvents = license.UseEvents; organization.UseTotp = license.UseTotp; organization.Use2fa = license.Use2fa; + organization.UseApi = license.UseApi; organization.SelfHost = license.SelfHost; organization.UsersGetPremium = license.UsersGetPremium; organization.Plan = license.Plan; diff --git a/src/Core/Utilities/StaticStore.cs b/src/Core/Utilities/StaticStore.cs index 02ff300f81..36b9bebae8 100644 --- a/src/Core/Utilities/StaticStore.cs +++ b/src/Core/Utilities/StaticStore.cs @@ -169,6 +169,7 @@ namespace Bit.Core.Utilities UseEvents = true, UseTotp = true, Use2fa = true, + UseApi = true, MaxStorageGb = 1, SelfHost = true, UsersGetPremium = true @@ -191,6 +192,7 @@ namespace Bit.Core.Utilities UseEvents = true, UseTotp = true, Use2fa = true, + UseApi = true, MaxStorageGb = 1, SelfHost = true, UsersGetPremium = true